![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
I know there are better places to ask this, but there's been a fair amount of
signal processing talk around here in recent history, and everything I google
comes up with patents and microprocessor talk.
The basic situation is that I want to program a piano tuner (we'll see about
having the guts to tune the thing). It didn't take more than a couple hours to
write a c program that takes audio input, FFT's it, and tells you the closest
pitch. The problem is the frequency resolution. I essentially get the refresh
rate for resolution, e.g. 10 updates per second -> 10 Hz resolution. This
resolution won't cut it. G#4 is 415.3 Hz, A4 is 440 Hz, and A#4 is 466.164 Hz,
so you can see what I'm up against. Here are my ideas:
1) Zero-pad the data pre-fft. (I'm not sure whether this actually improves the
quality of the information.)
2) Use a feedback loop to control the frequency of a test wave. (I don't know
what the controller should look like.)
3) FFT. Locate max. Band-pass. Inverse-fft. Count zero-crossings? (Not
robust for noisy signals?)
As I said, my lack of knowledge in this area makes it difficult to locate the
relevant resources. Does anyone know of a feedback loop or other more
sophisticated tools for this purpose?
- Ricky
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 15-3-2009 5:42, triple_r wrote:
> I know there are better places to ask this, but there's been a fair amount of
> signal processing talk around here in recent history, and everything I google
> comes up with patents and microprocessor talk.
>
> The basic situation is that I want to program a piano tuner (we'll see about
> having the guts to tune the thing). It didn't take more than a couple hours to
> write a c program that takes audio input, FFT's it, and tells you the closest
> pitch. The problem is the frequency resolution. I essentially get the refresh
> rate for resolution, e.g. 10 updates per second -> 10 Hz resolution.
That is not true. Your resolution mainly depends on your sampling
frequency. The only way you can get a resolution of 10 Hz with 10 Hz
updates is by sampling at 1kHz, which is much too low for your
application anyway.
Your resolution can be computed by dividing your sample frequency by the
number of samples.
> This
> resolution won't cut it. G#4 is 415.3 Hz, A4 is 440 Hz, and A#4 is 466.164 Hz,
> so you can see what I'm up against. Here are my ideas:
>
> 1) Zero-pad the data pre-fft. (I'm not sure whether this actually improves the
> quality of the information.)
It might sharpen your peaks as would using a Hamming or Hanning window.
I think I would also use overlapping windows to increase the number of
samples. I.e. if the sampling is more a problem than the computational
power.
>
> 2) Use a feedback loop to control the frequency of a test wave. (I don't know
> what the controller should look like.)
Me neither ;) I actually don't know what you mean.
> 3) FFT. Locate max. Band-pass. Inverse-fft.
You know what frequency you are expecting, so you don't need to locate
your maximum. Then the problem is more easily solved by a filter in the
time domain.
> Count zero-crossings? (Not robust for noisy signals?)
depends on the bandwidth of the filter. Can be very robust. Note that
some instruments have higher amplitude for harmonics than at the
fundamental frequency. There is also no guarantee that you get only 2
zero crossings because of the harmonics. A narrow bandwidth filter will
indeed solve most of these problems. BTW how are you going to count
exactly 93.2328 crossings with your 10 updates per second?
>
> As I said, my lack of knowledge in this area makes it difficult to locate the
> relevant resources. Does anyone know of a feedback loop
Do you want a pure digital solution or an mixed distal/analog or even a
pure analog?
You may want to have a look at phase locked loops, because you can
digitize the voltage that drives the frequency.
> or other more
> sophisticated tools for this purpose?
I think you can buy them, at least I knew them for guitars... Yep, you
can find them by googling. Not as much fun as building one oneself though.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
triple_r wrote:
> 1) Zero-pad the data pre-fft. (I'm not sure whether this actually improves the
> quality of the information.)
>
> 2) Use a feedback loop to control the frequency of a test wave. (I don't know
> what the controller should look like.)
>
> 3) FFT. Locate max. Band-pass. Inverse-fft. Count zero-crossings? (Not
> robust for noisy signals?)
What about using correlation with the desired frequency sine or cosine
wave? This is essentially what DFT does is correlate input data with a
series of cosines and sines to get the data into the frequency domain.
Alternatively, you may be able to use a much larger FFT and get a better
frequency resolution.
I have seen software that can analyze a signal and give its pitch,
though I'm not sure how it works. I'm sure it's using an FFT, it might
be using some means of interpolation to estimate where the peak really
sits.
--
~Mike
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
andrel <a_l### [at] hotmail com> wrote:
> Your resolution can be computed by dividing your sample frequency by the
> number of samples.
Thanks for all of your input!
The number of samples is the sample frequency * the sample duration. So if the
sample duration is 1/10 second, then this is 44100 / (44100*1/10) = 10 Hz.
> > 1) Zero-pad the data pre-fft.
> It might sharpen your peaks as would using a Hamming or Hanning window.
> I think I would also use overlapping windows to increase the number of
> samples.
Overlap the windows? Do you mean something like Welch's method? I could
combine one sample with some adjacent samples as long as the duration is still
relatively short. I'll try that. Thanks.
> > 2) Use a feedback loop to control the frequency of a test wave.
> Me neither ;) I actually don't know what you mean.
That makes two of us. I just thought it might be possible to have an output
wave sin(omega*t) and dynamically adjust omega to match the signal. This was a
VERY rough interpretation of circuits that would do the same. This didn't give
me much to go on:
http://en.wikipedia.org/wiki/Frequency-locked_loop
> You know what frequency you are expecting, so you don't need to locate
> your maximum.
Ideally I wouldn't know in advance. I play a note on the piano and it locates
the nearest key and tells the error. This is how most musical tuners work.
> > Count zero-crossings? (Not robust for noisy signals?)
> depends on the bandwidth of the filter. Can be very robust. ...
> BTW how are you going to count
> exactly 93.2328 crossings with your 10 updates per second?
I guess you'd have to take into account the exact time for the first and last
crossing. That was my fear, though, that you'd get spurious crossings from
even slightly higher harmonics.
> You may want to have a look at phase locked loops, because you can
> digitize the voltage that drives the frequency.
Maybe that would be wise. I'll see what I can find.
> > or other more sophisticated tools for this purpose?
> I think you can buy them, at least I knew them for guitars... Yep, you
> can find them by googling. Not as much fun as building one oneself though.
Certainly not! As an update, I used PortAudio, OpenGL, and FFTW to put a
spectrum on top of a keyboard. You can follow some of the Chopin nocturnes
pretty well, but it doesn't pick up low frequencies well. As for my sister's
piano, it looks to be at least fifty cents low, but it still plays just fine!
- Ricky
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> The basic situation is that I want to program a piano tuner (we'll see
>> about
>> having the guts to tune the thing). It didn't take more than a couple
>> hours to
>> write a c program that takes audio input, FFT's it, and tells you the
>> closest
>> pitch. The problem is the frequency resolution. I essentially get the
>> refresh
>> rate for resolution, e.g. 10 updates per second -> 10 Hz resolution.
>
> That is not true. Your resolution mainly depends on your sampling
> frequency.
I thought that if you did an FFT on 0.1 seconds of data the frequency
resolution would always be 10 Hz, no matter what sampling rate you used?
AIUI using higher sampling rates just lets you identify higher frequencies,
if you want more frequency resolution you need longer sample times. Hence I
recommend the OP just uses 2 seconds of audio data for the FFT rather than
0.1 seconds.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Mike Raiford <"m[raiford]!at"@gmail.com> wrote:
> What about using correlation with the desired frequency sine or cosine
> wave? This is essentially what DFT does is correlate input data with a
> series of cosines and sines to get the data into the frequency domain.
Signal -> frequency domain = spectrum
Sine wave -> frequency domain = delta function
Correlation in frequency domain = product.
In other words, this just picks off the nearest frequency (since it probably
won't fit exactly on the scale). I'm not sure this will improve the precision
quite enough.
>
> Alternatively, you may be able to use a much larger FFT and get a better
> frequency resolution.
You're limited if you want good temporal resolution too.
> I have seen software that can analyze a signal and give its pitch,
> though I'm not sure how it works. I'm sure it's using an FFT, it might
> be using some means of interpolation to estimate where the peak really
> sits.
I would assume those cheap electronic tuners must be using some sort of feedback
loop since they're certainly not FFT'ing it. So far, the FFT method works
acceptably well, but I'm still curious how it should be done properly. Thanks
for the advice!
- Ricky
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 16-3-2009 16:49, triple_r wrote:
> andrel <a_l### [at] hotmail com> wrote:
>> Your resolution can be computed by dividing your sample frequency by the
>> number of samples.
>
> Thanks for all of your input!
>
> The number of samples is the sample frequency * the sample duration. So if the
> sample duration is 1/10 second, then this is 44100 / (44100*1/10) = 10 Hz.
<slaps head> Sorry, apparently problems with concentration yesterday.
>
>>> 2) Use a feedback loop to control the frequency of a test wave.
>> Me neither ;) I actually don't know what you mean.
>
> That makes two of us. I just thought it might be possible to have an output
> wave sin(omega*t) and dynamically adjust omega to match the signal. This was a
> VERY rough interpretation of circuits that would do the same. This didn't give
> me much to go on:
>
> http://en.wikipedia.org/wiki/Frequency-locked_loop
That refers yo the PLL as the main article. Anyway it assumes you know
the frequency.
>> You know what frequency you are expecting, so you don't need to locate
>> your maximum.
>
> Ideally I wouldn't know in advance. I play a note on the piano and it locates
> the nearest key and tells the error. This is how most musical tuners work.
>
>>> Count zero-crossings? (Not robust for noisy signals?)
>> depends on the bandwidth of the filter. Can be very robust. ...
>> BTW how are you going to count
>> exactly 93.2328 crossings with your 10 updates per second?
>
> I guess you'd have to take into account the exact time for the first and last
> crossing. That was my fear, though, that you'd get spurious crossings from
> even slightly higher harmonics.
One thing you might do when you do know what string you will be working
on is adjusting the sampling frequency so that the one you are looking
for exactly fits.
When trying to fit powerline interference if it does not fit the
sampling I use another trick. (powerline is 50Hz here, but my main AD
system is 2048 Hz and even when it would have been 2000.000Hz the
interference would still be often a fraction because it is slightly
varying in time). What I do is not use an fft but compute a match with a
sine and cosine of the fractional frequency over an interval that is as
close as possible to an integer number of that sine. I.e. for your A4#
at 44100Hz and taking roughly 10 updates per second, youd'd have 46.6164
cycles. Which explains the why you'd have a somewhat broadened peak.
If you take eg. 4446 samples you should have nearly 47 complete cycles.
(all modulo computational errors, I have the same problem as yesterday
only slightly different)
>>> or other more sophisticated tools for this purpose?
>> I think you can buy them, at least I knew them for guitars... Yep, you
>> can find them by googling. Not as much fun as building one oneself though.
>
> Certainly not! As an update, I used PortAudio, OpenGL, and FFTW to put a
> spectrum on top of a keyboard. You can follow some of the Chopin nocturnes
> pretty well, but it doesn't pick up low frequencies well. As for my sister's
> piano, it looks to be at least fifty cents low, but it still plays just fine!
You apparently do not have absolute pitch.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> What about using correlation with the desired frequency sine or cosine
>> wave? This is essentially what DFT does is correlate input data with a
>> series of cosines and sines to get the data into the frequency domain.
>
> Signal -> frequency domain = spectrum
> Sine wave -> frequency domain = delta function
> Correlation in frequency domain = product.
DFT performs a correlation in the time domain, which is a convolution of
the frequency domain. It then sums the result in the time domain. (I
have no idea what this means in the frequency domain.)
> In other words, this just picks off the nearest frequency (since it probably
> won't fit exactly on the scale). I'm not sure this will improve the precision
> quite enough.
What I would do is try to correlate the input signal to the frequencies
of several adjacent notes. Whichever one has the highest correlation,
that's what note you have tuned. Adjust the tuning until the desired
pitch shows maximum correlation. (The correlation will also depend on
note amplitude of course...)
>> Alternatively, you may be able to use a much larger FFT and get a better
>> frequency resolution.
>
> You're limited if you want good temporal resolution too.
Yes. Better frequency resolution = worse temporal resolution.
> I would assume those cheap electronic tuners must be using some sort of feedback
> loop since they're certainly not FFT'ing it. So far, the FFT method works
> acceptably well, but I'm still curious how it should be done properly. Thanks
> for the advice!
As I say, I'd go with generating a sine and cosine wave for each note of
the scale and checking the correlation factors. But that's just me...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |