DSPRelated.com
Forums

Reference implementation of pitch detection

Started by Elizabeth August 23, 2003
> Detection of the pitch of what kind of signal?
I want to be able to detect the pitch/note that I'm playing on my flute in real time and tell how far off the mark I am.
In article <Hbz2b.1514$hM.1170@bignews6.bellsouth.net>,
Elizabeth <pleasedont@goaway.net> wrote:
>> Detection of the pitch of what kind of signal? > >I want to be able to detect the pitch/note that I'm playing on my flute >in real time and tell how far off the mark I am.
This might be an easy one if you are playing a long note which is all fundamental frequency (almost no overtones). Assuming you already have a sound input method with a reasonable gain setting, you could try just counting the zero crossings in the data for one second and you will have an answer to about 1 Hz. For better resolution in "cents", try subtracting the location in time of the first and last zero crossings for your denominator. If you have or can borrow a Palm Tungsten T handheld, try my Palm OS 5 guitar tuner application, which uses a slightly more complicated form of this algorithm. It can be found here: http://www.hotpaw.com/rhn/palm IMHO. YMMV. -- Ron Nicholson rhn AT nicholson DOT com http://www.nicholson.com/rhn/ #include <canonical.disclaimer> // only my own opinions, etc.
> This might be an easy one if you are playing a long note which is all > fundamental frequency (almost no overtones). Assuming you already have > a sound input method with a reasonable gain setting, you could try just > counting the zero crossings in the data for one second and you will > have an answer to about 1 Hz. For better resolution in "cents", try > subtracting the location in time of the first and last zero crossings > for your denominator.
Thanks a bunch, I'll look at it. What method should I be looking at to get closer to realtime?
Elizabeth wrote:
> > "Jerry Avins" <jya@ieee.org> wrote in message > news:3F4A2F2F.EEA60C51@ieee.org... > > Elizabeth wrote: > > > > > > Actually, any explanation that doesn't resort calculus would be > fabulous. > > > > Elizabeth, > > > > There may be one, but I haven't thought of it yet. One of my armchair > > pleasures is solving calculus problems without calculus. I started, as > > far as I know, in the seventh grade. > > Let me put it another way. I as I understand it, the sanskrit looking > formulae that I've been reading about recently are nothing more than > algorithms. However complex, they can be broken down into a series of steps > that can surely be explained without resorting to symbolic means. > > For purely illustrative purposes, something akin to: > > 1. for each peak frequency with an amplitude greater than X > add cosine(frequency) to a running total > > 2. Divide running total by number of peaks > > 3. Multiple result by Pi > > See what I mean?
I do indeed see what you mean, and I agree. Consider, though, that someone conceived of those algorithms. You can be pretty sure that calculus helped her to express the problem and its solution succinctly enough to think clearly about it. Without that clear thought, there would be no algorithm to code. Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
In article x3f2b.13323$99.8728@fe03.atl2.webusenet.com, Elizabeth at
pleasedont@goaway.net wrote on 08/24/2003 23:18:

> Actually, any explanation that doesn't resort calculus would be fabulous.
In article 8ix2b.638$Rg.526@bignews4.bellsouth.net, Elizabeth at pleasedont@goaway.net wrote on 08/25/2003 19:51:
>> i would send this directly to you (not comp.dsp) just to allow us to be >> frank which is difficult in a public environment, but with a return > address >> of <pleasedont@goaway.net>, i am skeptical that it would make it. > > lol. Good catch. > >> what is the math you don't understand? integrals? (they're just >> summations.) >> >> perhaps the better question is: what is the math you *do* understand? > it's >> not a silly question because you must be able to understand some if you're >> gonna code anything having to do with audio signal processing. > > Actually, you've hit on the head. It's the symbolic language I don't > understand.
the symbols are something to learn. an integral is simply the area under the curve of a function (when the function goes below the "x-axis" then the area between the function and the axis is "negative area". it really just means summing up the values of the function over a particular region.
> To give you some background, I've been a programmer for about ten years, and > a couple of years ago I wrote an application to price options using black > scholes and monte carlo simulations. The nasty looking formulas were driving > me nuts until I found a link that explained that the black scholes method > was simply: > > DoubleVar1 = Log(Price/Strike) + (RiskFreeRate + ( Volatility * Volatility) > / 2) * TimeToExpire) / (Volatility * Sqrt(TimeToExpire)) > DoubleVar2 = DoubleVar1 - Volatility * Sqrt(TimeToExpire) > > if CallOption then > Return Price * CumDistributionNorm(DoubleVar1) - Strike * Exp(RiskFreeRate > * -1 * TimeToExpire) * CumDistributionNorm(DoubleVar2) > > Simple, right? ;-)
it's not so bad. except for the definition of CumDistributionNorm(), it's pretty easy to see what it does, at least when CallOption is true. you have an unmatched ) parenth for DoubleVar1 and if the missing ( parenth comes before Log(Price/Strike), the expression is reasonable simple and can be simplified a bit mathematically. but sometimes programmers don't like to do that kind of simplification because it makes the code harder for them to maintain. In article bieciu$uj4$1@blue.rahul.net, Ronald H. Nicholson, Jr. at rhn@nojunk.rahul.net wrote on 08/25/2003 21:19:
> In article <XkK1b.4677$lq.4197@fe04.atl2.webusenet.com>, > Elizabeth <pleasedont@goaway.net> wrote: >> Could someone point me to a reference/example implementation of pitch >> detection? > > Detection of the pitch of what kind of signal? > > The answer could be as simple as counting zero crossings, to > something far more complicated, depending such things as the > signal-to-noise ratio, harmonic content, signal duration, signal > evolution over time, and the time/frequency resolution required. > The answer may also require you to precisely specify what you mean > by "pitch", as psychoacoustics and such might be required to model > your problem (people sometimes "hear" the pitch of "notes" which > don't actually "exist"). > > In many cases, the solution can be expressed in a simple algorithm, > but, which only makes sense if you understand mathematical concepts > such as convolution with a trigonometric function. Using an > algorithm without understanding what's behind it is like copying > the answer from the textbook; this only works if the instructor > doesn't modify the question slightly. The real world is often an > excellent instructor.
all true. i'm assuming Elizabeth wants to determine the fundamental frequency, f0, or the period T = 1/f0 of a periodic or quasi-periodic waveform for either musical note detection or for speech processing. counting zero crossings will not do it because it's not hard to dream up a periodic function that will fool it. i.e. (3/2 + sin(2*pi*f0*t))*sin(4*pi*f0*t) will look like it has frequency 2*f0 if you look only at the zero crossings but the fundamental is at f0. the Average Magnitude Difference Function (AMDF) or Average Squared Difference Function (ASDF) are probably the two simplest non-trivial methods. they are pretty robust (they make no assumptions about the periodic function other than that they are periodic) but they're pretty expensive, computationally, unless tricks are used. the definition of and main property of a periodic function, with period T, is that x(t+T) = x(t) for all t. strictly speaking, T should be chosen to be the smallest value that meets the above condition since if T works, we know that 2*T, 3*T, ... will also work but we don't want to call those integer multiples the period. (there is a problem with this restriction often called the "octave problem", but i'll get into it later.) now if x(t) is quasi-periodic, then the property above is only "almost true": x(t+T) = x(t) + e(t) where e(t) = x(t+T) - x(t) (of course!) e(t) is an error function (or "difference function" as in "DF") that should be very small if T is chosen correctly. so the idea of the AMDF or ASDF algorithm is to choose T so that e(t) is smallest (for all t that we care about) in some way. to measure the size of e(t) we have to do something to make if positive, even when it's negative so that the negative errors (or differences) team up with positive errors and do not arithmetically cancel them as negative numbers tend to do to positives. the AMDF will choose T to minimize the |e(t)| over some region of t and the ASDF will choose T to minimize (e(t))^2 . doing this for discrete-time signals, x[n] (we like the C-like convention of notation defining discrete sequences to have [] brackets and continuous functions to have () parenths), ain't too bad but you have to remember what limitations you get from the discrete domain. here i am defining the sampling frequency to be 1 (not a problem if you define your unit time to be the same as the sampling period) so that x[n] = x(n) (but only defined for integer n) so if x(t) happens to be periodic with period T that is an integer (remember t and T are in units of sampling periods), then x[n+T] = x[n] for all n. and if it's almost periodic or "quasi-periodic", x[n+T] = x[n] + e[n] and e[n] = x[n+T] - x[n] . now we wanna pick T to minimize |e[n]| or (e[n])^2 somehow. double x[]; // i dunno how big the x[] array is. double T = 0; double min_e_sum = +1.0e20; // init to some big horrible number double previous_e_sum = 0.0; for (int tau=1; tau<T_max; tau++) { double e_sum = 0.0; for (n=0; n<N; n++) { double e = x[n+tau] - x[n]; if (e < 0.0) { e = -e; // abs value, you can square it instead } e_sum = e_sum + e; } if (previous_e_sum < e_sum) // wait for first local maximum { previous_e_sum = e_sum; } else { previous_e_sum = 1.0e20; // this is like setting a flag if (e_sum < min_e_sum) { T = (double)tau; min_e_sum = e_sum; } } } at the end of this, T will equal the value of tau that gave you the smallest sum of errors. besides the "octave problem" (which we can talk about later) another issue is what if the period is not exactly an integer number of samples in length. then you will need to interpolate the apparent minimum to find where the true minimum is (quadratic is good enough) and you may have to do it to each local minimum and pick the lowest of those interpolated minimums. the interpolated location (tau) of the lowest minimum will be the best estimate of the period. howzat for a place to start? r b-j
"Jerry Avins" <jya@ieee.org> wrote in message
news:3F4ACF3B.62345BC8@ieee.org...
> Elizabeth wrote: > > > > "Jerry Avins" <jya@ieee.org> wrote in message > > news:3F4A2F2F.EEA60C51@ieee.org... > > > Elizabeth wrote: > > > > > > > > Actually, any explanation that doesn't resort calculus would be > > fabulous. > > > > > > Elizabeth, > > > > > > There may be one, but I haven't thought of it yet. One of my armchair > > > pleasures is solving calculus problems without calculus. I started, as > > > far as I know, in the seventh grade. > > > > Let me put it another way. I as I understand it, the sanskrit looking > > formulae that I've been reading about recently are nothing more than > > algorithms. However complex, they can be broken down into a series of
steps
> > that can surely be explained without resorting to symbolic means. > > > > For purely illustrative purposes, something akin to: > > > > 1. for each peak frequency with an amplitude greater than X > > add cosine(frequency) to a running total > > > > 2. Divide running total by number of peaks > > > > 3. Multiple result by Pi > > > > See what I mean? > > I do indeed see what you mean, and I agree. Consider, though, that > someone conceived of those algorithms. You can be pretty sure that > calculus helped her to express the problem and its solution succinctly > enough to think clearly about it. Without that clear thought, there > would be no algorithm to code.
There is a book written by David Goodstein recreating from a transcript of a recording of a lecture by Richard Feynman rederiving the method Newton used to derive Kepler's law of elliptical orbits. It is relatively easy to do using calculus, but Newton didn't use calculus. The story is that Goodstein was on a cruise ship with his wife at the time that he figured out how to make it work. The book is called "Feynman's Lost Lecture", and is pretty interesting even if you do know how to do it using calculus. I am pretty sure that Fourier used calculus in deriving his transforms and series. -- glen
Jerry Avins <jya@ieee.org> wrote in message news:<3F4ACF3B.62345BC8@ieee.org>...
> Elizabeth wrote: > > > > "Jerry Avins" <jya@ieee.org> wrote in message > > news:3F4A2F2F.EEA60C51@ieee.org... > > > Elizabeth wrote: > > > > > > > > Actually, any explanation that doesn't resort calculus would be > fabulous. > > > > > > Elizabeth, > > > > > > There may be one, but I haven't thought of it yet. One of my armchair > > > pleasures is solving calculus problems without calculus. I started, as > > > far as I know, in the seventh grade. > > > > Let me put it another way. I as I understand it, the sanskrit looking > > formulae that I've been reading about recently are nothing more than > > algorithms. However complex, they can be broken down into a series of steps > > that can surely be explained without resorting to symbolic means. > > > > For purely illustrative purposes, something akin to: > > > > 1. for each peak frequency with an amplitude greater than X > > add cosine(frequency) to a running total > > > > 2. Divide running total by number of peaks > > > > 3. Multiple result by Pi > > > > See what I mean? > > I do indeed see what you mean, and I agree. Consider, though, that > someone conceived of those algorithms. You can be pretty sure that > calculus helped her to express the problem and its solution succinctly > enough to think clearly about it. Without that clear thought, there > would be no algorithm to code. > > Jerry
In my experience it's not "prose or profundity", it's both. The maths makes no sense unless you know what you are trying to achieve with it. And once you know what you want to do, maths is the language of the computer implementation. Rune

Elizabeth wrote:
> > Could someone point me to a reference/example implementation of pitch > detection?
Just compute the normalized ACF of the signal. The maximum lag will give you the pitch value. If the better accuracy is required, you may have to oversample the signal and search the proximity of the previously determined maximum. Vladimir Vassilevsky, Ph.D. DSP and Mixed Signal Design Consultant http://www.abvolt.com
You do not have to use symbolic calculus notation in order to grasp
the main idea of an algorithm, e.g. a pitch detection algorithm.

In fact, calculus can even do some harm as far as the breadth
of an algorithm description is concerned.

For example, take a look at the US Patent Application
"Methods and apparatus for pitch determination" at www.uspto.gov/patft
(Pub. No. 20030088401) 

First claim: clear, broad, comprehensive and no calculus used ...


Regards,

Dmitry Terez
In article <3F4B5F4F.C0B1A262@abvolt.com>,
Vladimir Vassilevsky  <vlv@abvolt.com> wrote:
>Elizabeth wrote: >> Could someone point me to a reference/example implementation of pitch >> detection? > >Just compute the normalized ACF of the signal. The maximum lag will give >you the pitch value.
Won't an ACF, or LMS delay fit algorithm return false positives for multiples of the fundamental wavelength? (e.g. one octave down from the perceived pitch). How does one not return those values as the detected pitch? -- Ron Nicholson rhn AT nicholson DOT com http://www.nicholson.com/rhn/ #include <canonical.disclaimer> // only my own opinions, etc.