DSPRelated.com
Forums

Help processing a WAV file to get peak amplitude at specified frequencies at an interval

Started by Aaron Newsome December 26, 2006
Hi guys, I'm a newbie at signal processing, DSP, FFTs and all this
stuff I'm trying to learn about. When I first set out on this mission,
I thought it would be pretty easy to find a program that has already
been created that would do this. I'm not much of a programmer, but I do
know some perl so that's where I looked first, a perl module that would
do exactlty what I am looking for. No luck. I think what I want to do
is VERY simple, but apparently no one has ever needed this before and
has written a program to do it. Here is what I need:

Open wav file, get the peak amplitude at specific frequencies at a
specific interval (say 30 times per second) and write that information
to a text file.

I've found exactly ONE program that can do this. SpecLab. SpecLab is
the only program I've found that can do this but it does it perfectly.
The text file it creates is parsed and read perfectly by my application
and it's a workable solution. Problem is, my application runs on Linux
(perl based) and SpecLab is Windows only. Even worse, it's a GUI
program that does about 100 other things I don't need. It can't be run
from the command line and can't be well integrated into the automated
nature of the rest of my programs.

SpecLab is VERY full featured and it does a bunch of stuff like read
audio from soundcard in realtime, different sample rates, waterfall
plots and all kinds of stuff.

I don't need variable intervals, I just need 30/sec (or more
specifically 29.907/sec), I don't need variable sample rates, I don't
need realtime anything. Just open a wav file, do some analysis and
write a text file.

Does anyone have any clues to a command line application (preferrably
Linux, preferrably Perl) to do this with. If someone knows any perl
snippets and modules to point me at, I can probably figure it out. I'm
not that good with figuring out C code or most other languages but if
anyone has any of those snippets, I guess I could look at those too.

I just find it hard to believe, that a program such as this does not
exist at all.

Thanks in advance for all your help everyone. You guys are a lot
smarter at this than I am.

Aaron  Newsome wrote:
> Here is what I need: > > Open wav file, get the peak amplitude at specific frequencies at a > specific interval (say 30 times per second) and write that information > to a text file.
How many specific frequencies are there for which you require information? What is the frequency bandwidth, amplitude accuracy, time accuracy and computational performance you require? How much noise do you need to reject? An IIR + an averager can be implemented in very few lines of perl... all the way to much more sophisticated and larger packages, depending on your needs and what you consider an adequate quality of solution. IMHO. YMMV. -- rhn A.T nicholson d.0.t C-o-M
Aaron Newsome wrote:

> Hi guys, I'm a newbie at signal processing, DSP, FFTs and all this > stuff I'm trying to learn about.
"Newbie's" very welcome by this group. I'm one. I've gotten educational answers to any question I've asked. Not necessarily what I wanted to hear. Get idea I'm trying to break it to you gently ;)
> When I first set out on this mission, > I thought it would be pretty easy to find a program that has already > been created that would do this. I'm not much of a programmer, but I do > know some perl so that's where I looked first, a perl module that would > do exactlty what I am looking for. No luck. I think what I want to do > is VERY simple,
a fellow newbie chuckles WITH you.
> but apparently no one has ever needed this before and > has written a program to do it. Here is what I need: > > Open wav file, get the peak amplitude at specific frequencies at a > specific interval (say 30 times per second) ...
That's were everything falls apart. I'll let experts of group take over at this point. I've enough of an understanding to know you are in trouble at this point, but not enough to say why.
> I've found exactly ONE program that can do this. SpecLab. [*SNIP*]
Can you give a URL for "SpecLab"? A Google search gave too many unrelated hits. Tell us more of what you wish to accomplish.
Richard Owlett wrote:
> Aaron Newsome wrote: > > > I've found exactly ONE program that can do this. SpecLab. [*SNIP*] > > Can you give a URL for "SpecLab"? > A Google search gave too many unrelated hits. > > Tell us more of what you wish to accomplish.
I downloaded SpecLab by following the links here: http://freenet-homepage.de/dl4yhf/spectra1.html Again, SpecLab does do exactly what I need. I'll compose another posting that explains this a little better in case I wasn't clear enough in my original post. I can also explain why this only needs to be psuedo scientific and not necessarily 100% accurate.
Ron N. wrote:
> Aaron Newsome wrote: > > Here is what I need: > > > > Open wav file, get the peak amplitude at specific frequencies at a > > specific interval (say 30 times per second) and write that information > > to a text file. > > How many specific frequencies are there for which you require > information? What is the frequency bandwidth, amplitude accuracy, > time accuracy and computational performance you require? How > much noise do you need to reject? > > An IIR + an averager can be implemented in very few lines of perl... > all the way to much more sophisticated and larger packages, > depending on your needs and what you consider an adequate > quality of solution. > >
Ok, sorry the original post was not clear. I know it's hard to get help if the people helping you don't know what you are trying to accomplish. Maybe it's better If I just explain how I work with SpecLab to get what I need. First I setup the program to use wav file for input. Then I set it up for text file export. I define the text file export to have "30 columns", 30 columns is the max you can have. In SpecLab I can define the formula (in their definition language) for what each of the columns will be. Like this: peak_a(20, 25) peak_a(25, 40) peak_a(40, 60) and so on The peak_a() function will print the amplitude of the frequencies in the parenthesis. I guess it uses some kind of averaging, I really don't know. It's not important. I actually defined my columns using the boundaries around 1/3 octave frequencies, starting at 20Hz but I don't remember what those numbers are but you get the idea. The frequencies really don't need to be precise and I don't care how many db/Octave rolloff filtering is used on the data or whatever. Something reasonable I suppose. What was important is that I get about 30 columns of amplitiude data spread over the 20-16khz frequency range. I setup SpecLab to sample every 33ms. This was as close as I could get to the 29.907 frames per second that I was trying to achieve. So SpecLab steps through the audio file and for every 33ms of sound, it prints a line to a text file that looks something like this: -77,-68,-67,-68,-72,-69,-69,-70,-66,-54,-48,-53,-48,-49,-64,-45,-52,-52,-60,-66,-42,-45,-42,-41,-46,-50,-31,-18,-41, 30 columns of amplitude info from the wav file, at that time interval. I have no idea if it's taking a specific sampling of amplitude from that instance, or average the amplitudes since 33 ms ago. I don't really know. It's not important. Then what I do with the text file is, I wrote a script to parse each line and create, you guessed it, a specrtum analyzer image. Then, as you could probably guess, I take all of those graphic files and create an MPEG file, muxed with the audio. The resulting mpeg file is just eye candy. The precision of the analysis is not that important at this point. It's just eye candy. The blinkenlights bouncing around on the screen in sync to the music is very cool though. My first pass at this using SpecLab turned out pretty well. It's just waaay too much of a manual process. I just need to figure some way to get the amplitude data in perl, the way I need it. Hope that clears things up a bit. Thanks again for all your help everyone.
Aaron  Newsome skrev:

> I think what I want to do > is VERY simple, but apparently no one has ever needed this before and > has written a program to do it. Here is what I need:
I like the way you think: You have an apparently simple straight-forward problem, but for some reason it seems that no one have encountered it -- or at least produced a solution -- before. This is what ought to set of the warning bells in your mind. Ask yourself some control questions: - Am I the first to encounter ths problem? - If no, why does no solution exist? If you *are* the first person ever to encounter a problem, you might ask yourself why the problem is relevant. It is a chance that you have become lost somewere. If others have encountered the problem before, and the problem is relevant, and no solutions *still* are not available, chances are that there are good reasons for a solution not being available.
> Open wav file, get the peak amplitude at specific frequencies at a > specific interval (say 30 times per second) and write that information > to a text file.
Lots of people would find such a utility useful...
> I've found exactly ONE program that can do this.
The warning bells should be wrecking havoc by now... The problem you have encountered has several names, "Heisenbergs uncertainty principle" is one, "the time-frequency resolution limit" is another. To make a long story short, the thing is that you need an observation of a certain duration T in order to isolate a sinusoidal with a certain resolution dF of the frequency. Roughly speaking, the relation goes as dF = 2*pi/T With the numbers you state, the duration of the frames is on the order of 1/30 s, meaning you can get bands roughly 200 Hz wide. I would guess that the program you found uses some sort of spectrogram. It is no problem to make a time-frequency representation of the signal at arbitrary apparent density in both time and frequency. The problem is that the features visible in the pectrogram still obey the resolution limits. Rune
Rune Allnor wrote:
> > Open wav file, get the peak amplitude at specific frequencies at a > > specific interval (say 30 times per second) and write that information > > to a text file.
...
> The problem you have encountered has several names, > "Heisenbergs uncertainty principle" is one, "the time-frequency > resolution limit" is another. > > To make a long story short, the thing is that you need an > observation of a certain duration T in order to isolate a sinusoidal > with a certain resolution dF of the frequency. Roughly speaking, > the relation goes as > > dF = 2*pi/T > > With the numbers you state, the duration of the frames is on the > order of 1/30 s, meaning you can get bands roughly 200 Hz wide.
I think you've misinterpreted his problem. He want peak amplitude at specific intervals, not of specific time frame widths. Frequency resolution to meet his requirements can be had by sizing the frame to the required width completely independently from the frame offset required for successive time intervals. Furthermore, one doesn't need to use just a single frame width for a particular time frequency point. IMHO. YMMV. -- rhn A.T nicholson d.0.t C-o-M
>Then what I do with the text file is, I wrote a script to parse each >line and create, you guessed it, a specrtum analyzer image. Then, as >you could probably guess, I take all of those graphic files and create >an MPEG file, muxed with the audio. The resulting mpeg file is just eye >candy. The precision of the analysis is not that important at this >point. It's just eye candy. The blinkenlights bouncing around on the >screen in sync to the music is very cool though. > >My first pass at this using SpecLab turned out pretty well. It's just >waaay too much of a manual process. I just need to figure some way to >get the amplitude data in perl, the way I need it. > >Hope that clears things up a bit. > >Thanks again for all your help everyone. > >
Ron, I believe what you are looking for is a spectrogram plot. This is something that Speech Guys like to use a lot because you can visually see phonemes (basic parts of speech). It should look something like this: http://en.wikipedia.org/wiki/Image:Spectrogram_-minato-.png Basically, to get a spectrogram you run a FFT one window at a time on your wav file. The width of the window (number of samples) depends on 2 things: 1) Your sample rate (found in WAV header) 2) The granularity of frequency points For example if you perform a FFT of 1024 points and your sample rate is 48kHz, you will have frequencies at 0 Hz, 46.875Hz, 93.75Hz etc. You will not get data in-between these points. This ganularity is calculated by: (Sample Rate / points). Keep in mind that: ------------------ 1.) A FFT generates points (aka bins) for all frequencies up to the sample rate. But we know that due to Nyquist, only the first half of points are meaningfull. In fact the top half is the mirror image of the bottom. 2.) FFT algorithms return the vector as a complex number. To get the amplitude of each bin you must find the Magnitude of the complex number then convert it to dB. 3.) You will have to window the signal before sending it to the FFT function. If you don't you're high frequencies won't be accurate. Use something like a hamming window. 4.) Don't forget to slide your window and FFT accross your signal in the amounts that you want (33ms) If you want to do this yourself, I'd recommend searching for a perl FFT function and going from there. At any rate, I'd say this is of medium complexity for the average DSP guy. The theory isn't so hard if you know this stuff, but the implementation is always a bear. Not sure if this helps, but I found a spectrogram program here for windows: http://ece-www.colorado.edu/~mathys/ecen1200/hwcl09/index.html You may want to see if you can emulate a windows system to get this running. Jeff
Ron N. wrote:

> I think you've misinterpreted his problem. He want peak amplitude > at specific intervals, not of specific time frame widths.
This is trivial with libsndfile: http://www.mega-nerd.com/libsndfile/ Someone has even written Perl bindings for it (find them with Google). Erik -- +-----------------------------------------------------------+ Erik de Castro Lopo +-----------------------------------------------------------+ "Every time you get a windows programmer asking you to write some ass-backward workaround, think of it as a crack junkie asking you to help stuff his pipe because his hands are too shaky." -- Conrad Parker
Ron N. skrev:
> Rune Allnor wrote: > > > Open wav file, get the peak amplitude at specific frequencies at a > > > specific interval (say 30 times per second) and write that information > > > to a text file. > ... > > > The problem you have encountered has several names, > > "Heisenbergs uncertainty principle" is one, "the time-frequency > > resolution limit" is another. > > > > To make a long story short, the thing is that you need an > > observation of a certain duration T in order to isolate a sinusoidal > > with a certain resolution dF of the frequency. Roughly speaking, > > the relation goes as > > > > dF = 2*pi/T > > > > With the numbers you state, the duration of the frames is on the > > order of 1/30 s, meaning you can get bands roughly 200 Hz wide. > > I think you've misinterpreted his problem. He want peak amplitude > at specific intervals, not of specific time frame widths.
What's the difference? The uncertainty principle is valid regradless of whether the filter bank is implemented as DFTs of frames, or as filters.
> Frequency > resolution to meet his requirements can be had by sizing the frame > to the required width completely independently from the frame offset > required for successive time intervals. Furthermore, one doesn't > need to use just a single frame width for a particular time frequency > point.
The OP aims to track variations on the order of 30 ms. That requirement translates directly to a ~200Hz bandwidth of his filters. Rune