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: Concatenating MP3s using Java (Read 10000 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Concatenating MP3s using Java

Hi. I'm trying to use Java to programmatically combine multiple MP3 files together, i.e., literally "concatenate" them. I am learning real quick that I can't always just read one MP3 file into memory, add the next, etc., and then just save this bulk of memory into a file (I say "can't always" because this actually worked for some of the samples I've played around with).

I have been looking over the internet for information on how to do this correctly, and I simply can't find how to do this.  Right now, I'd be happy if I could only get information on how to do this with WAV files, and then just convert it to MP3 through some command-line utility.

Does anyone have any suggestions on how I can accomplish my seemingly simple goal? I would GREATLY appreciate it.

Thanks in advance.

Concatenating MP3s using Java

Reply #1
Quote
I am learning real quick that I can't always just read one MP3 file into memory, add the next, etc., and then just save this bulk of memory into a file (I say "can't always" because this actually worked for some of the samples I've played around with).
If the files are capable of being concatenated together, this will work. If they can't be concatenated together, it won't work. There might be a bit of a gap at the join point, or a sync error if the second file has tags at the beginning, but the resultant file will play if the files can be concatenated.

Doing it that way should play most of the time, but you seem to imply that generally it does not work. From what I know, at least Foobar will be able to read two concatenated files as long as they have the same sample rate. How did you test for success?

Quote
Right now, I'd be happy if I could only get information on how to do this with WAV files, and then just convert it to MP3 through some command-line utility.
Doing it from a WAV file is fairly straightforward. Just read the WAV header on both files, verify that they are concatenatable(?), make a new header with the updated length, then stick both of the data parts right after it. There are a lot of pages which go over the WAV file format (actually you'll find it called the RIFF file format a lot) this page seems to be pretty informational.
By far the most common header is 44 bytes long. If you know where you're getting your WAVs from, you should be able to just code for that case.
"We demand rigidly defined areas of doubt and uncertainty!" - Vroomfondel, H2G2

Concatenating MP3s using Java

Reply #2
Thanks for your reply, Omion.

I test for success by playing back the MP3 combined result, as the gap is audibly ostensible.

The weird part is that when I play my three MP3 files through ITunes in succession, the three sound seamless. So ITunes is apparently doing it right. It also plays back seamless with ProTools.

I have downloaded several MP3 "joiners" or "mergers" over the past days, and they are generating a non-seamless result as well.

How can knowledge on how to do this be so elusive? I wish someone could provide me document specifications on how to do this seemingly simple operation. I need to merge MP3 files seamlessly, that's all I care about.

I am also willing to pay for such services, if there's anyone out there who can help me at the technical level. I can be reached at inq@pilby.us.

Thanks.

Concatenating MP3s using Java

Reply #3
You seem to have found why we say that MP3 is not a gapless *fileformat*.
You cannot do that, because the data in MP3 is encoded/decoded in blocks, and the samples in blocks are >= than the actual samples.
Encoders like LAME (and now iTunes) add some extra data to the headers so that players can know how many samples of the last/first block it should discard at playback time.
If you simply concatenate them. such information is not available.

Do you need to have an mp3 in the end?

Concatenating MP3s using Java

Reply #4
I test for success by playing back the MP3 combined result, as the gap is audibly ostensible.

The weird part is that when I play my three MP3 files through ITunes in succession, the three sound seamless. So ITunes is apparently doing it right. It also plays back seamless with ProTools.

I have downloaded several MP3 "joiners" or "mergers" over the past days, and they are generating a non-seamless result as well.

How can knowledge on how to do this be so elusive? I wish someone could provide me document specifications on how to do this seemingly simple operation. I need to merge MP3 files seamlessly, that's all I care about.


Aha!

As Jaz has just mentioned,

MP3 is not a gapless format, instrinsically for two reasons:
  • encoder padding or delay
  • block/frame length (576 or 1152 samples) different to audio CD frame lengh (588 samples)

The LAME encoder stores the information on padding and accurate track length in the LAME header, allowing decoders that recognise this extra info (like foobar2000 or lame itself, when used as a decoder) to produce true gapless playback when separate files are played, but preserve gaps that were there on the original CD.

Other attempts to make gapless playback from a list of separate MP3 files simply try to detect and eliminate silence or sounds so quiet they're assumed to be silent, and possibly smooth over the join in some way. That's possibly what iTunes is doing when there's no accurate length data in the files.

Programs like mp3DirectCut can be used to join MP3 files without decoding and re-encoding (transcoding is detrimental to quality), but you'll again find gaps and need to delete one or two frames from near the join point. I've tried this on a few files from a DJ-mixed album encoded by FhG fastenc and the results were satisfactory, albeit a slightly imperfect reconstruction of the original CD rhythm/timing.

If you're prepared to use Java to analyze the files, remove tags and perhaps discard certain frames near the join as a matter of course, you might get a more gapless-sounding result. You'd need to get to grips with the MP3 frame format to identify the appropriate boundaries and any tags that need elimination.

Using any gapless format (including PCM WAV files) then converting to MP3 would work perfectly, assuming of course that all the music is at the same sample rate and mode (e.g. 44.1 kHz, stereo like a CD). For a WAV, you cannot simply concatenate, but need to remove the RIFF header on the second file. You can search for the specifications, but I think it's always a constant number of bytes.

You should note that the WAV format is a generic container for audio, so some WAV files can contain embedded MP3 files or ADPCM encoded audio (a simple encoding used widely in Windows system sounds, particularly early versions like Windows 95 and Windows 3.1). We sloppily use WAV in the most common sense, to denote PCM, and in particular 44.1 kHz stereo 16-bit per channel PCM, which you get by ripping an audio CD.

Depending on how robust your Java software should be, you might want to check the RIFF header to ensure that each WAV you concatenate is PCM, perhaps to check that it's 44.1 kHz stereo 16-bit PCM and otherwise report an error.

An alternative to WAV is to create a RAW file, which contains only the PCM data with no header or footer to explain the sample rate, the bit-depth (e.g. 16-bit)  the stereo mode or which channel comes first. Many audio editors can output RAW format. Assuming they have the same sample rate, bit depth and byte order, two RAW files may be concatenated directly, the way you're doing it now. The LAME encoder can accept RAW input, but you should tell it using commandline switches such as -r (to say it's a RAW PCM file) and, if neccessary, to override the default sampling frequency, byte-order and bitwidth (see lame --longhelp).
Dynamic – the artist formerly known as DickD