Please note that this is not perfect, not all wave files can be modified without first modifying other fileformatsubchunk fields.

  • Create a brand new Visual Basic Winforms project
  • Replace ALL of Form1's code with the following code:
'Option Strict Is Always Recommended
Option Strict On
Imports System.Text
Public Class Form1
 'Add one button to your form(make sure that the handles clause is still at the end of your sub afterwards)=Handles Button1.Click
 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 'Create a new instance of the wavefile class(provided in the technet article)
 Dim WaveFile As New Wave
 'Create a new openfiledialog
 Dim OFD As New OpenFileDialog
 'Set the filter for the openfiledialog
 OFD.Filter = "Wave Files|*.wav"
 'make it select single files only
 OFD.Multiselect = False
 'Show the dialog
 If OFD.ShowDialog = DialogResult.OK Then
  'If the user didn't cancel then load the wavefile into its wrapper
  WaveFile.LoadFromFile(OFD.FileName)
  'Modify the sample rate(not all speeds are compatible without adjusting other properties)
  WaveFile.FileFormatSubChunk.SampleRate = Wave.WavSampleRate.hz22050
  'Create a new memory stream  from the bytes of the wavefile
  Dim Stream As New IO.MemoryStream(WaveFile.GetBytes)
  'Play the wavefile
  My.Computer.Audio.Play(Stream, AudioPlayMode.Background)
 End If
 End Sub
End Class
  • Add a new class to your project
  • Replace all of that Class's code with the following code:
Option Strict On
Imports System.Text
Public Class Wave
 'By Paul Ishak
 'WAVE PCM soundfile format
 'The Canonical WAVE file format
 'The File's Header
 Public FileHeader As Header
 'Wave File's Format Sub Chunk
 Public FileFormatSubChunk As FormatSubChunk
 'Data Subchunk
 Public FileDataSubChunk As DataSubChunk
 'This structure is an optional parameter for creating a new wave file
 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
 'These are the various structures in the wave file and their description
 '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 LoadFromFile(ByVal FileName As String)
 If Not My.Computer.FileSystem.FileExists(FileName) Then Exit Sub
 Dim FileBytes() As Byte = My.Computer.FileSystem.ReadAllBytes(FileName)
 Try
  Me.FileHeader.ChunkID = GetDataFromByteArray(FileBytes, 0, 0, 4)
  Me.FileHeader.ChunkSize = BitConverter.ToUInt32(FileBytes, 4)
  Me.FileHeader.Format = GetDataFromByteArray(FileBytes, 0, 8, 4)
  Me.FileFormatSubChunk.Subchunk1ID = GetDataFromByteArray(FileBytes, 0, 12, 4)
  Me.FileFormatSubChunk.Subchunk1Size = BitConverter.ToUInt32(FileBytes, 16)
  Me.FileFormatSubChunk.AudioFormat = BitConverter.ToUInt16(FileBytes, 20)
  Me.FileFormatSubChunk.NumChannels = BitConverter.ToUInt16(FileBytes, 22)
  Me.FileFormatSubChunk.SampleRate = BitConverter.ToUInt32(FileBytes, 24)
  Me.FileFormatSubChunk.ByteRate = BitConverter.ToUInt32(FileBytes, 28)
  Me.FileFormatSubChunk.BlockAlign = BitConverter.ToUInt16(FileBytes, 32)
  Me.FileFormatSubChunk.BitsPerSample = BitConverter.ToUInt16(FileBytes, 34)
  Me.FileDataSubChunk.Subchunk2ID = GetDataFromByteArray(FileBytes, 0, 36, 4)
  Me.FileDataSubChunk.Subchunk2Size = BitConverter.ToUInt32(FileBytes, 40)
  Me.FileDataSubChunk.Data = GetDataFromByteArray(FileBytes, 0, 44, Me.FileDataSubChunk.Subchunk2Size)
 Catch
  Throw New Exception("File Is Invalid or corrupt!")
 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
 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 Answer(0 To CInt((DataLength - 1))) As 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
 Dim count As Integer = -1
 For Each bt As Byte In AnswerL
  count = count + 1
  Answer(count) = bt
 Next
 Return Answer
 End Function
 Sub New(Optional ByVal Options As WaveFileOptions = Nothing)
 Try
  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
 Catch ex As Exception
 End Try
 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

References

See also

Please check out my other Technet Wiki articles!