How do I visualize audio data?

algorithm, audio, graphics, language-agnostic, math

Solution

You'll likely have more than 1 sample for each pixel. For each group of samples mapped to a single pixel, you could draw a (vertical) line segment from the minimum value in the sample group to the maximum value. If you zoom in to 1 sample per pixel or less, this doesn't work anymore, and the 'nice' solution would be to display the sinc interpolated values. Because DrawLine cannot paint a single pixel, there is a small problem when the minimum and maximum are the same. In that case you could copy a single pixel image in the desired position, as in the code below:

double samplesPerPixel = (double)L / _width;
double firstSample = 0;
int endSample = firstSample + L - 1;
for (short pixel = 0; pixel < _width; pixel++)
{
    int lastSample = __min(endSample, (int)(firstSample + samplesPerPixel));
    double Y = _data[channel][(int)firstSample];
    double minY = Y;
    double maxY = Y;
    for (int sample = (int)firstSample + 1; sample <= lastSample; sample++)
    {
        Y = _data[channel][sample];
        minY = __min(Y, minY);
        maxY = __max(Y, maxY);
    }
    x = pixel + _offsetx;
    y1 = Value2Pixel(minY);
    y2 = Value2Pixel(maxY);
    if (y1 == y2)
    {
        g->DrawImageUnscaled(bm, x, y1);
    }
    else
    {
        g->DrawLine(pen, x, y1, x, y2);
    }
    firstSample += samplesPerPixel;
}

Note that Value2Pixel scales a sample value to a pixel value (in the y-direction).

Problem

I would like to have something that looks something like this. Two different colors are not nessesary. (source: sourceforge.net) I already have the audio data (one sample/millisecond) from a stereo wav in two int arrays, one each for left and right channel. I have made a few attempts but they don't look anywhere near as clear as this, my attempts get to spikey or a compact lump. Any good suggestions? I'm working in c# but psuedocode is ok. Assume we have - a function DrawLine(color, x1, y1, x2, y2) - two int arrays with data right[] and left[] of lenght L - data values between 32767 and -32768 If you make any other assumptions just write them down in your answer. ``` for(i = 0; i < L - 1; i++) { // What magic goes here? } ``` This is how it turned out when I applied the solution Han provided. (only one channel) alt text http://www.imagechicken.com/uploads/1245877759099921200.jpg

Original source