Results 1 to 6 of 6

Thread: [RESOLVED] Creating a wav file for use as an Infrared carrier

Hybrid View

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Feb 2006
    Location
    Guernsey, UK
    Posts
    104

    Resolved [RESOLVED] Creating a wav file for use as an Infrared carrier

    Hello,

    I am using the following code, which creates a wav file, for use as audio signal generation, to modulate an Infrared LED connected across the left and right channels of the headphone jack.

    I am able to create a maximum output frequency of 20 kHz because of the general limitations of head-phone ports. I need to modulate the Infrared LED at circa 38 kHz, so I have read about the technique of creating a stereo wav file where, for instance, the left channel is the inverse of the right channel, so with the LED connected across the channels, the LED effectively flashes at double the input frequency.

    My problem is, I cannot see how I can amend the code to be able to invert one channel. This code uses one byte-array for the data, but if you select stereo in the property set-up then the left and right channels are identical - I think I need to add another byte-array which I can build up as the inverse.

    Any help much appreciated. The form code and the class is shown, code originally comes from a person called Paul Ishak on this website (half way down the thread):-

    https://social.msdn.microsoft.com/Fo...orum=vbgeneral

    The form code creates a square wave at a fixed frequency for testing.

    Class code:-

    Code:
    Option Strict On
    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
        Const _Byte As Integer = 1
        Const _word As Integer = 2
        Const _dword As Integer = 4
        Const _qword As Integer = 8
        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 Sub OpenFile(ByVal FileName As String)
            Try
                If CBool(Not InStr(LCase(FileName), ".wav")) Then Throw New Exception("Invalid File Extension Specified!")
                If Not My.Computer.FileSystem.FileExists(FileName) Then Throw New Exception("File Does Not Exist!")
                Dim FileBytes() As Byte = My.Computer.FileSystem.ReadAllBytes(FileName)
                'Get Header
                Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, _dword)
                Me.FileHeader.ChunkSize = CUInt(BitConverter.ToInt32(GetDataFromByteArray(FileBytes, 0, 4, _dword), 0))
                Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, _dword)
                'Get FormatSubChunk
                Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, _dword)
                Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 16, _dword), 0)
                Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 20, _word), 0)
                Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 22, _word), 0)
                Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 24, _dword), 0)
                Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 28, _dword), 0)
                Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 32, _word), 0)
                Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 34, _word), 0)
                'Get DataSubChunck
                Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, _dword)
                Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 40, _dword), 0)
                Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
            Catch
                Throw New Exception("File Is Invalid or corrupt!")
            End Try
        End Sub
        Public Sub SetDirectBytes(ByVal FileBytes() As Byte)
            Try
                'Get Header
                Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, _dword)
                Me.FileHeader.ChunkSize = CUInt(BitConverter.ToInt32(GetDataFromByteArray(FileBytes, 0, 4, _dword), 0))
                Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, _dword)
                'Get FormatSubChunk
                Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, _dword)
                Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 16, _dword), 0)
                Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 20, _word), 0)
                Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 22, _word), 0)
                Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 24, _dword), 0)
                Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 28, _dword), 0)
                Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 32, _word), 0)
                Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 34, _word), 0)
                'Get DataSubChunck
                Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, _dword)
                Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 40, _dword), 0)
                Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
            Catch ex As Exception
                ' Throw New Exception("File Is Invalid or corrupt!")
                MsgBox(ex.StackTrace)
            End Try
        End Sub
    
        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(ByVal Array1() As Byte, ByVal 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 Sub SaveFile(ByVal FileName As String)
            Dim FileBytes As Byte() = Me.GetBytes()
            My.Computer.FileSystem.WriteAllBytes(FileName, FileBytes, False)
        End Sub
        Private Function GetDataFromByteArray(ByVal ByteArray As Byte(), ByVal BlockOffset As Long, ByVal RangeStartOffset As Long, ByVal DataLength As Long) As Byte()
            On Error Resume Next
            Dim AnswerL As New List(Of Byte)
            Dim CurrentOffset As Long
            For I = 0 To UBound(ByteArray)
                CurrentOffset = BlockOffset + I
                If CurrentOffset >= RangeStartOffset Then
                    If CurrentOffset <= RangeStartOffset + DataLength Then
                        AnswerL.Add(ByteArray(I))
                    End If
                End If
            Next
            Return AnswerL.ToArray
        End Function
        Sub New(ByVal Options As WaveFileOptions)
            FileHeader.ChunkID = Encoding.ASCII.GetBytes("RIFF")
            FileFormatSubChunk.Subchunk1Size = Options.FormatSize
            FileFormatSubChunk.NumChannels = Options.NumberOfChannels
            FileFormatSubChunk.BitsPerSample = Options.BitsPerSample
            FileDataSubChunk.Subchunk2Size = CUInt(Options.NumberOfSamples * Options.NumberOfChannels * Options.BitsPerSample / 8)
            FileHeader.ChunkSize = CUInt(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 = CUInt(Options.SampleRate * Options.NumberOfChannels * Options.BitsPerSample / 8)
            FileFormatSubChunk.BlockAlign = CUShort(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
    Main form code:-

    Code:
    Option Strict On
    Imports System.Text
    Public Class Form1
        Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
            Dim WaveFileOptions As New Wave.WaveFileOptions
            With WaveFileOptions
                .AudioFormat = Wave.Format.Standard
                .FormatSize = Wave.FormatSize.PCM
                .BitsPerSample = Wave.BitsPerSample.bps_8
                .NumberOfChannels = Wave.NumberOfChannels.Stereo
                .SampleRate = Wave.WavSampleRate.hz44100
                .NumberOfSamples = 4096
            End With
            Dim DataUpperBound As Integer = CInt(((WaveFileOptions.NumberOfSamples * WaveFileOptions.NumberOfChannels * WaveFileOptions.BitsPerSample) / 8) - 1)
            Dim Data(0 To DataUpperBound) As Byte
            '
            ' 255 = +100% 
            ' 128 = 0%
            ' 0 = -100%
            '
            Dim q As Integer = 0
            For pulse As Integer = 0 To 2047
                For i As Integer = 0 To 1  ' 2 pulses ON
                    Data(q) = CByte(255)
                    q += 1
                Next
                For i As Integer = 0 To 1 ' 2 pulses OFF
                    Data(q) = CByte(128)
                    q += 1
                Next
            Next
            '
            WaveFileOptions.Data = Data
            Dim WaveFile As New Wave(WaveFileOptions)
            WaveFile.SaveFile(My.Computer.FileSystem.SpecialDirectories.Desktop & "\whitenoise.wav")
            Process.Start(My.Computer.FileSystem.SpecialDirectories.Desktop & "\whitenoise.wav")
        End Sub
    End Class

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Creating a wav file for use as an Infrared carrier

    I don't see how inverting a channel will double the frequency. I would think all it would do is double the voltage (the delta between the two wave magnitudes).

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Feb 2006
    Location
    Guernsey, UK
    Posts
    104

    Re: Creating a wav file for use as an Infrared carrier

    So, the way I understand it, if the LED is just connected across Left and Ground with a Mono signal, then the LED will only flash on the positive cycle, when the negative cycle occurs, the LED just sits there doing nothing.

    Whereas, if the LED is connected across Left and Right (not ground) with a Stereo signal (one channel in opposite phase to the other) then when the Left channel is positive the LED will come on and when the Right channel is positive the LED will come on again, occurring twice in the same time period.

  4. #4
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Creating a wav file for use as an Infrared carrier

    Ok, I guess there must be more components involved here than just the LED. Perhaps you have a transistor to amplify the signal to the level needed to trigger the LED and a resister to limit the current. The D in LED stands for Diode and a Diode will primarily pass current in one direction so as you say it would light when the voltage was positive (the current moving in one direction) and not light when the voltage was negative (the current trying to move in the other direction but blocked by the diode).

    If you connected one side of the LED to ground, that gives you a fixed reference on that pin, and when the other pin goes higher than ground you have the positive voltage and the diode passes the current lighting the LED and when the other pin goes less than ground you have a negative voltage (in reference to the ground) so the diode blocks the current and the LED is unlit.

    If you connected a signal to one pin and an inverted version of that signal to the other pin the relative voltage potential between the pins would increase as the signals moved away from each other so at the peak of the signal the voltage potential between the two pins would be twice the value of the signal.

    Let's assume a one volt signal where the reference is ground and the wave (i.e. the voltage) goes to a peak of 1v above ground and 1v below ground in its cycle. If this signal is connected to one pin of the LED and the other pin of the LED is connected to ground (0), then the potential at the positive peak (1 - 0) is 1 and the potential at the negative peak (-1 - 0) is -1.
    If you connect a negative version of the signal to the one pin in place of the ground, then the potential at the positive peak is (1 - -1) = 2 and the potential at the negative peak is (-1 - 1) = -2.

    The result is you've double the voltage potential between the two pins compared to the original signal (original cycled between 1 and -1, the second cycles between 2 and -2).

    For what you propose there must be (I would think) two diodes inline (one on each signal input) with the "outputs" connected to the "input" of the LED so that when the signal is positive current is passing through that diode to the LED and the other signal is block by its diode because its signal is negative. Then when the signal is negative the diode on that input is blocking current while the inverted signal's (now positive) current is passed driving the LED.

    Of course, it seems to me like you wouldn't need a stereo input, i.e. two signals to accomplish this as the one wave could use a rectifier circuit of diodes to change the negative swing of the signal into a relative positive swing giving you two pulses per cycle from the one signal, but perhaps because you are modulating the signal to communicate data, flipping the signal with a rectifier would mess up or complicate the modulation mechanism.

    I guess I only "know enough to be dangerous", not enough to be competent or sure, but since the LED by design should conduct current when the voltage potential of the pins is in one condition, connecting an inverted signal to the other pin doesn't seem like the correct terminology for what you need to do.

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Feb 2006
    Location
    Guernsey, UK
    Posts
    104

    Re: Creating a wav file for use as an Infrared carrier

    I've been doing some testing following your posts and you're absolutely right

    You know when you run something through your brain and you come up with 2 answers and 1 is the wish-list answer!

    I'd still like to be able to do this (inverting the one channel), as like you say, I'd at least get double the volts. which will help with range etc.

    What I'm doing now is creating a positive DC pulse twice in the time period for 19kHz (effectively 38kHz), but it seems to be cutting out, perhaps the sound card doesn't like it - I can't get data streams longer than 60ms?

  6. #6

    Thread Starter
    Lively Member
    Join Date
    Feb 2006
    Location
    Guernsey, UK
    Posts
    104

    Re: Creating a wav file for use as an Infrared carrier

    Update:-
    So, I now have a working solution for my infrared transmitter. The following code creates a .wav file based on 1s and 0s which represent arbitrary values, in my case, approximately 560us long pulse for a logic 1, and a 560us long space for a logic 0.
    The modulation is 19kHz AC, so when two infrared LEDs are connected back-to-back, the effective frequency in terms of the infrared modulation is double that.
    Interestingly, through testing I have found that most infrared receivers will work on half the nominal 38kHz frequency, using only one infrared LED.
    The code creates the .wav file, and then plays it.
    Here is the test code if anybody is interested:-


    Code:
    Option Strict On
    Imports System.Text
    Public Class Form1
        Dim q As Integer = 0
        Dim Data As Byte() = New Byte(12500000) {}
        Dim pulse_mark As Integer = 3  ' Maximum current flow per cycle = 3
        Dim pulse_space As Integer = 0 ' Maximum current flow per cycle = 0
        '
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            '
            ' Code to create a small .wav file with data = 10101
            ' Based on 19kHz modulating 2 LED connecteds across Left channel and ground
            ' which flashes effectively at 38kHz. But it also works with 1 LED.
            ' 
            ' .wav values:-
            ' 255 = +100% 
            ' 128 = 0%
            ' 0 = -100%
            '
            ' An ideal 38kHz with a 50% duty cycle is:-
            ' 1/38000 = 26.3us/2 = 13.15us ON and 13.15us OFF
            '
            ' 1/192000*10 = 0.00005208 = 1/0.00005208 * 2 LEDs = 38400
            '
            q = 0
            Dim WaveFileOptions As New Wave.WaveFileOptions
            With WaveFileOptions
                .AudioFormat = Wave.Format.Standard
                .FormatSize = Wave.FormatSize.PCM
                .BitsPerSample = Wave.BitsPerSample.bps_8
                .NumberOfChannels = Wave.NumberOfChannels.Mono
                .SampleRate = Wave.WavSampleRate.hz192000
                .NumberOfSamples = 13260 ' adjust as necessary to fit the data in
            End With
            '
            add_One_19kHz()
            add_Zero_19kHz()
            add_One_19kHz()
            add_Zero_19kHz()
            add_One_19kHz()
            '
            WaveFileOptions.Data = Data
            Dim WaveFile As New Wave(WaveFileOptions)
            WaveFile.SaveFile(My.Computer.FileSystem.SpecialDirectories.Desktop & "\Remote.wav")
            My.Computer.Audio.Play(My.Computer.FileSystem.SpecialDirectories.Desktop & "\Remote.wav")
        End Sub
        '
        Private Sub add_One_19kHz()
            ' Create an AC pulse which has a length of 580 us
            For pulse As Integer = 0 To 10
                ' the following is 10 pulses long
                For i As Integer = 0 To pulse_mark
                    Data(q) = CByte(255)
                    q += 1
                Next
                For i As Integer = 0 To pulse_space
                    Data(q) = CByte(128)
                    q += 1
                Next
                For i As Integer = 0 To pulse_mark
                    Data(q) = CByte(0)
                    q += 1
                Next
                For i As Integer = 0 To pulse_space
                    Data(q) = CByte(128)
                    q += 1
                Next
            Next
        End Sub
    '
        Private Sub add_Zero_19kHz()
            ' Create an AC pulse which has a length of 580 us
            For pulse As Integer = 0 To 10
                ' the following is 10 pulses long
                For i As Integer = 0 To pulse_mark
                    Data(q) = CByte(255)
                    q += 1
                Next
                For i As Integer = 0 To pulse_space
                    Data(q) = CByte(128)
                    q += 1
                Next
                For i As Integer = 0 To pulse_mark
                    Data(q) = CByte(0)
                    q += 1
                Next
                For i As Integer = 0 To pulse_space
                    Data(q) = CByte(128)
                    q += 1
                Next
            Next
        End Sub
        '
    End Class
    
    wave class code again:-
    
    Option Strict On
    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
        Const _Byte As Integer = 1
        Const _word As Integer = 2
        Const _dword As Integer = 4
        Const _qword As Integer = 8
        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 Sub OpenFile(ByVal FileName As String)
            Try
                If CBool(Not InStr(LCase(FileName), ".wav")) Then Throw New Exception("Invalid File Extension Specified!")
                If Not My.Computer.FileSystem.FileExists(FileName) Then Throw New Exception("File Does Not Exist!")
                Dim FileBytes() As Byte = My.Computer.FileSystem.ReadAllBytes(FileName)
                'Get Header
                Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, _dword)
                Me.FileHeader.ChunkSize = CUInt(BitConverter.ToInt32(GetDataFromByteArray(FileBytes, 0, 4, _dword), 0))
                Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, _dword)
                'Get FormatSubChunk
                Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, _dword)
                Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 16, _dword), 0)
                Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 20, _word), 0)
                Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 22, _word), 0)
                Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 24, _dword), 0)
                Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 28, _dword), 0)
                Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 32, _word), 0)
                Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 34, _word), 0)
                'Get DataSubChunck
                Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, _dword)
                Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 40, _dword), 0)
                Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
            Catch
                Throw New Exception("File Is Invalid or corrupt!")
            End Try
        End Sub
        Public Sub SetDirectBytes(ByVal FileBytes() As Byte)
            Try
                'Get Header
                Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, _dword)
                Me.FileHeader.ChunkSize = CUInt(BitConverter.ToInt32(GetDataFromByteArray(FileBytes, 0, 4, _dword), 0))
                Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, _dword)
                'Get FormatSubChunk
                Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, _dword)
                Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 16, _dword), 0)
                Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 20, _word), 0)
                Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 22, _word), 0)
                Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 24, _dword), 0)
                Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 28, _dword), 0)
                Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 32, _word), 0)
                Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(GetDataFromByteArray(FileBytes, 0, 34, _word), 0)
                'Get DataSubChunck
                Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, _dword)
                Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(GetDataFromByteArray(FileBytes, 0, 40, _dword), 0)
                Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
            Catch ex As Exception
                ' Throw New Exception("File Is Invalid or corrupt!")
                MsgBox(ex.StackTrace)
            End Try
        End Sub
    
        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(ByVal Array1() As Byte, ByVal 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 Sub SaveFile(ByVal FileName As String)
            Dim FileBytes As Byte() = Me.GetBytes()
            My.Computer.FileSystem.WriteAllBytes(FileName, FileBytes, False)
        End Sub
        Private Function GetDataFromByteArray(ByVal ByteArray As Byte(), ByVal BlockOffset As Long, ByVal RangeStartOffset As Long, ByVal DataLength As Long) As Byte()
            On Error Resume Next
            Dim AnswerL As New List(Of Byte)
            Dim CurrentOffset As Long
            For I = 0 To UBound(ByteArray)
                CurrentOffset = BlockOffset + I
                If CurrentOffset >= RangeStartOffset Then
                    If CurrentOffset <= RangeStartOffset + DataLength Then
                        AnswerL.Add(ByteArray(I))
                    End If
                End If
            Next
            Return AnswerL.ToArray
        End Function
        Sub New(ByVal Options As WaveFileOptions)
            FileHeader.ChunkID = Encoding.ASCII.GetBytes("RIFF")
            FileFormatSubChunk.Subchunk1Size = Options.FormatSize
            FileFormatSubChunk.NumChannels = Options.NumberOfChannels
            FileFormatSubChunk.BitsPerSample = Options.BitsPerSample
            FileDataSubChunk.Subchunk2Size = CUInt(Options.NumberOfSamples * Options.NumberOfChannels * Options.BitsPerSample / 8)
            FileHeader.ChunkSize = CUInt(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 = CUInt(Options.SampleRate * Options.NumberOfChannels * Options.BitsPerSample / 8)
            FileFormatSubChunk.BlockAlign = CUShort(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

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width