ModDB Wiki
Advertisement

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.

Advertisement