How to change the speed at which you play your wavefile

I have seen this question posted multiple times in the forums and figured I would share here as well.

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
            '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)
            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)
            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
                End If
            End If
        Dim count As Integer = -1
        For Each bt As Byte In AnswerL
            count = count + 1
            Answer(count) = bt
        Return Answer
    End Function
    Sub New(Optional ByVal Options As WaveFileOptions = Nothing)
            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


I hope you find this helpful

Please check out my other Technet Wiki articles!