7

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.

3
  • 3
    Are you after help with the design or the coding? If it's the former you're in the right place, but for the latter Stack Overflow is the site you want. However, you will have to show what code you already have and explain what's not working.
    – ChrisF
    Feb 21, 2012 at 23:29
  • Well, what I want is to be headed in the right direction, I haven't written any actual code for this program yet. I'm still planning it out, but I have no idea where to start, so that's why I'm asking here. Feb 22, 2012 at 0:02
  • do you consider using Java Media Framework or some other library?
    – gnat
    Feb 22, 2012 at 14:56

3 Answers 3

4

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.

1

I suggest you look into some tutorials or textbooks on digital signal processing. What you are trying to do is actually quite complicated. Some of the things that make it complicated are:

  • Audio samples will be coming to you from the sound card in PCM (Pulse Code Modulated) samples. That is just a fancy term for time domain samples. That is, the analog sound wave going into the microphone is sampled at a regular interval and you are given those samples as numbers. This does not directly give you any frequency information, you will have to perform an FFT to transform the time domain data into the frequency domain.

  • Even after the FFT, you still do not have the array of frequencies you are looking for. What you have is an array of magnitudes at each sampled frequency. So you will have to do some kind of detection to determine which frequencies are actually present in your signal. This could be a simple threshold and peak pick, or something more involved.

  • In addition to this difficulty, there is a tradeoff when performing spectral analysis with the FFT between time and frequency resolution. If you want to get more frequency resolution, you must sacrifice time resolution. For example, if you want to be able to detect a 1Hz change in a signal that is sampled at 44100 Hz, you will need to perform an FFT of 44100 samples. Well, 44100 samples is an entire second of data, which means that even though you can detect a signal to 1Hz resolution, you don't know where in that second it occurred. This is why many pitch detection algorithms use time-domain methods like auto-correlation to find the pitch.

  • Another difficulty is that an instrument does not produce a pure tone (single frequency), but produces a number of harmonics as well. So you will not only have the true pitch frequency, but there will be other frequencies present in the signal that you will have to account for.

All of this is not to discourage you from doing this project, I am just trying to lay out some of the issues you might face when doing the project. I worked on a similar project and ran into these issues.

0

it depends on what format you get your data, the most efficient way is direct PCM which is really just samples of the sound stream (and what you'll likely be getting from most mice API's).

To get frequencies from this you'll need to fourier transform the samples. This will result in a set of values (one for each frequency).

1
  • Any idea how to do this, or get me pointed in the right direction with Java Sound? Feb 22, 2012 at 0:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.