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 RecommendedOption
Strict OnImports
System.TextPublic
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
SubEnd
Class- Add a new class to your project
- Replace all of that Class's code with the following code:
Option
Strict OnImports
System.TextPublic
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
EnumEnd
ClassReferences
- 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!