DirectSound: SecondaryBuffer to Base64, please help me.

Fabian_Russ

Newcomer
Joined
Sep 29, 2008
Messages
23
Hello, for three days now, I have been working with DirectSound, and have ran into a pretty big issue.

I cannot figure out how to return a byte array from the SecondaryBuffer, I understand how to create the secondary buffer from a memory stream but not vice-versa, I need to either:

A: Read the SecondaryBuffer to a Memory stream.
B: Read the SecondaryBuffer to a Byte array.

Here is what I have so far (please let me know if there is anything I can improve):

-------------------------------------------------------------------------

Public Class DSound2
Public DSDevice As DirectSound.Device
Public DSBuffers As New List(Of DirectSound.SecondaryBuffer)

Public Sub Save(ByVal Path As String)
'Create directory if it does not exist.
If Not IO.Directory.Exists(Path.Remove(Path.LastIndexOf("\"))) Then
IO.Directory.CreateDirectory(Path.Remove(Path.LastIndexOf("\")))
End If

'Create file if it does not exist and close it.
If Not IO.File.Exists(Path) Then
IO.File.Create(Path).Close()
End If

'Declare storage for SecondaryBuffer
Dim StreamBytes As Byte() = New Byte(39999) {}
Dim StreamDat As New IO.MemoryStream(StreamBytes, 0, 40000, True, True)

'Loop through each SecondaryBuffer, returning data to StreamDat.
For Each File In DSBuffers
'File.Read seems to never return the correct data, ever.
'I know I am doing something wrong and it will take work to fix it but
'I thought this part would be easy, I've swapped pieces of code around many times and the best I could get was a byte array full of zeros.


File.Read(0, StreamDat, DirectSound.LockFlag.EntireBuffer, DirectSound.LockFlag.None)

'Transfer the data from the MemoryStream to the Byte Array.
StreamBytes = StreamDat.ToArray()
Next
End Sub
End Class

-------------------------------------------------------------------------

I would just like to convert the SecondaryStream object to Base64 data and write the combined DSBuffer objects to one single file.

It's getting the data back from SecondaryStream that is the issue though.

Any help/comments would very much be appreciated.

I will continue research to find a fix and will post back if I find one. Thanks.
 
Last edited:
Found the solution, you need to write the header of the wave file, I believe the DirectSound.SecondaryBuffer strips the header from the wave file, and by using the Read method, the header is not returned, meaning you are to re-write the header, but by using the properties from the DirectSound.SecondaryBuffer class, there should not be any issues re-writing the headers.

Working code:

-------------------------------------------------------------------------
Imports DirectX
Imports DirectX.DirectSound
Imports IO

Public Class DSound
Public DSDevice As DirectSound.Device
Public DSBuffers As New List(Of DirectSound.SecondaryBuffer)

Private Sub Save(ByVal Path As String)
Dim Writer As New BinaryWriter(New FileStream(Path, FileMode.Create, FileAccess.ReadWrite))
Dim BufferData As Byte() = Nothing
DSBuffers(0).SetCurrentPosition(0)

CreateRIFF(Writer, DSBuffers(0).Format, DSBuffers(0).Caps.BufferBytes)
BufferData = CType(DSBuffers(0).Read(0, GetType(Byte), LockFlag.None, DSBuffers(0).Caps().BufferBytes), Byte())


Writer.Write(BufferData, 0, BufferData.Length)
Writer.Close()
End Sub

'Code used to create the header and ect.
Private Sub CreateRIFF(ByVal filename As String, ByVal InputFormat As WaveFormat, ByVal SampleCount As Integer)
'*************************************************************************
' Here is where the file will be created. A
' wave file is a RIFF file, which has chunks
' of data that describe what the file contains.
' A wave RIFF file is put together like this:
'
' The 12 byte RIFF chunk is constructed like this:
' Bytes(0 - 3) 'R' 'I' 'F' 'F'
' Bytes 4 - 7 : Length of file, minus the first 8 bytes of the RIFF description.
' (4 bytes for "WAVE" + 24 bytes for format chunk length +
' 8 bytes for data chunk description + actual sample data size.)
' Bytes(8 - 11) 'W' 'A' 'V' 'E'
'
' The 24 byte FORMAT chunk is constructed like this:
' Bytes(0 - 3) 'f' 'm' 't' ' '
' Bytes 4 - 7 : The format chunk length. This is always 16.
' Bytes 8 - 9 : File padding. Always 1.
' Bytes 10- 11: Number of channels. Either 1 for mono, or 2 for stereo.
' Bytes 12- 15: Sample rate.
' Bytes 16- 19: Number of bytes per second.
' Bytes 20- 21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or
' 16 bit mono, 4 for 16 bit stereo.
' Bytes 22- 23: Number of bits per sample.
'
' The DATA chunk is constructed like this:
' Bytes(0 - 3) 'd' 'a' 't' 'a'
' Bytes 4 - 7 : Length of data, in bytes.
' Bytes 8 -...: Actual sample data.
'**************************************************************************


' Open up the wave file for writing.
WaveFile = New FileStream(filename, FileMode.Create)
Writer = New BinaryWriter(WaveFile)

' Set up file with RIFF chunk info.
Dim ChunkRiff As Char() = {"R", "I", "F", "F"}
Dim ChunkType As Char() = {"W", "A", "V", "E"}
Dim ChunkFmt As Char() = {"f", "m", "t", " "}
Dim ChunkData As Char() = {"d", "a", "t", "a"}

Dim shPad As Short = 1 ' File padding
Dim nFormatChunkLength As Integer = &H10 ' Format chunk length.
Dim nLength As Integer = CInt(SampleCount + 36) ' File length, minus first 8 bytes of RIFF description.
Dim shBytesPerSample As Short = 0 ' Bytes per sample.
' Figure out how many bytes there will be per sample.
If 8 = InputFormat.BitsPerSample And 1 = InputFormat.Channels Then
shBytesPerSample = 1
ElseIf 8 = InputFormat.BitsPerSample And 2 = InputFormat.Channels Or (16 = InputFormat.BitsPerSample And 1 = InputFormat.Channels) Then
shBytesPerSample = 2
ElseIf 16 = InputFormat.BitsPerSample And 2 = InputFormat.Channels Then
shBytesPerSample = 4
End If
' Fill in the riff info for the wave file.
Writer.Write(ChunkRiff)
Writer.Write(nLength)
Writer.Write(ChunkType)

' Fill in the format info for the wave file.
Writer.Write(ChunkFmt)
Writer.Write(nFormatChunkLength)
Writer.Write(shPad)
Writer.Write(InputFormat.Channels)
Writer.Write(InputFormat.SamplesPerSecond)
Writer.Write(InputFormat.AverageBytesPerSecond)
Writer.Write(shBytesPerSample)
Writer.Write(InputFormat.BitsPerSample)

' Now fill in the data chunk.
Writer.Write(ChunkData)
Writer.Write(SampleCount) ' The sample length
End Sub
End Class
-------------------------------------------------------------------------
I hope this fixes your problem as well.
 
Last edited:
Back
Top