FFT de audio Android para recuperar una magnitud de frecuencia específica usando audiorecord

Actualmente estoy intentando implementar algún código con Android para detectar cuándo se reproducen una serie de rangos de frecuencia de audio específicos a través del micrófono del teléfono. Configuré la clase usando la clase 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); 

La realización de una FFT es donde me quedo estancado, ya que tengo muy poca experiencia en esta área. He estado tratando de usar esta clase:

FFT en Java y clase compleja para ir con él

Entonces 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 podría fácilmente ser un malentendido sobre cómo debe funcionar esta clase, pero los valores devueltos saltan por todas partes y no son representativos de una frecuencia uniforme ni siquiera 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?

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 verse más o menos así:

  double[] micBufferData = new double[]; 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; } 

Luego usa micBufferData [] para crear su matriz compleja de entrada.

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.

Necesita la frecuencia de muestreo para convertir los índices de matriz a tales magnitudes a frecuencias:

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