I am trying to plot out waveform data visually like in audacity. I really like the way it looks in audacity. I am having somewhat of a problem though.
So say I have a 2 minute long song that is consistent of tens of thousands of samples but I only have say 800 pixels wide to display this sound.
This means I have to take say 100 samples (50 left and 50 right) and somehow display this information with a line only 1 pixel wide.
I have tried to average the sound but mostly it will always turn out to be 0 since likely a lot of the samples are low. So if there is a quick snare stab in that timeframe I would want to be able to see that sound rather than the 25 samples of nothing that came before it.
Are there any well known solutions to combat this problem?
A real world click or intentional sound would be wider than an individual sample. If you are trying to detect audio above
0 dB, try View > Show Clipping or Analyze > Find Clipping (both in Audacity Beta). Or click the menu in the track name and look at the Spectrum View. That should show areas of greater energy with a frequency scale on the vertical axis. You can also plot out Energy against Frequency for a selection at Analyze > Plot Spectrum and print a text file of the data.
You can also obtain a sample export plug-in to export a text plot of sample amplitude against time. See how to install Nyquist plug-ins.
Gale
Thanks Bill. That helped. I found the part of audacity’s code where it displays the waveform, which I believe is GetWaveDisplay in the Sequence.cpp class. It’s difficult me to decipher exactly what’s going on there, though.
Right now I am able to get the waveform to draw, but the wave looks strange. The peaks are really peaky. Another problem is that sometimes even though two different sounds may sound the same volume to my ears, the application draws them at very different volumes. I don’t expect anyone to spend very much time looking at my code, but maybe if any audacity contributors are around they could help explain to me what I’m doing wrong or explain the algorithm used to draw a waveform out of many samples. Basically I am doing a few things here.
First I am taking a range of samples based on the scale I want to draw the waveform at.
Next I am finding the highest sample in the range and drawing that.
Finally, with the lighter blue color I am drawing the average volume of the range of samples.

private function extractWaveform(samples:ByteArray, waveform:Sprite,height:int,scale:int):void {
this.scale = scale;
samples.position = 0;
// Build waveform
var monoLow:Number;
var monoHigh:Number;
var rect:Rectangle = new Rectangle(0, 0, 1, 0);
var rect2:Rectangle = new Rectangle(0, 0, 1, 0);
for (var i:int=0; i<Math.floor(samples.length/(100*scale*8)); i++)
{
samples.position = i*(100*scale*8);
var peak:Number = 0;
var peakAverage:Number = 0;
for (var j:int = 0; j < (100*scale); j++) {
var l:Number = samples.readFloat();
var r:Number = samples.readFloat();
if (l+r > peak) {
peak = l+r;
}
peakAverage+= Math.abs(l+r);
}
monoHigh = (peak)/2;
monoLow = peakAverage/(100*scale);
if (monoHigh>2) monoHigh=2;
if (monoHigh<-2) monoHigh=-2;
rect.height = ((monoHigh*height)/10)*10;
rect.x = i;
rect.y = 0;
rect.y = (height - rect.height) / 2;
rect2.height = ((monoLow*height)/10)*10;
if (rect2.height<2) rect2.height=2;
rect2.x = i;
rect2.y = 0;
rect2.y = (height - rect2.height) / 2;
waveform.graphics.beginFill(0x434cd2);
waveform.graphics.drawRect(rect.x,rect.y,rect.width,rect.height);
waveform.graphics.beginFill(0x787de2);
waveform.graphics.drawRect(rect2.x,rect2.y,rect2.width,rect2.height);
}
}
Obviously, there is no perfect solution. I haven’t studied the Audacity code.
I think a common way of displaying waveforms is just to display every nth sample (i.e. n = number of samples in displayed range/number of pixels in window). This method can (will) miss some peaks, but it seems to be acceptable. Since the number of samples in the waveform and the audio frequency are uncorrelated to the number of available pixels, this is essentially a random sampling (of the sample sequence) and it gives a useful representation of the general waveform, ( or waveform-envelope at lower “zoom” levels). At least it should be useful for editing purposes.