I hope there're no vegetarians among us today because I'm going to get straight to the meat!
DirectSoundBuffer.WriteBuffer(start As Long, size As Long, buffer As Any, flags As CONST_DSBLOCKFLAGS)
I wonder if anyone has ever bothered to look at this method of the DirectSoundBuffer object before. I know I certainly hadn't paid it any attention prior to now! But what a thing of beauty she is. All you do is indicate where to write within the buffer (start, usually at the beginning: zero), how much stuff you want to write (size) and what you want to write in that space (buffer). The buffer must be an array of bytes, but you pass only the first element of that array. There's also a flags variable to pass, which can be either DSBLOCK_FROMWRITECURSOR (which writes from the current position of the buffer's playback and ignores the start variable), or DSBLOCK_ENTIREBUFFER (which writes to the entire buffer and ignores the size variable).
As great as WriteBuffer is, we're still not in the clear. We need some method of extracting the byte data from a wave file in order to pass it as our buffer variable, AND we also must find a way to fill a WAVEFORMATEX structure so that we can initialize the buffer correctly when we create it manually. How? Ryan's (not) patented wave file extractor!
'Wave file format info
Private Type WAVETYPE
strHead As String * 12
strFormatID As String * 4
lngChunkSize As Long
intFormat As Integer
intChannels As Integer
lngSamplesPerSec As Long
lngAvgBytesPerSec As Long
intBlockAlign As Integer
intBitsPerSample As Integer
End Type
Global gudtHeader As WAVETYPE
Global glngChunkSize As Long
Global gbytData() As Byte
Sub ExtractWaveData(strFileName As String, lngOffset As Long)
Dim intWAVFile As Integer
Dim i As Long
Dim strTemp As String * 4
Dim blnFound As Boolean
'Open the wave
intWAVFile = FreeFile()
Open strFileName For Binary Access Read Lock Write As intWAVFile
'Get the header info
Get intWAVFile, lngOffset, gudtHeader
'Find the "data" portion of the file
For i = lngOffset To LOF(intWAVFile)
Get intWAVFile, i, strTemp
If strTemp = "data" Then
blnFound = True
Exit For
End If
Next i
'Ensure this is a wave file
If blnFound = False Then
MsgBox "Invalid wave data.", vbCritical, "Invalid Wave"
Close intWAVFile
Exit Sub
End If
'Get the data information
Get intWAVFile, , glngChunkSize
ReDim gbytData(glngChunkSize)
Get intWAVFile, , gbytData
Close intWAVFile
End Sub
This gives us everything we need! We now have the wave data buffer (gbytData) and know its size (glngChunkSize). Also, gudtHeader contains the essential info we need for filling a WAVEFORMATEX structure and initializing a buffer from scratch! Observe:
Public Sub LoadSound(objBuffer As DirectSoundBuffer)
Dim udtBufferDesc As DSBUFFERDESC
Dim udtFormat As WAVEFORMATEX
'Set the Wave Format
With udtFormat
.nFormatTag = gudtHeader.intFormat
.nChannels = gudtHeader.intChannels
.lSamplesPerSec = gudtHeader.lngSamplesPerSec
.nBitsPerSample = gudtHeader.intBitsPerSample
.nBlockAlign = gudtHeader.intBlockAlign
.lAvgBytesPerSec = gudtHeader.lngAvgBytesPerSec
End With
'Create the buffer
udtBufferDesc.lBufferBytes = glngChunkSize
Set objBuffer = mobjDS.CreateSoundBuffer(udtBufferDesc, udtFormat)
'Load the buffer with data
objBuffer.WriteBuffer 0, glngChunkSize, gbytData(0), DSBLOCK_ENTIREBUFFER
End Sub
After extracting the wave data from a file we can run this LoadSound routine to create a buffer and load it properly. I realize this tutorial is quite advanced and hope this sample source code may serve to clarify somewhat.