-
Jan 25th, 2018, 04:18 PM
#1
Thread Starter
Lively Member
[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
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|