Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get frequency value in javascript?

I’m an italian student, and I’m using p5’s libraries to create a web guitar tuner. I would like to know if there is a way to get the frequency of the microphone input.

library link: https://p5js.org/reference/#/libraries/p5.sound

Different solution with different libraries are accepted

Thanks

like image 452
Strimply Avatar asked May 16 '18 17:05

Strimply


1 Answers

Building off of this example, if you use P5.sound's FFT object, you can call fft.analyze() to get an array of amplitudes divided up into different frequency bins.

The default is 1024 bins. These bins are evenly spaced from 0Hz to the Nyquist frequency, which is half your audio sample rate. (The default sample rate is 44100Hz, so the default Nyquist frequency is 22050Hz).

Note also that each bin has a default resolution of 22050Hz / 1024 bins ≈ 21.53Hz/bin. You're going to get at best a 21.53Hz precision if you use P5.sound (assuming your computer is set up the same way mine is).

So, bin 0 (or spectrum[0]) contains the amplitude at frequencies ~ 0 - 21.5Hz, bin 1 (spectrum[1]) contains the amplitude at frequencies ~ 21.5Hz - 43.0Hz, et cetera.

This means the frequency at any given bin is: freq = binIndex * (nyquist / numberOfBins).

If that's good enough for you, you can loop through the array returned by fft.analyze(), find the index of the peak, and then convert that index back to a frequency using the ratio of Nyquist to array length (bins).

function getLoudestFrequency() {
    var nyquist = sampleRate() / 2; // 22050
    var spectrum = fft.analyze(); // array of amplitudes in bins
    var numberOfBins = spectrum.length;
    var maxAmp = 0;
    var largestBin;

    for (var i = 0; i < numberOfBins; i++) {
        var thisAmp = spectrum[i]; // amplitude of current bin
        if (thisAmp > maxAmp) {
            maxAmp = thisAmp;
            largestBin = i;
        }
    }

    var loudestFreq = largestBin * (nyquist / numberOfBins);
    return loudestFreq;
}

Let's say ±21.53Hz isn't accurate enough for you. Well... you can initialize your FFT object with more bins: new p5.FFT(0.8,[bins]). The documentation says that the max number of bins is 1024, but I just tried with 8192 (for resolution of 2.69Hz) and it seemed to work fine for me.

like image 178
Wes Lord Avatar answered Nov 11 '22 18:11

Wes Lord