2010-10-13 8 views
23

Sto lavorando con Android, cercando di fare in modo che l'applicazione AudioTrack riproduca un file .wav di Windows (Tada.wav). Francamente, non dovrebbe essere così difficile, ma sto ascoltando un sacco di cose strane. Il file viene salvato sulla mini scheda SD del mio telefono e la lettura dei contenuti non sembra essere un problema, ma quando suono il file (con parametri I'm PRETTY SURE sono giusti), ottengo qualche secondo di rumore bianco prima che il suono sembra risolversi in qualcosa che potrebbe essere giusto.Utilizzo di AudioTrack in Android per riprodurre un file WAV

ho registrato con successo e ha giocato la mia voce di nuovo al telefono - ho creato un file .pcm secondo le istruzioni in questo esempio:

http://emeadev.blogspot.com/2009/09/raw-audio-manipulation-in-android.html

(senza il mascheramento all'indietro) ..

Qualcuno ha qualche suggerimento o consapevolezza di un esempio sul web per la riproduzione di un file .wav su un Android ??

Grazie, R.

risposta

26

mi sono imbattuto sulla risposta (francamente, provando &^@ Non pensavo che avrebbe funzionato!), Nel caso in cui nessuno è interessati ... nel mio codice originale (che deriva dall'esempio nel link nel post originale), i dati vengono letti dal file in questo modo:

InputStream    is = new FileInputStream  (file); 
    BufferedInputStream  bis = new BufferedInputStream (is, 8000); 
    DataInputStream   dis = new DataInputStream  (bis);  // Create a DataInputStream to read the audio data from the saved file 

    int i = 0;               // Read the file into the "music" array 
    while (dis.available() > 0) 
    { 
     music[i] = dis.readShort();          // This assignment does not reverse the order 
     i++; 
    } 

    dis.close();              // Close the input stream 

in questa versione, la musica [] è array di CORTI. Quindi, il metodo readShort() sembra avere un senso qui, dato che i dati sono PCM a 16 bit ... Tuttavia, su Android questo sembra essere il problema. Ho modificato il codice al seguente:

 music=new byte[(int) file.length()];//size & length of the file 
    InputStream    is = new FileInputStream  (file); 
    BufferedInputStream  bis = new BufferedInputStream (is, 8000); 
    DataInputStream   dis = new DataInputStream  (bis);  // Create a DataInputStream to read the audio data from the saved file 

    int i = 0;               // Read the file into the "music" array 
    while (dis.available() > 0) 
    { 
     music[i] = dis.readByte();          // This assignment does not reverse the order 
     i++; 
    } 

    dis.close();              // Close the input stream 

In questa versione, la musica [] è una matrice di BYTES. Sto ancora dicendo ad AudioTrack che sono dati PCM a 16 bit, e il mio Android non sembra avere problemi a scrivere una matrice di byte in un AudioTrack così configurato ... Comunque, finalmente suona bene, quindi se qualcuno altrimenti vuole riprodurre i suoni di Windows sul loro Android, per qualche ragione, questa è la soluzione. Ah, Endianness ......

R.

+0

Questa dovrebbe essere la risposta accettata, poiché risponde alla domanda. ;) – gary

+0

Potrei giurare che ho lasciato un "Grazie, Gary" proprio qui, ma non è qui ora ... Grazie, Gary !! – Rich

+1

Questo [articolo] (http://computermusicblog.com/blog/2008/08/29/reading-and-writing-wav-files-in-java) sembra essere sull'argomento: differenze tra l'utilizzo di short e byte di Java quando si tratta di leggere il formato WAV. – Vanja

5

Stai saltando i primi 44 byte del file prima di eseguire il dump il resto dei dati del file nel buffer? I primi 44 byte sono l'intestazione WAVE e suonerebbero come un rumore casuale se si provasse a riprodurli.

Inoltre, si è sicuri di creare AudioTrack con le stesse proprietà dell'AVE che si sta tentando di riprodurre (frequenza di campionamento, velocità in bit, numero di canali, ecc.)? Di Windows in realtà fa un buon lavoro di dare queste informazioni a voi nella pagina Proprietà file: alt text

+0

Ho provato ogni combinazione di saltare l'intestazione e non quello a cui riesco a pensare - senza molta fortuna. Il suono del rumore bianco dura MOLTO più di 44 morsi. Tada.wav è un file di 168 kByte, quindi "suonare" l'intestazione dovrebbe essere a malapena visibile, giusto? – Rich

+1

Corretto, l'intestazione del file genererebbe spazzatura per un tempo molto breve. Sei sicuro di creare AudioTrack con le stesse proprietà dell'AVE che stai cercando di riprodurre (frequenza di campionamento, velocità in bit, numero di canali, ecc.)? –

+0

Possiedo un editor esadecimale e sono sicuro che riterrò correttamente i numeri dall'intestazione. Sono abbastanza sorpreso di non essere stato in grado di trovare un analizzatore di file wav di qualche tipo su Internet. Sono sconcertato, e Windows Media Player può certamente riprodurre il file ... – Rich

2

Come detto da Aaron C, si deve saltare iniziale 44 byte o (come io preferisco) leggere primi 44 byte che sono l'intestazione WAVE. In questo modo puoi sapere quanti canali, bit per campione, lunghezza, ecc ... contiene WAVE.

Here è possibile trovare una buona implementazione di un parser/scrittore di intestazione WAVE.

5

Ho trovato molte risposte lunghe a questa domanda.La mia soluzione finale, che dato tutto il taglia e incolla non è certo il mio, si riduce a:

public boolean play() { 

    int i = 0; 
    byte[] music = null; 
    InputStream is = mContext.getResources().openRawResource(R.raw.noise); 

    at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, 
     AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, 
     minBufferSize, AudioTrack.MODE_STREAM); 

    try{ 
     music = new byte[512]; 
     at.play(); 

     while((i = is.read(music)) != -1) 
      at.write(music, 0, i); 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    at.stop(); 
    at.release(); 
    return STOPPED; 
} 

FERMO è solo un "vero" rimandato come un segnale per ripristinare il pulsante di pausa/play. E nel inizializzatore classe:

public Mp3Track(Context context) { 
    mContext = context; 
    minBufferSize = AudioTrack.getMinBufferSize(44100, 
     AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); 
} 

contesto è solo "questo" dall'attività di chiamata. È possibile utilizzare un FileInputStream sulla sdcard, ecc. I miei file sono in res/raw

+0

Grazie per questo, tra tutte le risposte che ho provato questo ha dato il miglior risultato. Anche se ho ancora un piccolo click audio quando inizia la traccia .... – methodMan

1

Si prega di non perpetuare il codice di parsing terribile. L'analisi WAV è banale per implementare http://soundfile.sapp.org/doc/WaveFormat/ e ti ringrazierai di essere in grado di analizzare cose come la frequenza di campionamento, la profondità di bit e il numero di canali.

Anche x86 e ARM (almeno per impostazione predefinita) sono entrambi little endian, quindi i file WAV nativi-endian dovrebbero essere perfetti senza alcun shuffling.

+0

La tua risposta sarebbe più utile se hai specificato quale codice di analisi pensi sia terribile e perché. – arlomedia