0

I'm trying to convert the Python program located at https://github.com/rraval/pied-piper/blob/master/decode.py to an Android Java file.

The first step is to identify the dominant frequency. I have written the following Java program to do that

private class RecordAudio
        extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... paramVarArgs) {
        int audioSource = AudioSource.MIC;
        int sampleRateInHz = 44100;
        int channelConfig = AudioFormat.CHANNEL_IN_MONO;
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
        int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
        byte Data[] = new byte[bufferSizeInBytes];

        AudioRecord audioRecorder = new AudioRecord(audioSource,
                sampleRateInHz,
                channelConfig,
                audioFormat,
                bufferSizeInBytes);
        audioRecorder.startRecording();

        boolean isRecording = true;
        while (isRecording) {
            audioRecorder.read(Data, 0, Data.length);
            fftPrint(Data, bufferSizeInBytes);
        }
        return null;
    }

    boolean fftPrint(byte[] waveArray, int bufferSizeInBytes) {
        double HANDSHAKE_START_HZ = 8192;
        double HANDSHAKE_END_HZ = 8192 + 512;
        int len = waveArray.length;
        double[] waveTransformReal = new double[len];
        double[] waveTransformImg = new double[len];

        for (int i = 0; i < len; i++) {
            waveTransformReal[i] = waveArray[i]; //copy of original
            waveTransformImg[i] = waveArray[i]; //FFT transformed below
        }

        RealDoubleFFT p = new RealDoubleFFT(bufferSizeInBytes);
        p.ft(waveTransformImg);

        //Calculating abs
        double[] abs = new double[len];
        for (int i = 0; i < len; i++) {
            abs[i] = (Math.sqrt(waveTransformReal[i] * waveTransformReal[i] + waveTransformImg[i] * waveTransformImg[i]));
        }

        //calculating maxIndex
        int maxIndex = 0;
        for (int i = 0; i < len; i++) {
            if (abs[i] > abs[maxIndex])
                maxIndex = i;
        }

        double dominantFrequency = (maxIndex * 44100) / len;
        if (dominantFrequency > 0) Log.d("Freq: ", String.format("%f", dominantFrequency));

        if (match(dominantFrequency, HANDSHAKE_START_HZ)) {
            Log.i("Handshake start:", "FOUND START");
        }
        if (match(dominantFrequency, HANDSHAKE_END_HZ)) {
            Log.i("Handshake end:", "FOUND END");
            return true;
        }
        return false;
    }

    boolean match(double freq1, double freq2) {
        return (Math.abs(freq1 - freq2) < 20);
    }

Note: RealDoubleFFT is from ca.uol.aig.fftpack

Am not sure if I have done it right. I'm getting the frequencies printed in the Logcat, but they are not finding the HANDSHAKE_START_HZ, which is present in the audio being played. What am I doing wrong?

Paul R
  • 208,748
  • 37
  • 389
  • 560
Arun
  • 3,036
  • 3
  • 35
  • 57

1 Answers1

1

Note that the frequency resolution of a FFT magnitude peak depends on the length of the FFT (and the window, etc.). This length is not specified or constrained in your code, so you won't know whether it is even possible for any FFT result bin to be within 20 Hz of your target frequencies.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
  • Thanks for the answer @hotpaw2, I'm completely new to sound and I managed to write the above code by reading a lot on the net. I did hardcode the bufferSizeInBytes ro 4096. But still did not see the expired output. Each time I run this program and play the same sound, I get different dominant frequencies for each chunk. Can you please help by correcting the above code. Many Thanks. – Arun Nov 17 '18 at 11:59