2011-04-25 7 views
38

Actualmente estoy tratando de implementar algún código con Android para detectar cuándo se tocan varios rangos de frecuencia de audio específicos a través del micrófono del teléfono. He creado la clase utilizando la clase AudioRecord:FFT de audio Android para recuperar una magnitud de frecuencia específica usando audiorecord

int channel_config = AudioFormat.CHANNEL_CONFIGURATION_MONO; 
int format = AudioFormat.ENCODING_PCM_16BIT; 
int sampleSize = 8000; 
int bufferSize = AudioRecord.getMinBufferSize(sampleSize, channel_config, format); 
AudioRecord audioInput = new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize); 

El audio se lee en:

short[] audioBuffer = new short[bufferSize]; 
audioInput.startRecording(); 
audioInput.read(audioBuffer, 0, bufferSize); 

Realización de una FFT es donde atorarse, ya que tengo muy poca experiencia en esta área . He estado tratando de utilizar esta clase:

FFT in Java y Complex class to go with it

entonces yo estoy enviando los siguientes valores:

Complex[] fftTempArray = new Complex[bufferSize]; 
for (int i=0; i<bufferSize; i++) 
{ 
    fftTempArray[i] = new Complex(audio[i], 0); 
} 
Complex[] fftArray = fft(fftTempArray); 

Esto fácilmente podría ser yo malentendido cómo esta clase está destinado a trabajar, pero los valores devueltos saltan por todos lados y no son representativos de una frecuencia uniforme incluso en silencio. ¿Alguien sabe de una manera de realizar esta tarea, o estoy complicando demasiado las cosas para tratar de obtener solo un pequeño número de rangos de frecuencia en lugar de dibujarlo como una representación gráfica?

+10

Hey, si lo imaginó, ¿podría publicar la versión final del código? thx –

Respuesta

33

Primero debe asegurarse de que el resultado que obtiene se convierta correctamente en flotante/doble. No estoy seguro de cómo funciona la versión corta [], pero la versión de bytes [] solo devuelve la versión de bytes sin formato. Esta matriz de bytes necesita convertirse correctamente en un número de punto flotante. El código para la conversión debe ser algo como esto:

double[] micBufferData = new double[<insert-proper-size>]; 
    final int bytesPerSample = 2; // As it is 16bit PCM 
    final double amplification = 100.0; // choose a number as you like 
    for (int index = 0, floatIndex = 0; index < bytesRecorded - bytesPerSample + 1; index += bytesPerSample, floatIndex++) { 
     double sample = 0; 
     for (int b = 0; b < bytesPerSample; b++) { 
      int v = bufferData[index + b]; 
      if (b < bytesPerSample - 1 || bytesPerSample == 1) { 
       v &= 0xFF; 
      } 
      sample += v << (b * 8); 
     } 
     double sample32 = amplification * (sample/32768.0); 
     micBufferData[floatIndex] = sample32; 
    } 

continuación, utiliza micBufferData [] para crear el array entrada compleja.

Una vez que obtenga los resultados, use las magnitudes de los números complejos en los resultados. La mayoría de las magnitudes deben ser cercanas a cero, excepto las frecuencias que tienen valores reales.

Usted necesita la frecuencia de muestreo para convertir los índices de matriz de tales magnitudes a las frecuencias:

private double ComputeFrequency(int arrayIndex) { 
    return ((1.0 * sampleRate)/(1.0 * fftOutWindowSize)) * arrayIndex; 
} 
+2

Muchas gracias por su respuesta, pero todavía tengo un par de problemas. Antes de ejecutar el método 'ComputeFrequency', ¿debería ser capaz de extraer los valores de la matriz compleja devuelta? El mismo problema todavía parece permitir que aparezcan números esporádicos que van de 10 a alrededor de 3000, mientras que la sala está en silencio, lamentablemente – user723060

+0

Sí, aún debe ser capaz de extraer los valores de la matriz compleja, quiere usar las magnitudes de la matriz. números complejos (es decir, sqrt (re * re + im * im)). Aunque la habitación está en completo silencio, puede haber ruido de fondo introducido por el micrófono que aparecerá en la FFT. Convierta los índices de la matriz a frecuencias para ver cuáles son las frecuencias exactas que aparecen. Los valores de esas frecuencias pueden ayudar a comprender si son ruido de fondo o no. – shams

+0

Tengo curiosidad si estoy llamando a la matriz compleja correctamente en lo que respecta a los números imaginarios. La forma en que lo he implementado ahora es muy similar a como lo hice en mi ejemplo original, pero ahora estoy recorriendo en bicicleta la nueva matriz micBufferData y asignando cada valor a una matriz compleja como el número real con el número imaginario constantemente como 0. Esto puede ser donde me estoy equivocando, pero los ejemplos anteriores que he leído parecen indicar que este es el método correcto. ¿Alguna idea de si hay algo más para entrar allí? ¡Gracias de nuevo! – user723060

Cuestiones relacionadas