Jump to content
Xtreme .Net Talk

Recommended Posts

Posted (edited)

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.

Edited by Fabian_Russ
Posted (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.

Edited by Fabian_Russ

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...