2010-10-13 23 views
23

Estoy trabajando con Android, tratando de hacer que mi aplicación AudioTrack reproduzca un archivo .wav de Windows (Tada.wav). Francamente, no debería ser tan difícil, pero estoy escuchando muchas cosas extrañas. El archivo se guarda en la tarjeta mini SD de mi teléfono y leer el contenido no parece ser un problema, pero cuando reproduzco el archivo (con los parámetros solo estoy BIEN SEGURO), recibo unos segundos de ruido blanco antes de que el sonido parezca resolverse en algo que simplemente puede ser correcto.Uso de AudioTrack en Android para reproducir un archivo WAV

he grabado con éxito y jugado mi propia voz de nuevo en el teléfono - He creado un archivo .pcm de acuerdo con las instrucciones de este ejemplo:

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

(sin el enmascaramiento hacia atrás) ..

¿Alguien tiene alguna sugerencia o conocimiento de un ejemplo en la web para reproducir un archivo .wav en un Android?

Gracias, R.

Respuesta

26

me encontré con la respuesta (francamente, tratando &^@ No pensé que iba a funcionar!), En caso de que alguien es interesados ​​... en mi código original (que se deriva del ejemplo en el enlace en el post original), los datos se leen desde el archivo de esta manera:

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 

en esta versión, la música [] es array de SHORTS. Entonces, el método readShort() parece tener sentido aquí, ya que los datos son PCM de 16 bits ... Sin embargo, en Android parece ser el problema. Cambié ese código a lo siguiente:

 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 

En esta versión, la música [] es una matriz de BYTES. Todavía le digo a AudioTrack que son datos PCM de 16 bits, y mi Android no parece tener problemas para escribir una matriz de bytes en un AudioTrack configurado de esta manera ... De todos modos, finalmente suena bien, así que si alguien si no quiere reproducir sonidos de Windows en su Android, por alguna razón, esa es la solución. Ah, Endianness ......

R.

+0

Esta debería ser la respuesta aceptada, ya que responde la pregunta. ;) – gary

+0

Podría haber jurado que dejé un "Gracias, Gary" aquí mismo, pero ahora no está aquí ... ¡Gracias, Gary! – Rich

+1

Este [artículo] (http://computermusicblog.com/blog/2008/08/29/reading-and-writing-wav-files-in-java) parece estar sobre el tema: diferencias entre utilizar el byte y el byte de Java cuando se trata de leer el formato WAV. – Vanja

5

¿Está omitiendo los primeros 44 bytes del archivo antes de volcar el resto de los datos del archivo en el búfer? Los primeros 44 bytes son el encabezado WAVE y suenan como ruido aleatorio si intentas reproducirlos.

Además, ¿está seguro de que está creando el AudioTrack con las mismas propiedades que el WAVE que está intentando reproducir (frecuencia de muestreo, velocidad de bits, cantidad de canales, etc.)? Ventanas realmente hace un buen trabajo de dar esta información a usted en la página Propiedades de archivo: alt text

+0

He intentado todas las combinaciones de omitir el encabezado y no es lo que se me ocurre, sin mucha suerte. El sonido del ruido blanco dura MUCHO más de 44 picaduras. Tada.wav es un archivo de 168 kByte, por lo que "jugar" el encabezado apenas se nota, ¿verdad? – Rich

+1

Correcto, el encabezado del archivo generaría basura por un tiempo muy corto. ¿Estás seguro de que estás creando el AudioTrack con las mismas propiedades que el WAVE que estás intentando reproducir (frecuencia de muestreo, velocidad de bits, cantidad de canales, etc.)? –

+0

Tengo un editor hexadecimal y estoy seguro de que obtendré los números del encabezado correctamente. Estoy sorprendido de que no haya podido encontrar un analizador de archivos wav de algún tipo en Internet. Estoy perplejo, Y el reproductor de Windows Media ciertamente puede reproducir el archivo ... – Rich

2

Como dijo por Aaron C, usted tiene que saltar inicial de 44 bytes o (como yo prefiero) leer primeros 44 bytes que son la cabecera WAVE. De esta forma sabrá cuántos canales, bits por muestra, longitud, etc. ... contiene la WAVE.

Here puede encontrar una buena implementación de un analizador/escritor de encabezado WAVE.

5

Encontré muchas respuestas largas a esta pregunta.Mi solución final, que da todo el cortar y pegar no es mía, se reduce 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; 
} 

interrumpida es simplemente un "verdadero" enviado de vuelta como una señal para restablecer el botón de pausa/reproducción. Y en el inicializador de la clase:

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

El contexto es simplemente "este" de la actividad de llamadas. Puede usar un FileInputStream en la tarjeta sd, etc. Mis archivos están en res/raw

+0

Gracias por esto, de todas las respuestas que probé ésta dio el mejor resultado. Aunque todavía recibo un pequeño clic de audio cuando comienza la pista ... – methodMan

1

No perpetúe el terrible código de análisis. El análisis WAV es trivial para implementar http://soundfile.sapp.org/doc/WaveFormat/ y usted se agradecerá al poder analizar cosas tales como la velocidad de muestreo, la profundidad de bits y la cantidad de canales.

También x86 y ARM (al menos de manera predeterminada) son ambos endian pequeños, por lo que los archivos WAV nativos pueden estar bien sin ningún tipo de mezcla.

+0

Su respuesta sería más útil si especificara qué código de análisis cree que es terrible y por qué. – arlomedia

Cuestiones relacionadas