Forums

fastest accurate spectrum analyser routine

Started by robert_temp December 8, 2015
Hi,
  I'm implementing a spectrum anaylzer with very limited memory.  My
intention is to provide 1/3 octave bands from 20hz to 5Khz accurate to
+-1db with a 10k sampling rate.  I have .5K of RAM to play with so you can
see my problem!  The platform is an atmega328 with around 8k of code space
left. 
  What does anyone reckon might work, accuracy can drop & sample rate
could be lowered further.
  So far I've been thinking of seeing how fast an IIR filter-bank can run
or maybe sampling, then perform an in-place FFT & have poorly defined
frequency buckets.

cheers,
  Rob


---------------------------------------
Posted through http://www.DSPRelated.com
robert_temp <110751@DSPRelated> wrote:

> I'm implementing a spectrum anaylzer with very limited memory. My > intention is to provide 1/3 octave bands from 20hz to 5Khz accurate to > +-1db with a 10k sampling rate. I have .5K of RAM to play with so you can > see my problem!
I see a problem mainly at the low end of your range. 1/3 octave centered at 20 Hz is 2.7 Hz. Ballpark calculation says you will need 10 * (1 / 2.7) = 3.7 seconds worth of signal to measure that component to 1 dB accuracy. This is more than your total size at the stated sample rate. Therefore you need to decimate to a lower sample rate to analyze the low frequency end of your signal. As you suggest, an IIR filter followed by downsampling is one way to go. It will save you RAM if you incrementaly commute the autocorrelation values over the course of a measurement epoch, and store these in RAM rather than the signal itself. A four-second measurement epoch should be about right. You will find that it is still pretty tight. Sacrificing some accuracy at the low end (20 - 100 Hz range) may be one way out. Good luck Steve
Steve Pope <spope33@speedymail.org> wrote a typo:

>It will save you RAM if you incrementaly commute the autocorrelation
^^^^^^^ That's "compute". Steve
>robert_temp <110751@DSPRelated> wrote: >
[...snip...]
> >I see a problem mainly at the low end of your range. 1/3 octave >centered at 20 Hz is 2.7 Hz.
This calculation puzzles me. One octave down from 20 Hz would be 10 Hz, yes? Consider the following calculations: 2^(1/3) = 1.25992105 2^(1/6) = 1.122462048 20 * 2^(1/6) = 22.44924096 20 / 2^(1/6) = 17.817974363 So a 1/3 Octave band centered at 20 Hz should range from 17.82 Hz to 22.45 Hz or am I missing something? [...snip...]
> >Good luck > >Steve
Ditto. Ced --------------------------------------- Posted through http://www.DSPRelated.com
Cedron <103185@DSPRelated> replies to my post,

>>I see a problem mainly at the low end of your range. 1/3 octave >>centered at 20 Hz is 2.7 Hz.
>This calculation puzzles me. One octave down from 20 Hz would be 10 Hz, >yes?
>Consider the following calculations:
>2^(1/3) = 1.25992105 > >2^(1/6) = 1.122462048
>20 * 2^(1/6) = 22.44924096
>20 / 2^(1/6) = 17.817974363
>So a 1/3 Octave band centered at 20 Hz should range from 17.82 Hz to 22.45 >Hz or am I missing something?
So you get an answer which is (22.45 - 17.82) = 4.63 Hz wide, as opposed to my 2.7 Hz. I'm going to say you are right. Thanks. Steve
>Cedron <103185@DSPRelated> replies to my post, > >>>I see a problem mainly at the low end of your range. 1/3 octave >>>centered at 20 Hz is 2.7 Hz. >
[...snip...]
> >I'm going to say you are right. > >Thanks. > >Steve
I did miss something. It would have been clearer if you said: "1/3 octave centered at 20 Hz is 2.7 Hz wide." I thought you were specifying the low end of the range, my bad. Still, I am not sure how to solve the OP's original problem. The main issue is that doing a DFT (or FFT) gives you "energy values" which are on a linear frequency scale proportional to the bin values whereas he wants his results on a logarithmic scale. It seems he would have to do a big FFT and then sum the energy levels in varying clump sizes as he moves up the scale. A range of 20 Hz to 5000Hz would be a factor of 250 which is roughly eight octaves. Clumping them in 1/3 octave ranges leaves 22 buckets to fill. He'd probably want to do a VonHann window on the signal first to reduce the effects of "leakage". Whether he could reach his 1 db goal with this, I'm not sure. Ced --------------------------------------- Posted through http://www.DSPRelated.com
On 08.12.2015 21:54, robert_temp wrote:
> Hi, > I'm implementing a spectrum anaylzer with very limited memory. My > intention is to provide 1/3 octave bands from 20hz to 5Khz accurate to > +-1db with a 10k sampling rate. I have .5K of RAM to play with so you can > see my problem! The platform is an atmega328 with around 8k of code space > left. > What does anyone reckon might work, accuracy can drop & sample rate > could be lowered further. > So far I've been thinking of seeing how fast an IIR filter-bank can run > or maybe sampling, then perform an in-place FFT & have poorly defined > frequency buckets. > > cheers, > Rob > > > --------------------------------------- > Posted through http://www.DSPRelated.com >
Hi, I remember reading several pages about filters for 1/N octave bands in the yellow book by fred harris ("Multirate Signal Processing for Communication Systems"). It seemed very relevant and involved, although I have forgotten most of that. Evgeny.
Cedron <103185@DSPRelated> wrote:

>Still, I am not sure how to solve the OP's original problem. The main >issue is that doing a DFT (or FFT) gives you "energy values" which are on >a linear frequency scale proportional to the bin values whereas he wants >his results on a logarithmic scale.
That is correct. The OP will first need to split the problem into two analyses: a low-frequency analyses say from 20 - 500 Hz, at a reduced sample rate (let's say 1250 Hz); then an analysis up to 5 KHz, with a resolution on the order of 100 Hz. Then for each of these, some binning of bins (so to speak) is needed to get to 1/3-octave output results. Steve
>Cedron <103185@DSPRelated> wrote: > >>Still, I am not sure how to solve the OP's original problem. The main >>issue is that doing a DFT (or FFT) gives you "energy values" which are
on
>>a linear frequency scale proportional to the bin values whereas he
wants
>>his results on a logarithmic scale. > >That is correct. The OP will first need to split the problem into >two analyses: a low-frequency analyses say from 20 - 500 Hz, at >a reduced sample rate (let's say 1250 Hz); then an analysis >up to 5 KHz, with a resolution on the order of 100 Hz. > >Then for each of these, some binning of bins (so to speak) is >needed to get to 1/3-octave output results. > >Steve
Yes, but he only has .5K of RAM to work with, so maybe he is better off doing a Goertzel (or two or three) at each of the frequencies he is interested in and somehow deriving an energy level for each neighborhood. Ced --------------------------------------- Posted through http://www.DSPRelated.com
On Tue, 08 Dec 2015 12:54:44 -0600, robert_temp wrote:

> Hi, > I'm implementing a spectrum anaylzer with very limited memory. My > intention is to provide 1/3 octave bands from 20hz to 5Khz accurate to > +-1db with a 10k sampling rate. I have .5K of RAM to play with so you > can see my problem! The platform is an atmega328 with around 8k of code > space left. > What does anyone reckon might work, accuracy can drop & sample rate > could be lowered further. > So far I've been thinking of seeing how fast an IIR filter-bank can > run > or maybe sampling, then perform an in-place FFT & have poorly defined > frequency buckets. > > cheers, > Rob
The constant Q transform works with logarithmically spaced "bins" and might suit your needs. I found the Wikipedia article not very satisfactory. https://en.wikipedia.org/wiki/Constant_Q_transform My explanation is different: Design three BP filters for your 1/3 octave bands, and a lowpass filter that selects the octave below. Then decimate the lowpass output by 2 and reuse the exact same filter kernels (this time at half the sample rate) on the decimated lowpass output. Repeat for as many octaves as you want. This can be computationally efficient, because at each sample you only need to calculate the filters for two octaves (independent of the total number of octaves). Example schedule (n is top octave, n-1 is 2nd top octave, etc): 1 n, n-1 2 n, n-2 3 n, n-1 4 n, n-3 5 n, n-1 6 n, n-2 7 n, n-1 8 n, n-4 9 n, n-1 10 n, n-2 11 n, n-1 12 n, n-3 13 n, n-1 14 n, n-2 etc. I believe this schedule is simple to do if your CPU has a "count trailing zeros" or equivalent instruction. The main (and possibly fatal) downfall of this design is that the lowpass filter accuracy matters a lot, as the lower octaves get filtered by it multiple times. I've no idea whether that fits into 8k of code space. Regards, Allan