2009-09-21 2 views
4

Я попытался объединить 2 файла MP3, используя код ниже. У меня есть новый файл, который я могу воспроизвести в первой половине (полный первый файл), но вторая половина молчат. Длина нового файла была правильной. Что я делаю неправильно?C#: concatenate 2 файла MP3

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); 
+1

У обоих файлов одинаковый битрейт? – jao

+0

да и: Мне нужно вырезать заголовок второго файла или что-то в этом роде – Markus

+0

есть ошибка в вашем коде. вы слышите только вторую песню. см. мой ответ ниже –

ответ

10

Я готов поспорить, что вы слышите только вторую песню. (и что оба файла имеют одинаковую длину или первый короче)

Вы копируете данные второй песни по первой. И данные MP3 транслируются, поэтому вы можете просто добавлять файлы друг к другу, не беспокоясь о битрейтах (в то время как они могут сбой) битрейт должен автоматически настраиваться.

Деталь на MP3 Frame headers

... попробуйте это ...

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

... или еще лучше ...

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(); 
} 
+2

это будет работать, но вы, скорее всего, получите ID3-теги, сидящие в середине выходного файла. Лучше всего отключить их (по крайней мере для последующих файлов) –

+0

Очень верно, но из-за заголовков кадров это не должно влиять на звук. –

+0

Пропаривание? Или вы имели в виду потоковое вещание? – Svish

1

В каждом файле MP3 есть заголовок в начале файла, содержащего метаданные песни. По крайней мере вам придется удалить это во втором файле.

Предыдущая предыдущая проблема переполнения стека, How do I merge/join MP3 files with C#?.

Дополнительная информация к Read MP3 Tag Information (ID3v1 and ID3v2), это может помочь вам удалить его.

+0

и как я могу его отключить? – Markus

+1

, возможно, просто пропустить эти многие байты помогут. Дополнительную информацию о формате MP3 можно найти здесь http://www.mp3-tech.org/programmer/frame_header.html – TheVillageIdiot

1

Этот вопрос был задан до here и here. Также см. reading MP3 Headers in C#, но вместо того, чтобы читать заголовок, вы просто хотите его отключить, объедините остальные, затем сгенерируйте новый заголовок для конкатенированного файла.

Редактировать: После дальнейшего чтения, по-видимому, это не имеет никакого значения, если вы просто конкатенируете файлы, не снимая теги ID3. Но по-прежнему кажется хорошей идеей вырезать их в первую очередь.

+0

Я не могу найти что-нибудь в этом сообщении, которое мне помогает. Как я могу отрезать заголовок? – Markus

+0

узнать, где он заканчивается, и начать копирование там –

1

Вот как вы можете сцепить MP3 файлы с помощью 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); 
     } 
    } 
} 

См here для получения дополнительной информации.

+0

где же остальная отметка? как вы сохраняете поток в качестве нового mp3-файла? скажите, пожалуйста, как вы называете эту функцию Combine, где раньше? – MonsterMMORPG

2

Простой:

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))); 
    } 
} 
+0

работает идеально и потрясающе изящное решение – MonsterMMORPG

+1

почему вы создадите список, чтобы перебирать множество? просто используйте ключевое слово foreach. –

1

Как все знают, что MP3-файлы только некоторые кадры и вы можете объединить потоки вместе:

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(); 
} 

и слышит использование:

Concatenate("D:\\1.mp3", "D:\\2.mp3");