I am writing some code to manipulate wave files. I have written the code to change sample rate, number of channels and to cut a single waveform part. After performing these operations, the code creates a new *.wav file with changed features, but windows media player and gom player are not able to play it. If I use the system reproduction method - in vb2008 the method is My.Computer.Audio.Play("file") - it plays the file without problems but the quality is very very low. There is a great audio noise that there wasn't before, and i didn't changed the waveform. For example, cutting a wav slice, thus leaving sample rate, channels' number and significant bits unalerted, result in a new wave file, that is cut correclty, but the reproduction is very bad: it seems that over the normal waveform it has added a new layer of noise. Can anyone help me?
The significant code is the following:
Private Stream As IO.FileStream
'...
Public Shared Function ToLittleEndian(ByVal Value As Int32, ByVal BitSize As Byte) As Byte()
If BitSize <> 8 And BitSize <> 16 And BitSize <> 24 And BitSize <> 32 Then
Throw New ArgumentException("BitSize deve essere 8, 16, 24 o 32.")
End If
Dim Result(BitSize / 8 - 1) As Byte
Dim Temp As Byte
For I As Byte = 0 To Result.Length - 1
For J As Byte = 0 To 7
Temp = 2 ^ (7 - J) * If((Value And (2 ^ (8 * I + 7 - J))) = 2 ^ (8 * I + 7 - J), 1, 0)
Result(I) += Temp
Value -= Temp
Next
Next
Return Result
End Function
'...
Public Sub New(ByVal Samples()() As Int32, ByVal SampleRate As Int32, ByVal SignificantBitsPerSample As Int16)
Stream = New IO.FileStream(IO.Path.GetRandomFileName(), IO.FileMode.Create)
_SampleRate = SampleRate
_SignificantBitsPerSample = SignificantBitsPerSample
_ChannelsNumber = Samples(0).Length
_SamplesNumber = Samples.Length
_CompressionMode = CompressionCode.PcmUncompressed
WriteMainHeader()
WriteFormatChunk()
WriteDataChunkHeader()
DataStartIndex = Stream.Position
DataSize = Me.SamplesNumber * Me.BlockAlign
For I As Int64 = 0 To Samples.LongLength - 1
For J As Byte = 0 To Me.ChannelsNumber - 1
Stream.Write(ToLittleEndian(Samples(I)(J), Me.SignificantBitsPerSample), 0, Me.SignificantBitsPerSample / 8)
Next
Next
Stream.Position = 0
End Sub
Public Sub New(ByVal BaseWave As Wave, ByVal SampleIndex As Int32, ByVal Length As Int32)
Me.New(BaseWave.ReadSamples(SampleIndex, Length), BaseWave.SampleRate, BaseWave.SignificantBitsPerSample)
End Sub
'...
Private Shared Sub WriteMainHeader(ByVal WaveStream As IO.FileStream, ByVal FileSize As Int32)
WaveStream.Position = 0
With WaveStream
.Write(ASCIIEncoding.ASCII.GetBytes("RIFF"), 0, 4)
.Write(ToLittleEndian(FileSize, 32), 0, 4)
.Write(ASCIIEncoding.ASCII.GetBytes("WAVE"), 0, 4)
End With
End Sub
Private Sub WriteMainHeader(ByVal WaveStream As IO.FileStream)
WriteMainHeader(WaveStream, Me.SamplesNumber * Me.BlockAlign + 44 - 8)
End Sub
Private Sub WriteMainHeader()
WriteMainHeader(Stream)
End Sub
Private Shared Sub WriteFormatChunk(ByVal WaveStream As IO.FileStream, ByVal CompressionMode As CompressionCode, _
ByVal ChannelsNumber As Int16, ByVal SampleRate As Int32, ByVal SignificantBitsPerSample As Int16)
Dim Writer As New IO.BinaryWriter(WaveStream)
Dim BlockAlign As Int16 = ChannelsNumber * SignificantBitsPerSample / 8
Dim BytesPerSecond As Int32 = SampleRate * BlockAlign
With Writer
.Write(New Char() {"f", "m", "t", " "})
.Write(ToLittleEndian(16, 32))
.Write(ToLittleEndian(CompressionMode, 16))
.Write(ToLittleEndian(ChannelsNumber, 16))
.Write(ToLittleEndian(SampleRate, 32))
.Write(ToLittleEndian(BytesPerSecond, 32))
.Write(ToLittleEndian(BlockAlign, 16))
.Write(ToLittleEndian(SignificantBitsPerSample, 16))
End With
Writer = Nothing
End Sub
Private Sub WriteFormatChunk(ByVal WaveStream As IO.FileStream)
WriteFormatChunk(WaveStream, Me.CompressionMode, Me.ChannelsNumber, Me.SampleRate, Me.SignificantBitsPerSample)
End Sub
Private Sub WriteFormatChunk()
WriteFormatChunk(Stream)
End Sub
Private Shared Sub WriteDataChunkHeader(ByVal WaveStream As IO.FileStream, ByVal DataSize As Int32)
WaveStream.Write(System.Text.ASCIIEncoding.ASCII.GetBytes("data"), 0, 4)
WaveStream.Write(ToLittleEndian(DataSize, 32), 0, 4)
End Sub
Private Sub WriteDataChunkHeader(ByVal WaveStream As IO.FileStream)
WriteDataChunkHeader(WaveStream, Me.SamplesNumber * Me.BlockAlign)
End Sub
Private Sub WriteDataChunkHeader()
WriteDataChunkHeader(Stream)
End Sub
'...
Public Sub Save(ByVal FileName As String)
Dim Writer As New IO.FileStream(FileName, IO.FileMode.Create)
Dim Buffer(Stream.Length - 1) As Byte
Stream.Position = 0
Stream.Read(Buffer, 0, Stream.Length)
Writer.Write(Buffer, 0, Buffer.Length)
Stream.Position = 0
Writer.Close()
Buffer = Nothing
End Sub