Java – How to Determine Frequency (In Hertz, Real Time) with Java Sound

java

I've been looking around and I've found some questions similar to mine but have never been quite satisfied with the answers. I'm more or less a Java n00b, although I am moderately proficient with C++ and I would consider myself intermediate to advanced, as a programmer in general. I'm looking to write a program in Java that functions similarly to a tuner – what I want to do is record an instrument's pitch over about a 3 second time frame, and to measure the average deviation. (This is for a band class.)

What I'm thinking is that I'll have a big array of numbers, and each entry in the array will be a number in terms of frequency. I want to be able to loop through the array, and calculate the average Hertz for displaying it on screen or something. So what I want to do is have some way of "polling" (for lack of a better word) the microphone to see what frequency is being inputted right that instant.

Is there a simple way to accept audio input from a microphone in terms of Hertz? This will be in Java, under a Windows platform.

Best Answer

You will need to do some spectrum analysis. Take a short piece of audio data, maybe some 256 samples, then calculate a fast fourier transform (FFT) for each piece of data. However, a fourier transform itself is not enough since the process of cutting up sound in short samples introduces some distortion. This distortion will mainly be in the higher frequencies. For pitch detection, you can get away with simply filtering away this distortion using a low pass filter. Alternatively, you can window your sound sample, usually using hanning or blackman window functions (different sine-slopes, basically). In order to improve time resolution you should also overlap the individual samples you take. At last, you should average your individual spectra over as long a time as you want to analyze.

Doing all that will give you something called a Power Spectral Density function. This method of deriving it is called the Welch method. Hence, if you are lucky, Java Sound will include a method for calculating one of these. In many signal processing environments, this would be called "pwelch" or "psd".

Of course, the spectrum will use logarithmic frequencies (way more frequency points towards the high frequencies) and the amplitudes will most likely be denormalized and linear instead of simply dB values. Also, you will still have to find a good method to find your actual pitch frequency amongst all the harmonic noise etc.

What I want to say is this: Either your library has an easy function that does exactly what you want or this stuff is probably too complex to have an easy answer. Sorry.