如何在不使用NAudio和.NET重新编码的情况下检测静音并剪切mp3文件

时间:2014-01-16 09:04:25

标签: naudio

我一直在寻找答案,我只能找到一些零碎的东西。我想要做的是加载多个mp3文件(暂时合并它们),然后使用静音检测将它们分割成碎片。

我的理解是我可以使用Mp3FileReader,但问题是: 1.如何从mp3文件中读出20秒的音频?我是否需要阅读20次阅读器.WaveFormat.AverageBytesPerSecond?或者可能继续阅读框架,直到Mp3Frame.SampleCount / Mp3Frame.SampleRate的总和超过20秒? 2.我如何真正发现沉默?我会查看相应数量的连续样本,以检查它们是否都低于某个阈值。但是我如何访问样本,无论它们是8位还是16位,单声道还是立体声等?我可以直接解码MP3帧吗? 3.在示例10465处检测到静音后,如何将其映射回mp3帧索引以执行切割而不重新编码?

3 个答案:

答案 0 :(得分:3)

以下是我推荐的方法(涉及重新编码)

  1. 使用AudioFileReader直接在Read方法
  2. 中将MP3作为浮点样本
  3. 找到一个开源噪声门算法,将其移植到C#,并使用它来检测静音(即当噪声门关闭时,你有静音。你想要调整阈值和攻击/释放时间)< / LI>
  4. 创建一个使用噪音门的派生ISampleProvider,并在其Read方法中,不会返回静默的样本
  5. 或者:将输出传递给WaveFileWriter以创建WAV文件,并将WAV文件编码为MP3  或者:使用NAudio.Lame直接编码而无需WAV步骤。您可能需要首先从SampleProvider返回到16位WAV提供程序

答案 1 :(得分:2)

MP3是一种压缩音频格式。你不能只删除比特并期望其余部分仍然是有效的MP3文件。实际上,由于它是基于DCT的变换,所以比特位于频域而不是时域。样本10465根本没有比特。其中包含样本10465的帧,并且存在描述该帧中所有频率的一组比特。

在样本10465处切换音频并继续使用一些随机的其他样本可能会导致不连续,这意味着所产生的帧中出现的频率数量会急剧增加。所以这绝对意味着一个完整的重新编码。更好的方法是平滑过渡,但这不是一个微不足道的操作。结果当然与输入略有不同,所以它仍然意味着重新编码。

  1. 我不明白你为什么要阅读20秒的音频。该号码来自何处?你通常想读一切。

  2. 声音是一波;完全可以预期它会过零。所以接近于零并不是特别的。对于20 Hz波(听觉阈值),零交叉每秒发生40次,但每次你有多个样本接近零。因此,您基本上需要多个样本,这些样本都接近于零,但两侧都是如此。 5 6 7对于16位声音来说并不是很多,但它很可能是一个最大值为10000的波的一部分。你真的应该检查至少0.05秒来捕捉那些20赫兹的声音。

  3. 由于您在50毫秒的时间间隔内检测到静音,因此您有一个&#34;位置&#34;大约有几百个样本宽。幸运的是,那里有一个框架边界。切到那里。是的,还有重新编码的时间。

答案 2 :(得分:2)

在阅读之前: Mark的回答更容易实现,您几乎肯定会对结果感到满意。这个答案适合那些愿意花费大量时间的人。

所以说,基于静音切割MP3文件而不重新编码或完全解码实际上是可行的...基本上,你可以看看每个帧的侧面信息和每个粒子的增益和放大器。霍夫曼数据“估计”沉默。

  • 找到沉默
  • 将沉默之前的所有帧复制到新文件

现在它变得棘手......

  • 在静音后从帧中拉出音频数据,跟踪哪个帧头与哪些音频数据一致。
  • 开始编写第二个新文件,但在写出帧时,更新main_data_begin字段,使位库与音频数据真正同步。