2009-09-21 63 views
4

我嘗試使用下面的代碼連接2個MP3文件。我得到了一個新文件,我可以播放前半部分(完成第一個文件),但下半部分是無聲的。新文件的長度是正確的。我做錯了什麼?C#:連接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 2009-09-21 17:53:30

+0

是和: 是否必須剪下第二個文件的標頭或類似的東西 – Markus 2009-09-21 17:54:57

+0

您的代碼中存在一個錯誤。你只聽到第二首歌。看到我的回答在 – 2009-09-21 18:19:20

回答

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標籤。最好將它們去掉(至少對於後面的文件) – 2010-11-08 18:43:36

+0

非常正確,但是由於幀頭,這不應該影響音頻。 – 2010-11-08 19:18:31

+0

蒸?還是你的意思是Streaming? – Svish 2010-11-11 16:55:01

1

每個MP3文件在包含歌曲元數據的文件開頭都有一個標題。至少你必須刪除第二個文件。

這是以前的堆棧溢出問題,How do I merge/join MP3 files with C#?

這是另一個鏈接到Read MP3 Tag Information (ID3v1 and ID3v2),它可能會幫助您刪除它。

+0

以下,我該如何切斷它? – Markus 2009-09-21 17:56:09

+1

也許只是跳過那些許多字節將有所幫助。你可以在這裏http://www.mp3-tech.org/programmer/frame_header找到更多關於MP3文件格式的信息。html – TheVillageIdiot 2009-09-21 18:30:23

1

這個問題已經被問herehere。另請參見reading MP3 Headers in C#,但不是讀取標題,而是僅刪除標題,連接其餘標題,然後爲連接文件生成新標題。

編輯:進一步閱讀後,顯然它沒有任何區別,如果你只是連接文件而不剝離ID3標籤。但它似乎是一個好主意,首先將其排除。

+0

我找不到任何東西可以幫助我。我怎樣才能切斷標題? – Markus 2009-09-21 18:17:29

+0

找出它在哪裏結束,並開始複製那裏 – 2009-09-21 23:29:11

1

這裏是如何使用NAudio串連MP3文件:

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 2015-01-26 13:26:10

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 2015-01-26 13:28:51

+1

爲什麼你會創建一個列表只是爲了迭代設置?只需使用foreach關鍵字即可。 – 2016-08-25 21:30:00

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");