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
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
'As Described Here:
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
'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
()
&nb>As
FormatSize
Public
NumberOfSamples
As
UInt32
Public
Data
As
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.
p; Contains the letters "fmt "(0x666d7420 big-endian form).
Public
Property
Subchunk1Size
As
UInt32
' Dword  
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
Sub
Dim
FileBytes()
As
Byte
= My.Computer.FileSystem.ReadAllBytes(FileName)
Try
.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
Throw
New
Exception(
"File Is Invalid or corrupt!"
)
EndSub
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
="color:#000000;">
DataLength As
Long
)
As
Byte
()
On
Error
Resume
Next
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
count = count + 1
Answer(count) = bt
Next
Return
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
Format
As
UInt16
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
- https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
- MSDN Forums - http://social.msdn.microsoft.com/Forums/en-US/categories
I hope you find this helpful
Please check out my other Technet Wiki articles!