Android AudioRecord preguntas?

He estado jugando con la función AudioRecord de la API de Android y he encontrado algunos comportamientos extraños con ella.

Información de fondo: Mi teléfono es un HTC Incredible Estoy usando el complemento de Eclipse para el desarrollo de Android con el emulador. Plataforma o sistema operativo orientado es 2,2 … Ya que es lo que mi teléfono utiliza.

Algún código:

bufferSize = AudioRecord.getMinBufferSize(FREQUENCY, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT); audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); 

Este es el código que utilizo para configurar la API de AudioRecord con. Ahora, para el emulador le gusta FREQUENCY que se establezca en 8000 para que funcione. Vuelve con un tamaño de búfer 640. Para el teléfono uso 44100. Un problema aquí es que parece que los datos PCM resultantes de la onda parece ser una onda firmada de ocho bits. Recibo valores de -127 a 128. Pensé que el valor AudioFormat.ENCODING_PCM_16BIT produciría algo diferente.

Proceso el audio con un hilo,

 public void run() { while(isRecording) { audioRecord.startRecording(); byte[] data = new byte[bufferSize]; audioRecord.read(data, 0, bufferSize); listener.setData(data); handleData(data); } audioRecord.release(); } 

Tengo una manera de mostrar gráficamente a la onda correspondiente en tiempo real usando un SurfaceView . Parece que hay mucho ruido proveniente del MIC. Tengo este ruido del emulador y el teléfono también. ¿Necesito ejecutar los datos a través de algún tipo de filtro (s)? Me gustaría usar estos datos para calcular algunos FFT de diversión y cosas sólo para jugar con la ola. Pero necesito reducir el ruido de alguna manera.

¿Alguien más experimenta esto también. ¿Alguien tiene una solución?

Aprecio su tiempo y respuestas, gracias, dk

Cuando se leen bytes de un flujo "AudioFormat.ENCODING_PCM_16BIT", en realidad le da tanto los bytes superior e inferior de cada muestra como 2 bytes secuenciales. Esto parecerá extremadamente ruidoso si usted acaba de tomar cada byte para ser una muestra (en lugar de la mitad de la muestra que realmente es), además de la firma será malo para el primer byte (está en orden poco endian).

Para obtener datos significativos de la secuencia, lea a través de cortos, por ejemplo

 public void run() { while(isRecording) { audioRecord.startRecording(); short[] data = new short[bufferSize/2]; audioRecord.read(data, 0, bufferSize/2); listener.setData(data); handleData(data); } audioRecord.release(); } 

Ha pasado un tiempo desde que se hizo esta pregunta, así que no sé si responderla es relevante.

La razón por la que obtiene valores de -127 a 128 es que está leyendo una matriz de bytes, cada uno de los cuales tiene un número de 8 bits firmado. Para audio de 16 bits, lea en una serie de pantalones cortos.

Me temo que no puedo evitar el problema del ruido.

Podría ser capaz de ayudar un poco. Sin embargo, estoy en la misma situación que tú, así que sólo puedo decirte sobre mis experiencias.

Creo que puedes obtener el sampleRate preferido de tu dispositivo así:

 int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM); 

El modo de codificación 16Bit es el único que funciona con AudioRecord. No estoy seguro de por qué está recibiendo 8Bit como salida (¿verdad?). Tal vez alguien lo sabe.

También estoy seguro de cómo se extrae la amplitud de los bytes recuperados, ¿hizo esto?

Finalmente, creo que necesitas usar las funciones de escuchas periódicas, así:

 int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM); int channelMode = AudioFormat.CHANNEL_IN_MONO; int encodingMode = AudioFormat.ENCODING_PCM_16BIT; int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelMode, encodingMode); AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelMode, encodingMode, bufferSize); recorder.setPositionNotificationPeriod(intervalFrames); recorder.setRecordPositionUpdateListener(recordListener); recorder.startRecording(); private RecordListener recordListener = new RecordListener(); private class RecordListener implements AudioRecord.OnRecordPositionUpdateListener { public void onMarkerReached(AudioRecord recorder) { Log.v("MicInfoService", "onMarkedReached CALL"); } public void onPeriodicNotification(AudioRecord recorder) { Log.v("MicInfoService", "onPeriodicNotification CALL"); } } 

Hay dos grandes preguntas aquí que no puedo contestar y quiero saber la respuesta de mí mismo también:

  1. ¿Qué se debe establecer como intervalFrames?
  2. ¿Por qué nunca se llaman los métodos de escucha?

Me gustaría poder ayudar más.

Este proyecto de código abierto tiene una buena cantidad de clases de ayuda para ayudarle a adquirir los datos de audio y experimentar con analizarlo:

https://github.com/gast-lib/gast-lib

Tiene una AsyncTask

Tiene algo que controla AudioRecorder

Incluso tiene un algoritmo simple de estimación de frecuencia

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.