2010-04-25 14 views
8

Estoy intentando portar una aplicación que reproduce archivos de música de chiptunes (NSF, SPC, etc.) de Java SE a Android. La API de Android parece carecer de las clases multimedia javax que esta aplicación utiliza para producir audio PCM en bruto. El análogo más cercano que he encontrado en la API es AudioTrack, así que he estado luchando con eso.Dificultad para portar código de salida de PCM sin procesar de Java a API de AudioTrack de Android

Sin embargo, cuando intento ejecutar uno de mis archivos de música de muestra a través de mi puerto en progreso, todo lo que recupero es estático. Mi sospecha es que es el AudioTrack que he configurado el que tiene la culpa. He intentado varios constructores diferentes, pero al final todo acaba con salidas estáticas.

La configuración DataLine en el código original es algo así como:

AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
       44100, 16, 2, 4, 44100, true); 
DataLine.Info lineInfo = new DataLine.Info(SourceDataLine.class, audioFormat); 
DataLine line = (SourceDataLine)AudioSystem.getLine(lineInfo); 

El constructor que estoy usando en este momento es:

AudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
     44100, 
     AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
     AudioFormat.ENCODING_PCM_16BIT, 
     AudioTrack.getMinBufferSize(44100, 
       AudioFormat.CHANNEL_CONFIGURATION_STEREO, 
       AudioFormat.ENCODING_PCM_16BIT), 
     AudioTrack.MODE_STREAM); 

he reemplazado constantes y variables en las que por lo que tener sentido lo más concisamente posible, pero mi pregunta básica es si hay algún problema obvio en las suposiciones que hice al pasar de un formato a otro.

+0

Aunque está recibiendo estática, ¿ha revisado para ver si la longitud de la pista es correcta? – nvuono

+0

Los archivos de música en cuestión realmente no tienen una longitud de pista definitiva. Es decir, están en forma de código para un DSP que simplemente continúa reproduciéndose hasta que se les dice que se detengan. – alexanderfb

Respuesta

7

Así que tuve un poco de tiempo para ver esto más lejos hoy, y creo que lo he descifrado. La declaración AudioFormat en el primer ejemplo de código anterior tiene el parámetro big endian establecido en "true", pero el AudioTrack de Android espera que los datos PCM estén en formato little endian.

Así que escribió un pequeño bucle rápida de poner a prueba mi corazonada de este modo:

for(int i = 0; i + LEN_PCM_SAMPLE_BYTES < LEN_PCM_BUFFER; i += LEN_PCM_SAMPLE_BYTES) { 
    // Really rude endian conversion. 
    byte bytTemp = a_bytBuffer[i]; 
    a_bytBuffer[i] = a_bytBuffer[i + 1]; 
    a_bytBuffer[i + 1] = bytTemp; 
} 

Básicamente, este bucle voltea los bytes de cada muestra (16 bits) en el tampón. Esto funciona muy bien, excepto que es un poco entrecortado ya que es terriblemente ineficiente. Intenté usar un ByteBuffer pero eso no parece invertir los bytes en las muestras individuales.

Definiré algo aún mejor en el futuro, pero el problema básico aquí está resuelto. ¡Espero que alguien más lo encuentre útil!

+0

¿Pudiste encontrar algo para el picor? – StackOverflowed

Cuestiones relacionadas