Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: [WAV] Bad reproduction after rewriting the file (Read 2355 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

[WAV] Bad reproduction after rewriting the file

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:
Code: [Select]
    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

[WAV] Bad reproduction after rewriting the file

Reply #1
I found the solution myself. I didn't count the negative integer values in ToLittleEndian e ToBigEndian methods!