|
|
Load and Display a Windows Wav Audio File
This application note shows
how to read data from a Windows wav-file and display the sounds in a DynaPlot chart.
The program can read
uncompressed PCM-encoded wave data with 8 or 16 bytes/sample and any number of channels (mono, stereo, quad, etc.). A play function lets you listen to the sound. The code demonstrates how to
pass an array of arrays to DynaPlot.

Reading in the Wave Header
A wav file consists of a header, followed by one or more chunks with format or other information
followed by a data chunk. In order to be able to interpret the data we need to read the format chunk.
|
Private Type FMTCHUNK
Format As Integer NumChannels As Integer SampleRate As Long BytesPerSecond As Long
BytesPerSample As Integer BitsPerSample As Integer End Type
|
From the format chunk we learn
|
 |
The
number of channels
(mono, stereo, etc.). For more than one channel the channel data in the data chunk are interleaved e.g. Left1, Right1, Left2, Right2, etc. and we have to separate the data streams when reading the file.
|
|
 |
The sample rate. We use this information to calculate the time between two samples. This is the increment in our parametric definition of the curves' abscissa values.
|
|
 |
The number of
bits per sample. This tells us, which data type we must use when reading channel data. For 8 bits/sample we use bytes, for 16 bits/sample we use integers.
|
From the length field in the data chunk, which tells us the total length of the following wave data in
bytes, we can compute the number of samples.
|
 |
Number of samples = size of data chunk / (bits per sample / 8) / number of channels
|
With this information at hand we can start reading in the data. To read the samples from the file we
use an array of bytes ReDim ybyte(NumChannels - 1, NumSamples - 1) As Byte and for 16 bit samples we use an array of integers ReDim yshort(NumChannels - 1, NumSamples - 1) As Integer. The layout
of these arrays reflects the interleaved way the samples are stored in the array.
We cannot pass the interleaved channel data to DynaPlot, however. Instead, we allocate Y a
twodimensional array of doubles which will hold our curve data.
|
' must be Doubles for AddParametric
ReDim Y (NumSamples - 1, NumChannels - 1) As Double
|
Notice, how the data are organized here: Y (sample, channel). This way, the samples of one channel
are in a contiguous block in memory an we can pass a pointer to a channel's first sample to DynaPlot's AddParametric method in order to add the channel to the chart.
Once the data have been read from the file, the only thing which remains for us to do is copy the
samples over like in Y(i, c) = yshort(c, i).
Reading in the Wave Data
|
If BitsPerSample = 8 Then
ReDim ybyte(NumChannels - 1, NumSamples - 1) As Byte Get WaveFile, , ybyte ' read data in one go
For i = 0 To NumSamples - 1 For c = 0 To NumChannels - 1
Y(i, c) = ybyte(c, i) - 128 '8 Bits/sample is unsigned Next
Next ElseIf BitsPerSample = 16 Then ReDim yshort(NumChannels - 1, NumSamples - 1) As Integer
Get WaveFile, , yshort ' read data in one go For i = 0 To NumSamples - 1
For c = 0 To NumChannels - 1 Y(i, c) = yshort(c, i)
Next Next Else Close WaveFile
MsgBox BitsPerSample & " bits/sample not supported" Exit Sub End If
|
Displaying the channels
The final step is to pass the channel arrays to DynaPlot for display. We pass pointers to the columns
of Y to DynaPlot's AddParametricCpp method.
|
For c = 0 To NumChannels - 1
DynaPlot1.DataCurves.AddParametricCpp "Channel " & c + 1, 0, 1# / SampleRate, Y(0, c), NumSamples Next
|
The project can also be downloaded:
Download LoadWav.zip
|