Click here to Skip to main content
15,887,911 members
Please Sign up or sign in to vote.
4.00/5 (2 votes)
See more:
Hi!

I've written a Visual Studio 2008 project in VB.Net based off the Concatenating Wave Files Using C# 2005[^] project. I wanted to re-write it so that I could understand what's going on and because I wanted to join more than two wave files.

My project has an issue I wondered if you could help with? When I join files, in the resulting merged file, the first file plays fine, but next one is corrupted. That's the pattern: good file/bad file/good file/bad file...

Here's the code that produces the merged file:

VB
For Each strFile In strFiles

    fsInput = New FileStream(strFile, FileMode.Open, FileAccess.Read)

    Dim byteWaveData(fsInput.Length - 44) As Byte

    fsInput.Position = 44
    fsInput.Read(byteWaveData, 0, byteWaveData.Length)
    fsInput.Close()
    fsInput = Nothing

    fsOutput = New FileStream(strNewFileName, FileMode.Append, FileAccess.Write)
    bwOutput = New BinaryWriter(fsOutput)
    bwOutput.Write(byteWaveData)

    bwOutput.Close()
    fsOutput.Close()

    bwOutput = Nothing
    fsOutput = Nothing

    byteWaveData = Nothing

Next


If I load all the input into the byte array and then issue a single write to the output, each of the joined segments in the merged file play correctly.

Can you see what might be causing the problem?

Thanks!
Phil Jones

>>Having only one header for the merged files also implies that the sample rate and other important parameters
>>of the files must much. Since you didn't elaborate what kind of corruption you encountered I take it
>>that the corruption could very well come from this.
>>If you want serious help with you problem please feel free to edit your question and add the relevant
>>details.

I did read the article carefully, along with several other articles on the web, including 3 pages that describe the file format for WAVE files.

The term "one header" is somewhat misleading. RIFF specification WAVE (PCM) file formats are arranged in chunks and sub-chunks. Each file has one "RIFF" chunk, one "fmt" sub-chunk, and usually only one "data" sub-chunk (though it can have more than one "data" sub-chunk).

If my "RIFF" chunk had incorrect data in it, the entire file would not play at all. That's not the case. The 1st joined file portion of the "data" sub-chunk plays correctly, the 2nd only produces hissing noise, the 3rd play correctly, the 4th produces hissing noise, etc.

As I noted in the original post, if I change my code to load all the "data" sub-chunk inputs into a single byte array and then perform a single BinaryWrite operation to the merged file, the entire file plays without any error whatsoever. I only get the problem if I perform a BinaryWrite operation after each file input, which is what I would prefer doing as WAVE files can be as large as 4 GBs.

Loading 4 GBs into a single ByteArray would be a serious memory intensive operation. I know because I tested that scenario using a single BinaryWrite operation (the merged file played correctly, by the way). After the test, I had to reboot my PC (which has 4 GBs of ram) because it was sluggish after the test.

Having looked over the previous web pages on WAVE file formats again, the only thought I have at the moment relates to the information that WAVE file chunks and sub-chunks are supposed to end on full Word boundaries. If they do not, they are supposed to be padded with binary zeroes. I'm not coding for that, but then again, Ehab Mohamed Essa's original project (which is excellent, by the way... thank you Mr. Essa if you're reading this), does not code for that either, and his project does not result in my problem; I've tested it.

So unless there's some difference between C# (which I know little about) and VB, then the Word boundary issue may not be the problem.

To be clear, every WAVE file I'm testing with has exactly the same encoding (the same channels, audio format, sample rate, sample size and bit rate).

As a test, I ran the same two WAVE files through Mr. Essa's project and mine. In the separate merged files, the "RIFF" chunks and the "fmt" sub-chunks are exactly the same. The only difference between the two merged files is that my file is longer. Eacy BinaryWrite operation apparently adds 1 byte to the file's length, and I can't account for it.
Posted
Updated 25-Apr-11 2:16am
v4
Comments
Manfred Rudolf Bihy 25-Apr-11 10:50am    
The update to your question is very good and helpful :thumbsup:, but in order for me to get notified about the change leave a comment on the solution. I came back because I found your question quite interesting so I saw that you had updated you question. Please see the update to my solution for another idea.
TheBitSlinger 25-Apr-11 11:39am    
I was able to compare two samples in HxD. It said the files match exactly, expect that my file is 1 byte bigger with a HEX '00' tacked onto the end of the file.

If you read the article you mentioned carefully you'd have run across this:
"We must be careful when writing the header. If there is any small mistake, the merged file doesn't work, so we write "RIFF" as an array of char, not as string and use int type for storing 4 bytes and short type for storing 2 bytes."


Having only one header for the merged files also implies that the sample rate and other important parameters of the files must much. Since you didn't elaborate what kind of corruption you encountered I take it that the corruption could very well come from this.

If you want serious help with you problem please feel free to edit your question and add the relevant details.

[Update]:

If the generated merged files lengths differ from your project to Mr. Essa's you could try to analyze the difference either with a hex editor or even just write a small programm that reads both files byte for byte and compares them outputting the bytes that differ and their respective position.

[End Update]

Best Regards,

-MRB
 
Share this answer
 
v2
Comments
TheBitSlinger 25-Apr-11 10:57am    
Excellent suggestion! I'll see if I can open the files in UltraEdit and do the Hex examination. Anything else, as you rightly point out, would be guess-work.
Phil,

I am not 100% sure this is the problem but when you mentioned that 1 byte difference for every single write, I just thought of it.

The article is in C#. Your code is in VB.

You have VB code like this:

VB
Dim byteWaveData(fsInput.Length - 44) As Byte


The matching C# code for that is:

C#
byte[] byteWaveData = new byte[fsInput.Length - 43];


So if you need 44 bytes off, then your VB code needs to be:

VB
Dim byteWaveData(fsInput.Length - 45) As Byte


Worth trying.
 
Share this answer
 
v3
Comments
TheBitSlinger 25-Apr-11 11:44am    
So C# sharp IS different from VB. Is the difference that offsets in C# start with 1, while offsets in VB start with 0? I'd say that has to be the problem, because as I noted in my comment to MRB's excellent suggestion, my merged file is one byte longer than the sample I created with the original project.
Nish Nishant 25-Apr-11 11:50am    
C# and VB start at 0, but in C# when you define an array of n items, the index goes from 0 to n-1. In VB when you define an array of n items, the index goes from 0 to n (so you actually create an n+1 array). VB does this to be backward compatible with VB6 code where this was the norm.
TheBitSlinger 25-Apr-11 12:12pm    
Okay, I follow what you're saying. I'm just talking through this so I fully understand... Say my input file has a length of 1,500, and I want to create array to hold bytes 45 through 1,500, which is 1,456 bytes. The boundaries of the array in both C# and VB.Net would be 0 to 1,455, but since VB.Net arrays are sized relative to n + 1, that has to be accounted for. Blah, I knew I was missing something about C# vs VB.Net. Thanks!
Nish Nishant 25-Apr-11 12:18pm    
Yes, your understanding is correct. And you are most welcome. Glad it helped.
TheBitSlinger 25-Apr-11 23:42pm    
It worked! Thanks to everyone who helped out!
Hi first 44 bytes of wav is header , but from 40 to 44 is data len and very important for playing wave , you should update 4 byte (40,41,42,43) after append binary data .
 
Share this answer
 
Comments
Nelek 1-Sep-13 8:38am    
Do you realize that you are answering to an already solved question almost 2,5 years old?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900