Results 1 to 4 of 4

Thread: [RESOLVED] Concatenate .wav files via byte array

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Dec 2007
    Location
    West Yorkshire, UK
    Posts
    791

    Resolved [RESOLVED] Concatenate .wav files via byte array

    I want to concatenate two .wav files. The file format for a .wav is bytes 0 to 39 file details, bytes 40 to 43 length of the data chunk, 44 onwards is the data.
    The method I have chosen is:
    1. load two wavs as byte arrays (byt1 and byt2)
    2. copy the header from byt1 and store it
    3. copy the data portion of byt1 to another byte array (finalData)
    4. copy the data from byt2 and add it to the end if FinalData.
    5. Create a final finished byte array representation of the wav (Output)
    6. Copy the previously saved header to Output.
    7. store the length of FinalData.
    8. Add FinalData to the end of Output
    9. Convert the previously saved length (int32=4 bytes) to byte array
    10. Overwrite bytes 40-43 of Output with the new length
    11. Save the final file to disk.

    When I run the program, there are no errors until it tries to play the file, then it says the header is corrupt. Since both wav files are created in exactly the same way, things like sample rate etc are the same, the only thing that should change is the length and therefore I should have no problem retaining the information in the header. Giving a corrupt header error probably means that the length is wrong but I have checked and checked and can't find a mistake in my maths.
    this is my first foray into Byte arrays so I need another pair of more experienced eyes to look over my code please.
    vb.net Code:
    1. Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    2.         Dim Byt1() As Byte = IO.File.ReadAllBytes("h.wav")
    3.         Dim Byt2() As Byte = IO.File.ReadAllBytes("e.wav")
    4.         Join(Byt1, Byt2)
    5.         Byt1 = IO.File.ReadAllBytes("temp.wav")
    6.         Byt2 = IO.File.ReadAllBytes("l.wav")
    7.         Join(Byt1, Byt2)
    8.         Byt1 = IO.File.ReadAllBytes("temp.wav")
    9.         Byt2 = IO.File.ReadAllBytes("ow.wav")
    10.         Join(Byt1, Byt2)
    11.         Dim snd As New System.Media.SoundPlayer("temp.wav")
    12.         snd.Play()
    13.     End Sub
    14.  
    15.     Private Sub Join(ByRef byt1() As Byte, byt2() As Byte)
    16.  
    17.         Dim Lgth As Integer
    18.         Dim SaveHeader(43) As Byte
    19.  
    20.         'Save the header
    21.         System.Array.Copy(Byt1, 0, SaveHeader, 0, 43)
    22.         Dim FinalData(byt1.Length - 44) As Byte
    23.  
    24.         'Save the data from the first file
    25.         System.Array.Copy(Byt1, 44, FinalData, 0, Byt1.Length - 44)
    26.  
    27.         'Save the data from the second file
    28.         ReDim Preserve FinalData(byt1.Length + byt2.Length - 44)
    29.         System.Array.Copy(byt2, 44, FinalData, byt1.Length - 44, byt2.Length - 44)
    30.  
    31.         'save length of new data
    32.         Lgth = FinalData.Length
    33.  
    34.         'create array to hold final output
    35.         Dim Output() As Byte
    36.         ReDim Output(FinalData.Length + 43)
    37.  
    38.         'add header
    39.         System.Array.Copy(SaveHeader, Output, 43)
    40.  
    41.         'add data
    42.         System.Array.Copy(FinalData, 0, Output, 44, FinalData.Length)
    43.  
    44.         'adjust data length
    45.         Dim bytes() As Byte = BitConverter.GetBytes(Lgth)
    46.         System.Array.Copy(bytes, 0, Output, 40, 4)
    47.         ByteArrayToFile("temp.wav", Output)
    48.  
    49.     End Sub
    50.  
    51.     ' <summary>
    52.     ' Function to save byte array to a file
    53.     ' </summary>
    54.     ' <param name="_FileName">File name to save byte array</param>
    55.     ' <param name="_ByteArray">Byte array to save to external file</param>
    56.     ' <returns>Return true if byte array save successfully, if not return false</returns>
    57.     Public Sub ByteArrayToFile(ByVal _FileName As String, ByVal _ByteArray() As Byte)
    58.         Try
    59.             'Dim myInt As Int32
    60.             'myint = BitConverter.ToInt32(_ByteArray, 40)
    61.             'MsgBox("Length of file " & BitConverter.ToString(BitConverter.GetBytes(_ByteArray.Length)) & ". Length stored in header " & BitConverter.ToString(BitConverter.GetBytes(myInt)))
    62.             '' Open file for readin
    63.             Dim _FileStream As New System.IO.FileStream(_FileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write)
    64.             ' Writes a block of bytes to this stream using data from a byte array.
    65.             _FileStream.Write(_ByteArray, 0, _ByteArray.Length)
    66.             ' close file stream
    67.             _FileStream.Close()
    68.  
    69.         Catch _Exception As Exception
    70.             ' Error
    71.             Console.WriteLine("Exception caught in process: {0}", _Exception.ToString())
    72.         End Try
    73.         ' error occured, return false
    74.  
    75.     End Sub
    Last edited by Españolita; Mar 20th, 2013 at 05:51 AM.

  2. #2
    Frenzied Member
    Join Date
    Jul 2011
    Location
    UK
    Posts
    1,335

    Re: Concatenate .wav files via byte array

    Hey Españolita,

    I think you may have a couple of problems there.

    You seem to be doing what I typically do; getting confused over array upper bounds and array lengths. By this I mean that an array with a Length of 44 (44 elements) has an upper bound of 43 (the highest index value you can access). Zero indexing can be a pain in the bum at times.

    Also, looking at the .wav format as explained here, I think you may need to alter two length fields in the final file Header (at offsets 4 and 40).

    So your join sub should look like:

    Code:
    Private Sub Join(ByRef byt1() As Byte, byt2() As Byte)
    
        Dim Lgth As Integer
        Dim SaveHeader(43) As Byte
    
        'Save the header
        System.Array.Copy(byt1, 0, SaveHeader, 0, 44)
        Dim FinalData(byt1.Length - 44 - 1) As Byte 
    
        'Save the data from the first file
        System.Array.Copy(byt1, 44, FinalData, 0, byt1.Length - 44)
    
        'Save the data from the second file
        ReDim Preserve FinalData(byt1.Length - 44 + byt2.Length - 44 - 1)
        System.Array.Copy(byt2, 44, FinalData, byt1.Length - 44, byt2.Length - 44)
    
        'save length of new data
        Lgth = FinalData.Length
    
        'create array to hold final output
        Dim Output() As Byte
        ReDim Output(FinalData.Length + 44 - 1)
    
        'add header
        System.Array.Copy(SaveHeader, Output, 44)
    
        'add data
        System.Array.Copy(FinalData, 0, Output, 44, FinalData.Length)
    
    
        Dim bytes() As Byte
        'adjust data length (Subchunk2Size)
        bytes = BitConverter.GetBytes(Lgth)
        System.Array.Copy(bytes, 0, Output, 40, 4)
    
        'adjust data length (ChunkSize)
        bytes = BitConverter.GetBytes(Lgth + 36)
        System.Array.Copy(bytes, 0, Output, 4, 4)
    
    
        ByteArrayToFile("temp.wav", Output)
    
        End Sub

    That said, would you not consider using Lists, (and also avoid writing temporary files)?
    vb.net Code:
    1. Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    2.  
    3.  
    4.     Dim wav1 As List(Of Byte) = IO.File.ReadAllBytes("h.wav").ToList
    5.     Dim wav2 As List(Of Byte) = IO.File.ReadAllBytes("e.wav").ToList
    6.  
    7.     wav1 = Join(wav1, wav2)
    8.     wav1 = Join(wav1, IO.File.ReadAllBytes("l.wav").ToList)
    9.     wav1 = Join(wav1, IO.File.ReadAllBytes("ow.wav").ToList)
    10.  
    11.  
    12.     File.WriteAllBytes("test.wav", wav1.ToArray)
    13.  
    14.     Dim snd As New System.Media.SoundPlayer("test.wav")
    15.     snd.Play()
    16.  
    17. End Sub
    18.  
    19.  
    20. Private Function Join(ByVal wavBytes As List(Of Byte), ByVal wav2 As List(Of Byte)) As List(Of Byte)
    21.  
    22.     '   add on the second file excluding its header bytes
    23.     wavBytes.AddRange(wav2.Skip(44).Take(wav2.Count - 44))
    24.  
    25.  
    26.     '   rewrite the ChunkSize and Subchunk2Size fields of the Header
    27.     Dim chunkSize As Integer = wavBytes.Count - 8
    28.     Dim subChunk2Size As Integer = wavBytes.Count - 44
    29.  
    30.     Dim chunkSizeBytes() As Byte = BitConverter.GetBytes(chunkSize)
    31.     Dim subChunk2SizeBytes() As Byte = BitConverter.GetBytes(subChunk2Size)
    32.     For i = 0 To 3
    33.         wavBytes(4 + i) = chunkSizeBytes(i)
    34.         wavBytes(40 + i) = subChunk2SizeBytes(i)
    35.     Next
    36.  
    37.     Return wavBytes
    38. End Function

    You could also avoid saving the combined .wav to file by replacing
    Code:
    File.WriteAllBytes("test.wav", wav1.ToArray)
    
    Dim snd As New System.Media.SoundPlayer("test.wav")
    snd.Play()
    with
    Code:
    Using ms As New MemoryStream(wav1.ToArray)
        Using snd As New System.Media.SoundPlayer(ms)
            snd.Play()
        End Using
    End Using
    Last edited by Inferrd; Mar 20th, 2013 at 10:25 AM.

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Dec 2007
    Location
    West Yorkshire, UK
    Posts
    791

    Re: Concatenate .wav files via byte array

    What an absolute star!!! Thank you so much. After creating this thread, I saw another which mentioned using lists and it was on my "Upgrade list" after I got the basics of this sorted out. You were absolutely right about confusing UpperBounds and Array Lengths. I'm afraid I simply copied and pasted your code and it works brilliantly. But rest assured, I will analyse the code because that first part (chunks length at index 4) really confuses me.
    Also you must be a mindreader, because that last little bit about playing directly from memory was also on my "Upgrade list". This is my first foray into this kind of thing and I found it a bit overwhelming.
    I would have given you some more rep but I need to spread it around a bit first

  4. #4
    Registered User
    Join Date
    Oct 2014
    Posts
    1

    Re: Concatenate .wav files via byte array

    Quote Originally Posted by Españolita View Post
    What an absolute star!!! Thank you so much. After creating this thread, I saw another which mentioned using lists and it was on my "Upgrade list" after I got the basics of this sorted out. You were absolutely right about confusing UpperBounds and Array Lengths. I'm afraid I simply copied and pasted your code and it works brilliantly. But rest assured, I will analyse the code because that first part (chunks length at index 4) really confuses me.
    Also you must be a mindreader, because that last little bit about playing directly from memory was also on my "Upgrade list". This is my first foray into this kind of thing and I found it a bit overwhelming.
    I would have given you some more rep but I need to spread it around a bit first


    I have set of wav files in a folder with different length. I want to join as single file. kindly provide code for this

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width