locked
Direct X Play Wav File Created in Ram RRS feed

Answers

  • I just figured it out, the trick was that I needed to add a memory stream!(D'oh) either way, this was a difficult task to solve, considering I am writing the wav file from scratch, storing it in ram, and playing it back from ram... Either way it works now, so here's the working code, since all of my searches have led me to code that does NOT work. =)

    Again,

    I am using .net framework 2.0, and I have a reference to directx and directsound as follows:

    C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.DirectSound.dll

    C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.dll

    FORM CODE:

    Imports Microsoft.DirectX.DirectSound
    Imports System.Text
    Public Class Form1
        Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
            Dim WaveFileOptions As New Wave.WaveFileOptions
            With WaveFileOptions
                .AudioFormat = Wave.Format.Standard
                .BitsPerSample = Wave.BitsPerSample.bps_8
                .FormatSize = Wave.FormatSize.PCM
                .NumberOfChannels = Wave.NumberOfChannels.Mono
                .NumberOfSamples = 100000
                .SampleRate = Wave.WavSampleRate.hz22050
            End With
            Dim DataUpperBound As Integer = ((WaveFileOptions.NumberOfSamples * WaveFileOptions.NumberOfChannels * WaveFileOptions.BitsPerSample) / 8) - 1
            Dim Data(0 To DataUpperBound) As Byte
            Dim Gen As New Random
            For I = 0 To DataUpperBound
                Data(I) = Gen.Next(0, 255)
            Next
            WaveFileOptions.Data = Data
            Dim WaveFile As New Wave(WaveFileOptions)
            TextBox2.Text = WaveFile.ViewBinary(False)
            TextBox2.Update()
            Dim Stream As New System.IO.MemoryStream(WaveFile.GetBytes)
            Dim DXFormat As New Microsoft.DirectX.DirectSound.WaveFormat
            DXFormat.AverageBytesPerSecond = WaveFile.FileFormatSubChunk.ByteRate
            DXFormat.BitsPerSample = WaveFile.FileFormatSubChunk.BitsPerSample
            DXFormat.BlockAlign = WaveFile.FileFormatSubChunk.BlockAlign
            DXFormat.Channels = WaveFile.FileFormatSubChunk.NumChannels
            DXFormat.FormatTag = WaveFormatTag.Pcm
            DXFormat.SamplesPerSecond = WaveFile.FileFormatSubChunk.SampleRate
            Dim BufferDescription As New Microsoft.DirectX.DirectSound.BufferDescription(DXFormat)
            BufferDescription.BufferBytes = WaveFileOptions.BitsPerSample
            BufferDescription.ControlFrequency = True
            BufferDescription.ControlPan = True
            BufferDescription.ControlVolume = True
            BufferDescription.GlobalFocus = True
            BufferDescription.StaticBuffer = True
            Dim SoundDevice As New Device
            SoundDevice.SetCooperativeLevel(Me.Handle, CooperativeLevel.Priority)
            Dim SecondaryBuffer As SecondaryBuffer = New Microsoft.DirectX.DirectSound.SecondaryBuffer(Stream, BufferDescription, SoundDevice)
            SecondaryBuffer.Play(0, Microsoft.DirectX.DirectSound.BufferPlayFlags.Default)
        End Sub
    End Class
    
    WaveFile Class:
    Imports System.Text
    Public Class Wave
        'By Paul Ishak
        'WAVE PCM soundfile format 
        'The Canonical WAVE file format
        'As Described Here: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
        Public FileHeader As Header
        Public FileFormatSubChunk As FormatSubChunk
        Public FileDataSubChunk As DataSubChunk
        Public Structure WaveFileOptions
            Public SampleRate As WavSampleRate
            Public AudioFormat As Format
            Public BitsPerSample As BitsPerSample
            Public NumberOfChannels As NumberOfChannels
            Public FormatSize As FormatSize
            Public NumberOfSamples As UInt32
            Public Data As Byte()
        End Structure
        '                                               DATATYPE          OFFSET        Endian           Description
        Structure Header
            Public Property ChunkID As Byte() '          Dword              0             Big            Contains the letters "RIFF" in ASCII form(0x52494646 big-endian form).
            Public Property ChunkSize As UInt32 '        Dword              4             Little         36 + SubChunk2Size, or more precisely: 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
            Public Property Format As Byte() '           Dword              8             Big            Contains the letters "WAVE" in ASCII form (0x57415645 big-endian form).
        End Structure
        Structure FormatSubChunk
            Public Property Subchunk1ID As Byte() '      Dword              12            Big            Contains the letters "fmt "(0x666d7420 big-endian form).
            Public Property Subchunk1Size As UInt32 '    Dword              16            little         16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
            Public Property AudioFormat As UInt16  '     Word               20            little         PCM = 1 (i.e. Linear quantization)Values other than 1 indicate some form of compression.
            Public Property NumChannels As UInt16 '      Word               22            little         Mono = 1, Stereo = 2, etc.
            Public Property SampleRate As UInt32 '       Dword              24            little         8000, 44100, etc.
            Public Property ByteRate As UInt32 '         Dword              28            little         == SampleRate * NumChannels * BitsPerSample/8
            Public Property BlockAlign As UInt16 '       Word               32            little         == NumChannels * BitsPerSample/8
            Public Property BitsPerSample As UInt16 '    Word               34            little         8 bits = 8, 16 bits = 16, etc.
        End Structure
        Structure DataSubChunk
            Public Property Subchunk2ID As Byte() '      Dword              36            Big            Contains the letters "data"(0x64617461 big-endian form).
            Public Property Subchunk2Size As UInt32 '    Dword              40            little         == NumSamples * NumChannels * BitsPerSample/8     This is the number of bytes in the data.
            Public Property Data As Byte() '             VariableLength     44            little         The actual sound data.
        End Structure
        Public Function GetBytes() As Byte()
            Dim Results As Byte() = Nothing
            Results = CombineArrays(FileHeader.ChunkID, BitConverter.GetBytes(FileHeader.ChunkSize))
            Results = CombineArrays(Results, FileHeader.Format)
            Results = CombineArrays(Results, FileFormatSubChunk.Subchunk1ID)
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.Subchunk1Size))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.AudioFormat))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.NumChannels))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.SampleRate))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.ByteRate))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.BlockAlign))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.BitsPerSample))
            Results = CombineArrays(Results, FileDataSubChunk.Subchunk2ID)
            Results = CombineArrays(Results, BitConverter.GetBytes(FileDataSubChunk.Subchunk2Size))
            Results = CombineArrays(Results, FileDataSubChunk.Data)
            Return Results
        End Function
        Function CombineArrays(Array1() As Byte, Array2() As Byte) As Byte()
            Dim AllResults(Array1.Length + Array2.Length - 1) As Byte
            Array1.CopyTo(AllResults, 0)
            Array2.CopyTo(AllResults, Array1.Length)
            Return AllResults
        End Function
        Public Function ViewBinary(Optional HexOffsets As Boolean = True) As String
            Dim asc As New StringBuilder
            Dim Hex As New StringBuilder
            Dim result As New StringBuilder
            Dim MB As Byte() = Me.GetBytes
            Select Case HexOffsets
                Case True
                    result.Append(" OFFSET " & "    " & "00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F  " & "    " & "0123456789ABCDEF" & vbCrLf & vbCrLf)
                Case False
                    result.Append(" OFFSET " & "    " & "00  01  02  03  04  05  06  07  08  09  10  11  12  13  14  15  " & "    " & "0123456789012345" & vbCrLf & vbCrLf)
            End Select
            Dim Count As Integer = -16
            For Each B As Byte In MB
                Count = Count + 1
                Hex.Append(B.ToString("X2") & "  ")
                If B > 32 And B < 128 Then
                    asc.Append(Chr(B))
                Else
                    asc.Append(".")
                End If
                If Count Mod 16 = 0 Then
                    Select Case HexOffsets
                        Case True
                            result.Append(Count.ToString("X").PadLeft(8, "0") & "    " & Hex.ToString & "    " & asc.ToString & vbCrLf)
                        Case False
                            result.Append(Count.ToString.PadLeft(8, "0") & "    " & Hex.ToString & "    " & asc.ToString & vbCrLf)
                    End Select
                    Hex.Remove(0, Hex.ToString.Length)
                    asc.Remove(0, asc.ToString.Length)
                End If
            Next
            Dim Counts As String = String.Empty
            Select Case HexOffsets
                Case True
                    Counts = (Count + (16 - (Count Mod 16))).ToString("X").PadLeft(8, "0").ToString
                Case False
                    Counts = (Count + (16 - (Count Mod 16))).ToString.PadLeft(8, "0").ToString
            End Select
            Dim H As Integer = 64 - Hex.ToString.Length
            Dim FinalHex As String = Hex.ToString & Space(H)
            result.Append(Counts & "    " & FinalHex & "    " & asc.ToString & vbCrLf)
            Return result.ToString
        End Function
        Sub New(Options As WaveFileOptions)
            FileHeader.ChunkID = Encoding.ASCII.GetBytes("RIFF")
            FileFormatSubChunk.Subchunk1Size = Options.FormatSize
            FileFormatSubChunk.NumChannels = Options.NumberOfChannels
            FileFormatSubChunk.BitsPerSample = Options.BitsPerSample
            FileDataSubChunk.Subchunk2Size = Options.NumberOfSamples * Options.NumberOfChannels * Options.BitsPerSample / 8
            FileHeader.ChunkSize = 4 + (8 + FileFormatSubChunk.Subchunk1Size) + (8 + FileDataSubChunk.Subchunk2Size)
            FileHeader.Format = Encoding.ASCII.GetBytes("WAVE")
            FileFormatSubChunk.Subchunk1ID = Encoding.ASCII.GetBytes("fmt ")
            FileFormatSubChunk.AudioFormat = Options.AudioFormat
            FileFormatSubChunk.SampleRate = Options.SampleRate
            FileFormatSubChunk.ByteRate = Options.SampleRate * Options.NumberOfChannels * Options.BitsPerSample / 8
            FileFormatSubChunk.BlockAlign = Options.NumberOfChannels * Options.BitsPerSample / 8
            FileDataSubChunk.Subchunk2ID = Encoding.ASCII.GetBytes("data")
            FileDataSubChunk.Data = Options.Data
        End Sub
        Public Enum WavSampleRate As UInt32
            hz8000 = 8000
            hz11025 = 11025
            hz16000 = 16000
            hz22050 = 22050
            hz32000 = 32000
            hz44100 = 44100
            hz48000 = 48000
            hz96000 = 96000
            hz192000 = 192000
        End Enum
        Public Enum Format As UInt16
            Standard = 1
        End Enum
        Public Enum BitsPerSample As UInt16
            bps_8 = 8
            bps_16 = 16
            bps_32 = 32
            bps_64 = 64
            bps_128 = 128
            bps_256 = 256
        End Enum
        Public Enum NumberOfChannels As UInt16
            Mono = 1
            Stereo = 2
        End Enum
        Public Enum FormatSize As UInt32
            PCM = 16
        End Enum
    End Class
    


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Tuesday, May 15, 2012 6:46 AM
    Moderator

All replies

  • Ok so I tried re-writing the program, and now the wav files that it generates will play in windows media player, but I still have no idea why I can't buffer that file from ram directly to direct sound(that way I don't have to save it to the hard disc). On a side note, I am using .net framework 2.0, and I have a reference to directx and directsound as follows:

    C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.DirectSound.dll

    C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.dll

    Here is my current progress:

    Form Code:

    Imports Microsoft.DirectX.DirectSound
    Imports System.Text
    Public Class Form1
        Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
            Dim WaveFileOptions As New Wave.WaveFileOptions
            With WaveFileOptions
                .AudioFormat = Wave.Format.Standard
                .BitsPerSample = Wave.BitsPerSample.bps_8
                .FormatSize = Wave.FormatSize.PCM
                .NumberOfChannels = Wave.NumberOfChannels.Mono
                .NumberOfSamples = 100000
                .SampleRate = Wave.WavSampleRate.hz22050
            End With
            Dim DataUpperBound As Integer = ((WaveFileOptions.NumberOfSamples * WaveFileOptions.NumberOfChannels * WaveFileOptions.BitsPerSample) / 8) - 1
            Dim Data(0 To DataUpperBound) As Byte
            Dim Gen As New Random
            For I = 0 To DataUpperBound
                Data(I) = Gen.Next(0, 255)
            Next
            WaveFileOptions.Data = Data
            Dim WaveFile As New Wave(WaveFileOptions)
            TextBox2.Text = WaveFile.ViewBinary(False)
            TextBox2.Update()
            My.Computer.FileSystem.WriteAllBytes(My.Computer.FileSystem.SpecialDirectories.Desktop & "\NewWav.wav", WaveFile.GetBytes, False)
            MsgBox(WaveFile.FileFormatSubChunk.ByteRate)
            Application.DoEvents()
            Dim DXFormat As New Microsoft.DirectX.DirectSound.WaveFormat
            DXFormat.AverageBytesPerSecond = WaveFile.FileFormatSubChunk.ByteRate
            DXFormat.BitsPerSample = WaveFile.FileFormatSubChunk.BitsPerSample
            DXFormat.BlockAlign = WaveFile.FileFormatSubChunk.BlockAlign
            DXFormat.Channels = WaveFile.FileFormatSubChunk.NumChannels
            DXFormat.FormatTag = WaveFormatTag.Pcm
            DXFormat.SamplesPerSecond = WaveFile.FileFormatSubChunk.SampleRate
            Dim BufferDescription As New Microsoft.DirectX.DirectSound.BufferDescription(DXFormat)
            BufferDescription.BufferBytes = WaveFile.FileFormatSubChunk.SampleRate * 1
            BufferDescription.ControlFrequency = True
            BufferDescription.ControlPan = True
            BufferDescription.ControlVolume = True
            BufferDescription.GlobalFocus = True
            Dim SoundDevice As New Device
            SoundDevice.SetCooperativeLevel(Me.Handle, CooperativeLevel.Priority)
            Dim SecondaryBuffer As SecondaryBuffer = New Microsoft.DirectX.DirectSound.SecondaryBuffer(BufferDescription, SoundDevice)
            SecondaryBuffer.Play(0, Microsoft.DirectX.DirectSound.BufferPlayFlags.Default)
        End Sub
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Dim SoundFile As String = My.Computer.FileSystem.SpecialDirectories.Desktop & "\NewWav.wav"
            Try
                Dim SoundDevice As New Microsoft.DirectX.DirectSound.Device
                SoundDevice.SetCooperativeLevel(Me.Handle, Microsoft.DirectX.DirectSound.CooperativeLevel.Normal)
                Dim SbufferOriginal As New Microsoft.DirectX.DirectSound.SecondaryBuffer(SoundFile, SoundDevice)
                SbufferOriginal.Play(0, Microsoft.DirectX.DirectSound.BufferPlayFlags.Default)
            Catch ex As Exception
            End Try
        End Sub
    End Class

    And Here is my new version of the wavefile class:

    Imports System.Text
    Public Class Wave
        'By Paul Ishak
        'WAVE PCM soundfile format 
        'The Canonical WAVE file format
        'As Described Here: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
        Public FileHeader As Header
        Public FileFormatSubChunk As FormatSubChunk
        Public FileDataSubChunk As DataSubChunk
        Public Structure WaveFileOptions
            Public SampleRate As WavSampleRate
            Public AudioFormat As Format
            Public BitsPerSample As BitsPerSample
            Public NumberOfChannels As NumberOfChannels
            Public FormatSize As FormatSize
            Public NumberOfSamples As UInt32
            Public Data As Byte()
        End Structure
        '                                               DATATYPE          OFFSET        Endian           Description
        Structure Header
            Public Property ChunkID As Byte() '          Dword              0             Big            Contains the letters "RIFF" in ASCII form(0x52494646 big-endian form).
            Public Property ChunkSize As UInt32 '        Dword              4             Little         36 + SubChunk2Size, or more precisely: 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
            Public Property Format As Byte() '           Dword              8             Big            Contains the letters "WAVE" in ASCII form (0x57415645 big-endian form).
        End Structure
        Structure FormatSubChunk
            Public Property Subchunk1ID As Byte() '      Dword              12            Big            Contains the letters "fmt "(0x666d7420 big-endian form).
            Public Property Subchunk1Size As UInt32 '    Dword              16            little         16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
            Public Property AudioFormat As UInt16  '     Word               20            little         PCM = 1 (i.e. Linear quantization)Values other than 1 indicate some form of compression.
            Public Property NumChannels As UInt16 '      Word               22            little         Mono = 1, Stereo = 2, etc.
            Public Property SampleRate As UInt32 '       Dword              24            little         8000, 44100, etc.
            Public Property ByteRate As UInt32 '         Dword              28            little         == SampleRate * NumChannels * BitsPerSample/8
            Public Property BlockAlign As UInt16 '       Word               32            little         == NumChannels * BitsPerSample/8
            Public Property BitsPerSample As UInt16 '    Word               34            little         8 bits = 8, 16 bits = 16, etc.
        End Structure
        Structure DataSubChunk
            Public Property Subchunk2ID As Byte() '      Dword              36            Big            Contains the letters "data"(0x64617461 big-endian form).
            Public Property Subchunk2Size As UInt32 '    Dword              40            little         == NumSamples * NumChannels * BitsPerSample/8     This is the number of bytes in the data.
            Public Property Data As Byte() '             VariableLength     44            little         The actual sound data.
        End Structure
        Public Function GetBytes() As Byte()
            Dim Results As Byte() = Nothing
            Results = CombineArrays(FileHeader.ChunkID, BitConverter.GetBytes(FileHeader.ChunkSize))
            Results = CombineArrays(Results, FileHeader.Format)
            Results = CombineArrays(Results, FileFormatSubChunk.Subchunk1ID)
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.Subchunk1Size))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.AudioFormat))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.NumChannels))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.SampleRate))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.ByteRate))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.BlockAlign))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.BitsPerSample))
            Results = CombineArrays(Results, FileDataSubChunk.Subchunk2ID)
            Results = CombineArrays(Results, BitConverter.GetBytes(FileDataSubChunk.Subchunk2Size))
            Results = CombineArrays(Results, FileDataSubChunk.Data)
            Return Results
        End Function
        Function CombineArrays(Array1() As Byte, Array2() As Byte) As Byte()
            Dim AllResults(Array1.Length + Array2.Length - 1) As Byte
            Array1.CopyTo(AllResults, 0)
            Array2.CopyTo(AllResults, Array1.Length)
            Return AllResults
        End Function
        Public Function ViewBinary(Optional HexOffsets As Boolean = True) As String
            Dim asc As New StringBuilder
            Dim Hex As New StringBuilder
            Dim result As New StringBuilder
            Dim MB As Byte() = Me.GetBytes
            Select Case HexOffsets
                Case True
                    result.Append(" OFFSET " & "    " & "00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F  " & "    " & "0123456789ABCDEF" & vbCrLf & vbCrLf)
                Case False
                    result.Append(" OFFSET " & "    " & "00  01  02  03  04  05  06  07  08  09  10  11  12  13  14  15  " & "    " & "0123456789012345" & vbCrLf & vbCrLf)
            End Select
            Dim Count As Integer = -16
            For Each B As Byte In MB
                Count = Count + 1
                Hex.Append(B.ToString("X2") & "  ")
                If B > 32 And B < 128 Then
                    asc.Append(Chr(B))
                Else
                    asc.Append(".")
                End If
                If Count Mod 16 = 0 Then
                    Select Case HexOffsets
                        Case True
                            result.Append(Count.ToString("X").PadLeft(8, "0") & "    " & Hex.ToString & "    " & asc.ToString & vbCrLf)
                        Case False
                            result.Append(Count.ToString.PadLeft(8, "0") & "    " & Hex.ToString & "    " & asc.ToString & vbCrLf)
                    End Select
                    Hex.Remove(0, Hex.ToString.Length)
                    asc.Remove(0, asc.ToString.Length)
                End If
            Next
            Dim Counts As String = String.Empty
            Select Case HexOffsets
                Case True
                    Counts = (Count + (16 - (Count Mod 16))).ToString("X").PadLeft(8, "0").ToString
                Case False
                    Counts = (Count + (16 - (Count Mod 16))).ToString.PadLeft(8, "0").ToString
            End Select
            Dim H As Integer = 64 - Hex.ToString.Length
            Dim FinalHex As String = Hex.ToString & Space(H)
            result.Append(Counts & "    " & FinalHex & "    " & asc.ToString & vbCrLf)
            Return result.ToString
        End Function
        Sub New(Options As WaveFileOptions)
            FileHeader.ChunkID = Encoding.ASCII.GetBytes("RIFF")
            FileFormatSubChunk.Subchunk1Size = Options.FormatSize
            FileFormatSubChunk.NumChannels = Options.NumberOfChannels
            FileFormatSubChunk.BitsPerSample = Options.BitsPerSample
            FileDataSubChunk.Subchunk2Size = Options.NumberOfSamples * Options.NumberOfChannels * Options.BitsPerSample / 8
            FileHeader.ChunkSize = 4 + (8 + FileFormatSubChunk.Subchunk1Size) + (8 + FileDataSubChunk.Subchunk2Size)
            FileHeader.Format = Encoding.ASCII.GetBytes("WAVE")
            FileFormatSubChunk.Subchunk1ID = Encoding.ASCII.GetBytes("fmt ")
            FileFormatSubChunk.AudioFormat = Options.AudioFormat
            FileFormatSubChunk.SampleRate = Options.SampleRate
            FileFormatSubChunk.ByteRate = Options.SampleRate * Options.NumberOfChannels * Options.BitsPerSample / 8
            FileFormatSubChunk.BlockAlign = Options.NumberOfChannels * Options.BitsPerSample / 8
            FileDataSubChunk.Subchunk2ID = Encoding.ASCII.GetBytes("data")
            FileDataSubChunk.Data = Options.Data
        End Sub
        Public Enum WavSampleRate As UInt32
            hz8000 = 8000
            hz11025 = 11025
            hz16000 = 16000
            hz22050 = 22050
            hz32000 = 32000
            hz44100 = 44100
            hz48000 = 48000
            hz96000 = 96000
            hz192000 = 192000
        End Enum
        Public Enum Format As UInt16
            Standard = 1
        End Enum
        Public Enum BitsPerSample As UInt16
            bps_8 = 8
            bps_16 = 16
            bps_32 = 32
            bps_64 = 64
            bps_128 = 128
            bps_256 = 256
        End Enum
        Public Enum NumberOfChannels As UInt16
            Mono = 1
            Stereo = 2
        End Enum
        Public Enum FormatSize As UInt32
            PCM = 16
        End Enum
    End Class


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.



    Tuesday, May 15, 2012 5:59 AM
    Moderator
  • Pehaps I am missing something...but does windows Media player have...in memory support?

    One thing ive always thaught managed code needs is that ability to see bytes actually in memory. I know that violates a basic presumptiom of managed code BUT that as pect of managed code is not convenient - at all.

    Renee


    "MODERN PROGRAMMING is deficient in elementary ways BECAUSE of problems INTRODUCED by MODERN PROGRAMMING." Me

    Tuesday, May 15, 2012 6:35 AM
  • I just figured it out, the trick was that I needed to add a memory stream!(D'oh) either way, this was a difficult task to solve, considering I am writing the wav file from scratch, storing it in ram, and playing it back from ram... Either way it works now, so here's the working code, since all of my searches have led me to code that does NOT work. =)

    Again,

    I am using .net framework 2.0, and I have a reference to directx and directsound as follows:

    C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.DirectSound.dll

    C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.dll

    FORM CODE:

    Imports Microsoft.DirectX.DirectSound
    Imports System.Text
    Public Class Form1
        Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click
            Dim WaveFileOptions As New Wave.WaveFileOptions
            With WaveFileOptions
                .AudioFormat = Wave.Format.Standard
                .BitsPerSample = Wave.BitsPerSample.bps_8
                .FormatSize = Wave.FormatSize.PCM
                .NumberOfChannels = Wave.NumberOfChannels.Mono
                .NumberOfSamples = 100000
                .SampleRate = Wave.WavSampleRate.hz22050
            End With
            Dim DataUpperBound As Integer = ((WaveFileOptions.NumberOfSamples * WaveFileOptions.NumberOfChannels * WaveFileOptions.BitsPerSample) / 8) - 1
            Dim Data(0 To DataUpperBound) As Byte
            Dim Gen As New Random
            For I = 0 To DataUpperBound
                Data(I) = Gen.Next(0, 255)
            Next
            WaveFileOptions.Data = Data
            Dim WaveFile As New Wave(WaveFileOptions)
            TextBox2.Text = WaveFile.ViewBinary(False)
            TextBox2.Update()
            Dim Stream As New System.IO.MemoryStream(WaveFile.GetBytes)
            Dim DXFormat As New Microsoft.DirectX.DirectSound.WaveFormat
            DXFormat.AverageBytesPerSecond = WaveFile.FileFormatSubChunk.ByteRate
            DXFormat.BitsPerSample = WaveFile.FileFormatSubChunk.BitsPerSample
            DXFormat.BlockAlign = WaveFile.FileFormatSubChunk.BlockAlign
            DXFormat.Channels = WaveFile.FileFormatSubChunk.NumChannels
            DXFormat.FormatTag = WaveFormatTag.Pcm
            DXFormat.SamplesPerSecond = WaveFile.FileFormatSubChunk.SampleRate
            Dim BufferDescription As New Microsoft.DirectX.DirectSound.BufferDescription(DXFormat)
            BufferDescription.BufferBytes = WaveFileOptions.BitsPerSample
            BufferDescription.ControlFrequency = True
            BufferDescription.ControlPan = True
            BufferDescription.ControlVolume = True
            BufferDescription.GlobalFocus = True
            BufferDescription.StaticBuffer = True
            Dim SoundDevice As New Device
            SoundDevice.SetCooperativeLevel(Me.Handle, CooperativeLevel.Priority)
            Dim SecondaryBuffer As SecondaryBuffer = New Microsoft.DirectX.DirectSound.SecondaryBuffer(Stream, BufferDescription, SoundDevice)
            SecondaryBuffer.Play(0, Microsoft.DirectX.DirectSound.BufferPlayFlags.Default)
        End Sub
    End Class
    
    WaveFile Class:
    Imports System.Text
    Public Class Wave
        'By Paul Ishak
        'WAVE PCM soundfile format 
        'The Canonical WAVE file format
        'As Described Here: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
        Public FileHeader As Header
        Public FileFormatSubChunk As FormatSubChunk
        Public FileDataSubChunk As DataSubChunk
        Public Structure WaveFileOptions
            Public SampleRate As WavSampleRate
            Public AudioFormat As Format
            Public BitsPerSample As BitsPerSample
            Public NumberOfChannels As NumberOfChannels
            Public FormatSize As FormatSize
            Public NumberOfSamples As UInt32
            Public Data As Byte()
        End Structure
        '                                               DATATYPE          OFFSET        Endian           Description
        Structure Header
            Public Property ChunkID As Byte() '          Dword              0             Big            Contains the letters "RIFF" in ASCII form(0x52494646 big-endian form).
            Public Property ChunkSize As UInt32 '        Dword              4             Little         36 + SubChunk2Size, or more precisely: 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
            Public Property Format As Byte() '           Dword              8             Big            Contains the letters "WAVE" in ASCII form (0x57415645 big-endian form).
        End Structure
        Structure FormatSubChunk
            Public Property Subchunk1ID As Byte() '      Dword              12            Big            Contains the letters "fmt "(0x666d7420 big-endian form).
            Public Property Subchunk1Size As UInt32 '    Dword              16            little         16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
            Public Property AudioFormat As UInt16  '     Word               20            little         PCM = 1 (i.e. Linear quantization)Values other than 1 indicate some form of compression.
            Public Property NumChannels As UInt16 '      Word               22            little         Mono = 1, Stereo = 2, etc.
            Public Property SampleRate As UInt32 '       Dword              24            little         8000, 44100, etc.
            Public Property ByteRate As UInt32 '         Dword              28            little         == SampleRate * NumChannels * BitsPerSample/8
            Public Property BlockAlign As UInt16 '       Word               32            little         == NumChannels * BitsPerSample/8
            Public Property BitsPerSample As UInt16 '    Word               34            little         8 bits = 8, 16 bits = 16, etc.
        End Structure
        Structure DataSubChunk
            Public Property Subchunk2ID As Byte() '      Dword              36            Big            Contains the letters "data"(0x64617461 big-endian form).
            Public Property Subchunk2Size As UInt32 '    Dword              40            little         == NumSamples * NumChannels * BitsPerSample/8     This is the number of bytes in the data.
            Public Property Data As Byte() '             VariableLength     44            little         The actual sound data.
        End Structure
        Public Function GetBytes() As Byte()
            Dim Results As Byte() = Nothing
            Results = CombineArrays(FileHeader.ChunkID, BitConverter.GetBytes(FileHeader.ChunkSize))
            Results = CombineArrays(Results, FileHeader.Format)
            Results = CombineArrays(Results, FileFormatSubChunk.Subchunk1ID)
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.Subchunk1Size))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.AudioFormat))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.NumChannels))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.SampleRate))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.ByteRate))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.BlockAlign))
            Results = CombineArrays(Results, BitConverter.GetBytes(FileFormatSubChunk.BitsPerSample))
            Results = CombineArrays(Results, FileDataSubChunk.Subchunk2ID)
            Results = CombineArrays(Results, BitConverter.GetBytes(FileDataSubChunk.Subchunk2Size))
            Results = CombineArrays(Results, FileDataSubChunk.Data)
            Return Results
        End Function
        Function CombineArrays(Array1() As Byte, Array2() As Byte) As Byte()
            Dim AllResults(Array1.Length + Array2.Length - 1) As Byte
            Array1.CopyTo(AllResults, 0)
            Array2.CopyTo(AllResults, Array1.Length)
            Return AllResults
        End Function
        Public Function ViewBinary(Optional HexOffsets As Boolean = True) As String
            Dim asc As New StringBuilder
            Dim Hex As New StringBuilder
            Dim result As New StringBuilder
            Dim MB As Byte() = Me.GetBytes
            Select Case HexOffsets
                Case True
                    result.Append(" OFFSET " & "    " & "00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F  " & "    " & "0123456789ABCDEF" & vbCrLf & vbCrLf)
                Case False
                    result.Append(" OFFSET " & "    " & "00  01  02  03  04  05  06  07  08  09  10  11  12  13  14  15  " & "    " & "0123456789012345" & vbCrLf & vbCrLf)
            End Select
            Dim Count As Integer = -16
            For Each B As Byte In MB
                Count = Count + 1
                Hex.Append(B.ToString("X2") & "  ")
                If B > 32 And B < 128 Then
                    asc.Append(Chr(B))
                Else
                    asc.Append(".")
                End If
                If Count Mod 16 = 0 Then
                    Select Case HexOffsets
                        Case True
                            result.Append(Count.ToString("X").PadLeft(8, "0") & "    " & Hex.ToString & "    " & asc.ToString & vbCrLf)
                        Case False
                            result.Append(Count.ToString.PadLeft(8, "0") & "    " & Hex.ToString & "    " & asc.ToString & vbCrLf)
                    End Select
                    Hex.Remove(0, Hex.ToString.Length)
                    asc.Remove(0, asc.ToString.Length)
                End If
            Next
            Dim Counts As String = String.Empty
            Select Case HexOffsets
                Case True
                    Counts = (Count + (16 - (Count Mod 16))).ToString("X").PadLeft(8, "0").ToString
                Case False
                    Counts = (Count + (16 - (Count Mod 16))).ToString.PadLeft(8, "0").ToString
            End Select
            Dim H As Integer = 64 - Hex.ToString.Length
            Dim FinalHex As String = Hex.ToString & Space(H)
            result.Append(Counts & "    " & FinalHex & "    " & asc.ToString & vbCrLf)
            Return result.ToString
        End Function
        Sub New(Options As WaveFileOptions)
            FileHeader.ChunkID = Encoding.ASCII.GetBytes("RIFF")
            FileFormatSubChunk.Subchunk1Size = Options.FormatSize
            FileFormatSubChunk.NumChannels = Options.NumberOfChannels
            FileFormatSubChunk.BitsPerSample = Options.BitsPerSample
            FileDataSubChunk.Subchunk2Size = Options.NumberOfSamples * Options.NumberOfChannels * Options.BitsPerSample / 8
            FileHeader.ChunkSize = 4 + (8 + FileFormatSubChunk.Subchunk1Size) + (8 + FileDataSubChunk.Subchunk2Size)
            FileHeader.Format = Encoding.ASCII.GetBytes("WAVE")
            FileFormatSubChunk.Subchunk1ID = Encoding.ASCII.GetBytes("fmt ")
            FileFormatSubChunk.AudioFormat = Options.AudioFormat
            FileFormatSubChunk.SampleRate = Options.SampleRate
            FileFormatSubChunk.ByteRate = Options.SampleRate * Options.NumberOfChannels * Options.BitsPerSample / 8
            FileFormatSubChunk.BlockAlign = Options.NumberOfChannels * Options.BitsPerSample / 8
            FileDataSubChunk.Subchunk2ID = Encoding.ASCII.GetBytes("data")
            FileDataSubChunk.Data = Options.Data
        End Sub
        Public Enum WavSampleRate As UInt32
            hz8000 = 8000
            hz11025 = 11025
            hz16000 = 16000
            hz22050 = 22050
            hz32000 = 32000
            hz44100 = 44100
            hz48000 = 48000
            hz96000 = 96000
            hz192000 = 192000
        End Enum
        Public Enum Format As UInt16
            Standard = 1
        End Enum
        Public Enum BitsPerSample As UInt16
            bps_8 = 8
            bps_16 = 16
            bps_32 = 32
            bps_64 = 64
            bps_128 = 128
            bps_256 = 256
        End Enum
        Public Enum NumberOfChannels As UInt16
            Mono = 1
            Stereo = 2
        End Enum
        Public Enum FormatSize As UInt32
            PCM = 16
        End Enum
    End Class
    


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Tuesday, May 15, 2012 6:46 AM
    Moderator
  • Thank you for sharing your solution here!

    Best regards,


    Shanks Zen
    MSDN Community Support | Feedback to us

    Tuesday, May 15, 2012 7:56 AM
    Moderator
  • Thank you for sharing your solution here!

    Best regards,


    Shanks Zen
    MSDN Community Support | Feedback to us

    I am certain that someone else out there is going to be pulling their hair out trying to figure this out!


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Tuesday, May 15, 2012 8:31 AM
    Moderator
  • I figured I would post this project too(yea its ugly haha) for whoever feels like tinkering. Any improvements would be awesome!

    Skydrive - WaveClass.zip


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.

    Wednesday, May 16, 2012 6:34 AM
    Moderator
  • its evolving...


    If you want something you've never had, you need to do something you've never done. If you believe something to be true, then one day you will be called upon to demonstrate that truth.


    Friday, May 18, 2012 12:50 AM
    Moderator