Question

I tried to concatenate 2 MP3 files using the code below. I got a new file which I can play the first half of (complete first file), but the second half is silent. The length of the new file was correct. What do I do wrong?

List<Byte[]> files = new List<byte[]>();
var tempfile = File.ReadAllBytes(Path.Combine(path, "1.mp3"));
files.Add(tempfile);
tempfile = File.ReadAllBytes(Path.Combine(path, "2.mp3"));
files.Add(tempfile);
Byte[] a=new Byte[files[0].Length+files[1].Length];
Array.Copy(files[0], a, files[0].Length);
Array.Copy(files[1], a, files[1].Length);

File.WriteAllBytes(Path.Combine(path, "3.mp3") , a);
Was it helpful?

Solution

I am willing to bet you are only hearing the second song. (and that either both files are the same length or the first is shorter)

You are copying the second song data over the first. And MP3 data is streaming so you can just append the files to each other without worrying about bitrates (while they may glitch) the bitrate should automaticly adjust.

Detail on MP3 Frame headers

... try this...

Array.Copy(files[0], 0, a, 0, files[0].Length);
Array.Copy(files[1], 0, a, files[0].Length, files[1].Length);

... or better still...

using (var fs = File.OpenWrite(Path.Combine(path, "3.mp3")))
{
    var buffer = File.ReadAllBytes(Path.Combine(path, "1.mp3"));
    fs.Write(buffer, 0, buffer.Length);
    buffer = File.ReadAllBytes(Path.Combine(path, "2.mp3"));
    fs.Write(buffer, 0, buffer.Length);
    fs.Flush();
}

OTHER TIPS

Simple:

public static void Combine(string[] mp3Files, string mp3OuputFile)
{
    using (var w = new  BinaryWriter(File.Create(mp3OuputFile)))
    {
        new List<string>(mp3Files).ForEach(f => w.Write(File.ReadAllBytes(f)));
    }
}

Here's how you can concatenate MP3 files using NAudio:

public static void Combine(string[] inputFiles, Stream output)
{
    foreach (string file in inputFiles)
    {
        Mp3FileReader reader = new Mp3FileReader(file);
        if ((output.Position == 0) && (reader.Id3v2Tag != null))
        {
            output.Write(reader.Id3v2Tag.RawData,
                         0,
                         reader.Id3v2Tag.RawData.Length);
        }
        Mp3Frame frame;
        while ((frame = reader.ReadNextFrame()) != null)
        {
            output.Write(frame.RawData, 0, frame.RawData.Length);
        }
    }
}

See here for more information.

Each MP3 file has a header at the beginning of the file containing the metadata of the song. At the very least you will have to remove that on the second file.

Here is a previous Stack Overflow question, How do I merge/join MP3 files with C#?.

Here's another link to Read MP3 Tag Information (ID3v1 and ID3v2), it might help you remove it.

This question has been asked before here and here. Also see reading MP3 Headers in C#, but instead of reading the header you just want to strip it off, concatenate the rest, then generate a new header for the concatenated file.

Edit: After further reading apparently it doesn't make any difference if you just concatenate the files without stripping the ID3 tags. But it still seems like a good idea to strip them out first.

As all knows, the Mp3 files are just some frames and you can concatenate the streams together:

public static void Concatenate(params string[] mp3filenames)
{
    Stream w = File.OpenWrite("D:\\out.mp3");

    foreach (string filename in mp3filenames)
        File.OpenRead(filename).CopyTo(w);    

    w.Flush();
    w.Close();
}

and hears the usage:

Concatenate("D:\\1.mp3", "D:\\2.mp3");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top