2009-09-21 62 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");