1

I am doing sound analyzer application in android.I can generate 18 khz to 20 khz ultrasonic sound using AudioTrack Api.i can record audio using AudioRecord Api.But i don't know how to calculate frequency form mic input data.i saw multiple question How to get frequency from fft result? and Get frequency wav audio using FFT and Complex class it not giving proper frequency.Please help me .sorry for my communication.

This is my frequency calculation code

int bufferSizeInBytes = 1024; 
short[] buffer = new short[bufferSizeInBytes];
class Recording extends Thread {
    @Override
    public void run() {

        while (true) {

                bufferReadResult = audioInput.read(buffer, 0, bufferSizeInBytes); // record data from mic into buffer                    

                if(bufferReadResult > 0){
                   calculate();
                }              
        }
    }   


public void calculate() {
    DoubleFFT_1D fft1d = new DoubleFFT_1D(bufferSizeInBytes);//using JTransforms lib
    double[] fftBuffer = new double[bufferSizeInBytes * 2];
    double[] magnitude = new double[bufferSizeInBytes / 2];

    // copy real input data to complex FFT buffer
    for (int i = 0; i < bufferSizeInBytes - 1; ++i) {
        fftBuffer[2 * i] = buffer[i];
        fftBuffer[2 * i + 1] = 0;
    }
    //perform  FFT on fft[] buffer
    fft1d.realForward(fftBuffer);

    // calculate power spectrum (magnitude) values from fft[]
    for (int i = 0; i < (bufferSizeInBytes / 2) - 1; ++i) {

        double real = fftBuffer[2 * i];
        double imaginary = fftBuffer[2 * i + 1];
        magnitude[i] = Math.sqrt(real * real + imaginary * imaginary);

    }

    // find largest peak in power spectrum
    double max_magnitude = magnitude[0];
    int max_index = 0;
    for (int i = 0; i < magnitude.length; ++i) {
        if (magnitude[i] > max_magnitude) {
            max_magnitude = (int) magnitude[i];
            max_index = i;
        }
    }
    double freq = max_index * 44100 / bufferSizeInBytes;
    Log.e("AudioBEacon", "" + freq);
}

}

This is my output.Please let me know where i did mistake.

02-10 12:33:04.450 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21662.0
02-10 12:33:04.451 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21317.0
02-10 12:33:04.453 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21791.0
02-10 12:33:04.471 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21748.0
02-10 12:33:04.472 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21533.0
02-10 12:33:04.474 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21834.0
02-10 12:33:04.491 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21533.0
02-10 12:33:04.493 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21705.0
02-10 12:33:04.511 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21533.0
02-10 12:33:04.512 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21447.0
02-10 12:33:04.513 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21490.0
02-10 12:33:04.531 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21576.0
02-10 12:33:04.551 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21619.0
02-10 12:33:04.591 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21877.0
02-10 12:33:04.613 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21576.0
02-10 12:33:04.633 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21920.0
02-10 12:33:04.653 17013-17063/com.org.sohamsaa.audiobeacontransmitter E/AudioBEacon: 21791.0

My frequency range is 18 khz to 20 khz.but i don't get my frequency.how to filter my frequency.thank you.

Community
  • 1
  • 1
Siddharthan
  • 61
  • 2
  • 9
  • Remove the `(int)` cast here: `max_magnitude = (int) magnitude[i];` - there may be other problems but this is definitely wrong. Note also that most devices have very poor sensitivity at > 18 kHz - the microphone usually has a poor response above 15 kHz and the anti-aliassing filter may also reduce levels further. – Paul R Feb 10 '17 at 08:54
  • @ Paul R Thanks for your reply and i remove (int).But it is not working and i generate 14 khz frequency but i'm not getting.This is my log result E/AudioBEacon: 861.0 E/AudioBEacon: 21404.0 E/AudioBEacon: 21705.0 E/AudioBEacon: 21447.0 E/AudioBEacon: 215.0 E/AudioBEacon: 21705.0 E/AudioBEacon: 344.0 E/AudioBEacon: 473.0 E/AudioBEacon: 430.0 – Siddharthan Feb 10 '17 at 10:08
  • what is window function?and how to do? – Siddharthan Feb 10 '17 at 10:45
  • 1
    Try plotting your time domain waveform and spectrum to see if they look reasonable - that's usually a good way to narrow down the problem. For window functions you can just [search here on StackOverflow](http://stackoverflow.com/search?q=Window+function+%5Bdsp%5D) and/or read the [Wikipedia entry](https://en.m.wikipedia.org/wiki/Window_function). – Paul R Feb 10 '17 at 10:51

2 Answers2

5

See my sample project. :D Github.

This retrieve frequency with high precision and big velocity, based on a Spectrum Analyzer app developed by Google developers.

enter image description here

Lucas
  • 431
  • 3
  • 7
1

Finally i found the answer.Just apply FFT instead of JTransforms lib in my code.This code is working for me.

int bufferSizeInBytes = 1024; 
short[] buffer = new short[bufferSizeInBytes];
class Recording extends Thread {

    @Override
    public void run() {

        while () {

            if (true) {                   
                int bufferReadResult = audioInput.read(buffer, 0, bufferSizeInBytes); // record data from mic into buffer
                if (bufferReadResult > 0) {
                    calculate();
                }
            } 
        }
    }
}
public void calculate() {

    double[] magnitude = new double[bufferSizeInBytes / 2];

    //Create Complex array for use in FFT
    Complex[] fftTempArray = new Complex[bufferSizeInBytes];
    for (int i = 0; i < bufferSizeInBytes; i++) {
        fftTempArray[i] = new Complex(buffer[i], 0);
    }

    //Obtain array of FFT data
    final Complex[] fftArray = FFT.fft(fftTempArray);
    // calculate power spectrum (magnitude) values from fft[]
    for (int i = 0; i < (bufferSizeInBytes / 2) - 1; ++i) {

        double real = fftArray[i].re();
        double imaginary = fftArray[i].im();
        magnitude[i] = Math.sqrt(real * real + imaginary * imaginary);

    }

    // find largest peak in power spectrum
    double max_magnitude = magnitude[0];
    int max_index = 0;
    for (int i = 0; i < magnitude.length; ++i) {
        if (magnitude[i] > max_magnitude) {
            max_magnitude = (int) magnitude[i];
            max_index = i;
        }
    }
    double freq = 44100 * max_index / bufferSizeInBytes;//here will get frequency in hz like(17000,18000..etc)        

}
Siddharthan
  • 61
  • 2
  • 9
  • 1
    This worked like a charm for me! For anyone else interested in this, you can find the FFT implementation here https://introcs.cs.princeton.edu/java/97data/FFT.java.html and the implementation for the Complex numbers here https://introcs.cs.princeton.edu/java/97data/Complex.java.html. – Theo Stefou Jul 01 '21 at 11:46