Convert Audiorecord Data to process FFT

295 views Asked by At

I have been implementing a Polyphonic signal pitch detector so I started to code my Program doing (RecordData, Convert Data, Zero-padding, Windowing, FFT, Peak detection). At first I tested it with sounds I already new which values I should get, and it worked perfectly.

The problem I have is when recording with my Phone using the Audiorecord class.

For example: I played and recorded two or three pure tones with my phone and the values I get with the Audiorecord class were not correct. Getting wrong data from my phone does not let me do a good analysis.

Here is my code to Record Data(Short) and Convert Data Short to Double (This step is where i think its the problem)

Here is my code:

void recordAudio() {

mShouldContinue= true;

    new Thread(new Runnable() {
        @Override
        public void run() {
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);


            // buffer size in short
            bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); //Consigue el minimo tamaño de buffer para poder analizar

            if (bufferSize == AudioRecord.ERROR || bufferSize == AudioRecord.ERROR_BAD_VALUE) {
                bufferSize = sampleRate * 2; // si el buffersize obtenido por nuestro getMinBufferSize es apto  usaremos el encontrado si no utilizaremos el doble de nuestra frecuencia de sampleo
            }


            short[] audioBuffer = new short[bufferSize];

            if (audioBuffer.length % 2 == 0){ // Aseguramos que nuestro buffer input tenga una tamaño impar para una mejor R.F.
                audioBuffer = new short[bufferSize +1];
            }


            AudioRecord record = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); //Instancia de la clase AudioRecord

            if (record.getState() != AudioRecord.STATE_INITIALIZED) { // Si audiorecord no ha sido inicializado displeamos un mensaje advirtiendo.
                Log.e(LOG_TAG, "Audio Record can't initialize!");
                return;
            }
            record.startRecording(); //Empezamos a grabar con nuestros parámetros ya definidos.

            Log.v(LOG_TAG, "Start recording");  //mensaje informativo

            long shortsRead = 0;

            while (mShouldContinue) {

                int numberOfShort = record.read(audioBuffer, 0, audioBuffer.length); //audiobuffer.length
                shortsRead += numberOfShort;





                DFT(audioBuffer);



                try { // Dormimos el programa durante un segundo
                    Thread.sleep(1000);
                } catch(InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }

            }

                record.stop();
                record.release();

                Log.v(LOG_TAG, String.format("Recording stopped. Samples read: %d", shortsRead));




        }
    }).start();
}

Convertion where Inputsignal is audiobuffer and N it's length (Inside DFT Function):

for(int i = 0; i < N; i++){
    doubley[i] = (double)(InputSignal[i])/32768.0;

}
1

There are 1 answers

1
hotpaw2 On

An FFT magnitude peak detector is not a reliable musical pitch (frequency/note) estimator. It will often find harmonic frequencies instead for some timbres.

Instead, look up some pitch detection/estimation methods (weighted autocorrelation, AMDF, HPS, cepstral, decision, CDNN, etc.), and try one of those, instead of (mis)using a spectral frequency estimator.