4

I recently asked this question:

I am looking for an algorithm to detect pitch. one of the answers suggested that I use an initial FFT to get the basic frequency response, figure out which frequencies are getting voiced, and follow it up with a band pass filter in each area of interest:

A slightly advanced algorithm could do something like this:

  1. Roughly detect pitch frequency (could be done with DFT).
  2. Bandpass signal to filter isolate pitch frequency.
  3. Count the number of samples between two peaks in the filtered signals.

Now I can do the first step okay ( I am coding for iOS, and Apple has a framework (the accelerate framework) for doing FFTs etc.

I have made a start here: but I can see the problem: an FFT that would differentiate all of the possible notes one could sing would require a lot of samples, and I don't want to perform too much unnecessary computation as I'm targeting a mobile device.

So I'm trying to get my head round this answer above, but I don't understand how I could apply the concept of a band pass filter to code.

Can anyone help?

istepaniuk
  • 4,016
  • 2
  • 32
  • 60
P i
  • 29,020
  • 36
  • 159
  • 267
  • You've asked a lot of questions on SO about pitch detection already but it seems that you still don't quite understand (a) the difference between *pitch* and *frequency* or (b) the need to choose a pitch detection algorithm which is appropriate for the type of sound that you are trying to analyse (e.g. speech, music, etc). I suggest you do a bit more reading on the fundamentals before trying to implement something, otherwise you may well expend a lot of unnecessary effort going down the wrong route. – Paul R Nov 05 '10 at 09:57
  • This is why I am asking so many questions -- I am trying to figure out what is practical and what is not before launching into something. I'm slowly getting some perspective on the problem. – P i Nov 05 '10 at 15:26
  • @Ohmu: you might want to go back and re-read some of the previous answers, and also the links that were provided. I get the feeling that you're trying to jump into an implementation without having grasped the fundamentals first. Good luck. – Paul R Nov 05 '10 at 16:30
  • @Paul R: As I understand it, the voice consists of a fundamental frequency and harmonics thereof. I've gone through the math of Fourier Transforms, DFT, FFT, and run into practical limitations; to detect if a sung tone is slightly off from but the actual note requires a low fundamental frequency, which requires a large sampling window, which requires either heavy CPU, or drastically lowering the microphone sample rate. Hence I am looking at performing a basic FFT to get general areas of interest in the frequency domain, and refining the result somehow. – P i Nov 05 '10 at 19:14
  • @Paul R: Hence my interest in the answer given me suggesting I use a band pass filter at this stage. However, I can't determine whether this is a practical suggestion. I have also looked into the other suggestions; autocorrelation is effectively the same as multiplying the source signal by a sine wave of desired frequency and integrating over an integral number of wavelengths, this may work but would take some work to decipher slightly off frequencies from the output. I'm really still trying to prod it from all angles. – P i Nov 05 '10 at 19:22
  • @Ohmu: if you're interested in the pitch of the human voice then you might want to look at cepstral analysis: http://en.wikipedia.org/wiki/Cepstrum – Paul R Nov 05 '10 at 21:28

3 Answers3

3

Filter design is pretty complex. There are many techniques. First you have to decide what kind of filter you want to create. Finite impulse response (FIR)? Infinite impulse response (IIR)? Then you select an algorithm for designing a filter of that type. The Remez algorithm is often used for FIR filter design. Go here to see the complexity that I was referring to: http://en.wikipedia.org/wiki/Remez_algorithm

Your best best for creating a filter is to use an existing signal processing library. A quick Google search led me here: http://spuc.sourceforge.net/

Given what your application is, you may want to read about matched filters. I am not sure if they are relevant here, but they might be. http://en.wikipedia.org/wiki/Matched_filter

Fantius
  • 3,806
  • 5
  • 32
  • 49
1

well in Wikipedia, checkup on low-pass filter, and hi-pass, then join them to make a band-pass filter. Wikipedia has code implementations for those two filters.

http://en.wikipedia.org/wiki/Low-pass_filter http://en.wikipedia.org/wiki/High-pass_filter

TechEffigy
  • 45
  • 2
  • I'm busy with a neural network at the moment, and outweighing using band-pass filters or FFT. That's how I came across your question :) – TechEffigy Sep 16 '14 at 01:09
0

Since you only want to detect a single frequency, it would be an overkill to perform a DFT to then only use one of the values.

You could implement the Goertzel algorithm. Like this C implementation used to detect DTMF tones over a phone line, from the FreePBX source code:

float goertzel(short x[], int nmax, float coeff) {
    float s, power;
    float sprev, sprev2;
    int   n;

    sprev = 0;
    sprev2 = 0;
    for(n=0; n<nmax; n++) {
        s = x[n] + coeff * sprev - sprev2;
        sprev2 = sprev;
        sprev = s;
    }

    power = sprev2*sprev2 + sprev*sprev - coeff*sprev*sprev2;

    return power;
}

As you can see, the implementation is fairly trivial and quite effective for single frequencies. Check the link for different versions with and without floating point, and how to use it.

istepaniuk
  • 4,016
  • 2
  • 32
  • 60