4

How can I merge two wav files using java?

I tried this but it didn't work correctly, is their any other way to do it?

Community
  • 1
  • 1
Alex K
  • 5,092
  • 15
  • 50
  • 77
  • 2
    How didn't it work correctly? What went wrong? – Buhake Sindi Apr 05 '10 at 14:37
  • The result file came out too short. You need to consider that each file of the files that I try to merge takes 1 sec or even less. Maybe this is the cause. – Alex K Apr 05 '10 at 14:55
  • So each file is 1 second long or less? The maximum song length will be 2 second then? Isn't what yours is doing? – Buhake Sindi Apr 05 '10 at 15:15
  • I think I know what is the problem. How can I add 1 sec (or more) of empty audio between this two files? – Alex K Apr 05 '10 at 15:45

2 Answers2

14

If you work with the bytes of a wav file directly you can use the same strategy in any programming language. For this example I'll assume the two source files have the same bitrate/numchannels and are the same length/size. (if not you can probably edit them before starting the merge).

First look over the wav specificaiton, I found a good one at a stanford course website:

Common header lengths are 44 or 46 bytes.

If you want to concatenate two files (ie play one wav then the other in a single file):

  1. find out what format your wav files are
  2. chop off the first 44/46 bytes which are the headers, the remainder of the file is the data
  3. create a new file and stick one of the headers in that.

    new wav file = {header} = {44/46} bytes long

  4. add the two data parts from the original files

    new wav file = {header + data1 + data2 } = {44/46 + size(data1) + size(data2)} bytes long

  5. modify your header in two places to reflect the new file's length.

    a. modify bytes 4+4 (ie. 4 bytes starting at offset 4). The new value should be a hexadecimal number representing the size of the new wav file in bytes {44/46 + size(data1) + size(data2)} - 8bytes.

    b. modify bytes 40+4 or 42+4 (the 4 bytes starting at offset 40 or 42, depending on if you have a 44byte header or 46 byte header). The new value should be a hexadecimal number representing the total size of the new wav file. ie {44/46 + size(data1) + size(data2)}

If you want to instead merge or mix the two files (so that they both play at the same time then):

  1. you won't have to edit the header if both files are the same length.
  2. starting at byte 44/46 you will have to edit each sample to be the value in data1 + the value in data2. so for example if your SampleRate was 8 bits you would modify 1 byte, if your sample rate was 16bits you would modify 2 bytes. the rest of the file is just Samples of 1/2bytes storing an int value representing the waveform of the sound at that time.

    a. For each of the remaining samples in the file grab the 1/2 byte hex string and get the int value from both files data1 and data2.

    b. add the 1/2 byte integers together convert the result back to hexadecimal and use that value in your output file.

    c. You normally have to divide that number by 2 to get an average value that fits back in the original 1/2byte sample block. I was getting distortion when i tried it in objc(probably related to signed or unsigned ints) and just skipped the division part since it will only likely be a problem if you are merging very loud sounds together. ie when data1 + data2 is larger than 1/2 bytes the sound will clip. There was a discussion about the clipping issue here and you may want to try one of those clipping techniques.

Scott Stensland
  • 26,870
  • 12
  • 93
  • 104
Thamster
  • 156
  • 1
  • 3
  • Hi Thamster, i want to merge two wav files.i did that but after merging them we can here both songs and also with songs noise also occuring..please help me...int a =buffer_1[i]/2; int b =buffer_2[i]/2; int c = (a+b); datafinal[i]=(byte) c; – sandeep Apr 04 '13 at 09:57
  • Thanks for this solution. Not dividing by 2 gave me distortion for anyone who may encounter this in the future. I'm adding every byte individually for a 16-bit PCM file. – Anshuul Kai Nov 14 '17 at 15:46
2

Merge implies mixing, but it sounds like you mean concatenation here.

To concatenate with silence in the middle you need to insert a number of frames of silence into the file. A silent frame is one where every channel has a "0" - if you are using signed samples this is literally a 0, for unsigned, it is maxvalue/2.

Each frame will have one sample for each channel. So to generate one second of silence in CD format, you would insert 44100 (hz) * 2 (channels per frame) = 88200 16 bit signed ints with a value of 0 each. I am not sure how to access the raw file abstracted by the Java audio abstractions, but that is the data to insert.

Justin Smith
  • 2,503
  • 14
  • 12