The best — though least helpful — way to do this is not to use MP3 files as your source files. WAV, FLAC or M4A files don't have this problem.
MP3s aren't made up of fixed-rate samples, so cropping out a section of an arbitrary length will not work as you expect. Unless the encoder was smart (like lame), there will often be a gap at the start or end of the MP3 file's audio. I did a test with a sample 0.98s long (which is precisely 73½ CDDA frames, and many MP3 encoders use frames for minimum sample lengths). I then encoded the sample with three different MP3 encoders (lame, sox, and the ancient shine), then decoded those files with three decoders (lame, sox, and madplay). Here's how the sample lengths compare to the original:
Enc.→Dec. Length Samples CDDA Frames
----------------- --------- ------- -----------
shine→lame 0.95" 42095 71.5901
shine→madplay 0.97" 42624 72.4898
shine→sox 0.97" 42624 72.4898
lame→lame 0.98" 43218 73.5000
*Original 0.98" 43218 73.5000
sox→sox 0.99" 43776 74.4490
sox→lame 1.01" 44399 75.5085
lame→madplay 1.02" 44928 76.4082
lame→sox 1.02" 44928 76.4082
sox→madplay 1.02" 44928 76.4082
Only the file encoded and decoded by lame ended up the same length (mostly because lame inserts a length tag to correct for these too-short samples, and knows how to decode it). Everything encoded by sox ended up with a tiny gap, no matter what decoder I used. So joining the files will result in tiny clicks.
Your browser is likely mixing and overlapping the source files very slightly so you don't hear the clicks. Gapless playback is hard to do correctly.
Answer from scruss on Stack OverflowThe best — though least helpful — way to do this is not to use MP3 files as your source files. WAV, FLAC or M4A files don't have this problem.
MP3s aren't made up of fixed-rate samples, so cropping out a section of an arbitrary length will not work as you expect. Unless the encoder was smart (like lame), there will often be a gap at the start or end of the MP3 file's audio. I did a test with a sample 0.98s long (which is precisely 73½ CDDA frames, and many MP3 encoders use frames for minimum sample lengths). I then encoded the sample with three different MP3 encoders (lame, sox, and the ancient shine), then decoded those files with three decoders (lame, sox, and madplay). Here's how the sample lengths compare to the original:
Enc.→Dec. Length Samples CDDA Frames
----------------- --------- ------- -----------
shine→lame 0.95" 42095 71.5901
shine→madplay 0.97" 42624 72.4898
shine→sox 0.97" 42624 72.4898
lame→lame 0.98" 43218 73.5000
*Original 0.98" 43218 73.5000
sox→sox 0.99" 43776 74.4490
sox→lame 1.01" 44399 75.5085
lame→madplay 1.02" 44928 76.4082
lame→sox 1.02" 44928 76.4082
sox→madplay 1.02" 44928 76.4082
Only the file encoded and decoded by lame ended up the same length (mostly because lame inserts a length tag to correct for these too-short samples, and knows how to decode it). Everything encoded by sox ended up with a tiny gap, no matter what decoder I used. So joining the files will result in tiny clicks.
Your browser is likely mixing and overlapping the source files very slightly so you don't hear the clicks. Gapless playback is hard to do correctly.
This is my guess for your issue:
- sox does not add time gap during concatenation,
- however it add time-gap in other operations, for instance if you do a conversion before the concatenation.
To find out what happens I suggest you to check all durations of your files at each time (you can use soxi for instance) to see what's going on.
If it doesn't work (the time-gap is added during concatenation), let me please do another guess:
- Sox add time gap because your samples at the beginning or at the end of the file are not close to zero.
To solve this, you could use very short fade-in an fade-out on you files.
Moreover, to force sox to output files with a well-defined length, you could use the trim parameter like this:
sox filein.mp3 trim 0 duration fileout.mp3
You need to insert a silent track between each track as you specify them so you end up with something like:
sox track1.wav silence.wav track2.wav silence.wav ... output.wav
You can do that manually (as above), or we can loop the current directory with an inline for-loop. Something like this should work:
sox -n -r 44100 -c 2 /tmp/silence.wav trim 0.0 2
sox $(for f in *.wav; do echo -n "$f /tmp/silence.wav "; done) output.wav
The silence-generator is stolen from here.
Generate 2 seconds of (stereo) silence
sox -n -r 44100 -c 2 silence.wav trim 0.0 3.0
Combining the files
sox silence.wav filetopad.mp3 silence.wav output.wav
source http://activearchives.org/wiki/Padding_an_audio_file_with_silence_using_sox
Another possible solution
quoted from https://stackoverflow.com/questions/5587135/sox-merge-two-audio-files-with-a-pad
sox starts-last.mp3 -p pad 2 0 | sox - -m starts-second.mp3 -p pad 2 0 | sox - -m starts-first.mp3 combined.mp3
Need a batch file to merge audio files using Sox
Merge 2 audio files in sox - Stack Overflow
Combine 3 WAV files with Sox? merge and concatenate difference?
Sox : merge two audio files with a pad - Stack Overflow
If all the files have the same parameters, like sample rate and number of channels, you still can't just catenate them. You have to strip away the WAV header.
It may be easiest to use an audio file manipulation utility like sox, which contains a method for catenating files. In fact, it does this by default. E.g. to combine three .wav files into one long one:
$ sox short1.wav short2.wav short3.wav long.wav
A loop will not arrange the files in the order you want. What you want is to sort the names, but treat them numerically. sort -n will do this.
Thus:
$ sox $(ls *.wav | sort -n) out.wav
If sox cannot handle that many files, we can break up the job like this:
$ ls *.wav | sort -n > script
Then we have a script file which looks like:
1.wav
2.wav
...
3999.wav
4000.wav
...
file7500.wav
We edit that to make several command lines:
# catenate about half the files to temp1.wav
sox \
1.wav \
2.wav \
... \
3999.wav \
temp1.wav
# catenate the remainder to temp2.wav
sox \
4000.wav \
... \
7500.wav \
temp2.wav
# catenate the two halves
sox temp1.wav temp2.wav out.wav ; rm temp1.wav temp2.wav
As the first editing step on the file list, you can use the vi command :%s/.*/& \\/ to add a backslash after every line.
This has been bugging me today as well as I had many more files to concatenate than sox can load. So I ended up using this shell script inside the folder with the wavs (please make sure you don't need in.wav and out.wav as they'll be overwritten):
rm in.wav out.wav
ls *.wav | sort -n | while read l;
do
if [ ! -f in.wav ]
then
cp $l in.wav
else
sox in.wav $l out.wav
cp out.wav in.wav
fi
echo "$l"
done
``
This is poorly documented in the Sox documentation and the web. How do I use Sox to combine 3 2GB 2496 WAVs into one 2496 FLAC file?
What is the difference between "concatenate" and "merge"?
I've tried:
"C:\Program Files\sox-14-4-2\sox.exe" --combine concatenate ZOOM0002.WAV ZOOM0003.WAV ZOOM0004.WAV joined-c.flac
and
"C:\Program Files\sox-14-4-2\sox.exe" --combine merge ZOOM0002.WAV ZOOM0003.WAV ZOOM0004.WAV joined-m.flac
Both seem to do the same thing but the output files are slightly different in size. The output FLAC file should be seamless with no gaps or glitches.
You should be able to do something like:
sox short.ogg -p pad 0 6|sox - long.ogg output.ogg
-p option to sox is used for piping - basically, it tells sox to use stdout as the output. Using - as the input to the second sox is actually saying input is stdin (which happens to be the stdout of the previous sox, as we are piping with |). pad 0 6 tells pad 0 seconds at the beginning and 6 seconds at the end.
Hope this helps.
Thanks to icyrock, I managed to find a solution. I'm using:
$ sox short.ogg -p pad 6 0 | sox - -m long.ogg output.ogg
For multi tracks (credits to Orlando):
$ sox starts-last.mp3 -p pad 2 0 | sox - -m starts-second.mp3 -p pad 2 0 | sox - -m starts-first.mp3 combined.mp3
You can do it with one invocation of sox like this:
sox -m in1.mp3 in2.mp3 in3.mp3 out.mp3
If you want to combine this with the pad effect you need to be clearer about what you want.
To combine mix and effects (pad, trim etc) use the following:
sox -m "|sox end.mp3 -p pad 6 0" start.mp3 output.mp3
The general pattern is:
sox -m input1 input2 ... inputN output
where inputX can be either a filename or a pipe in quotes
"|sox end.mp3 -p pad 6"