调试NAudio MP3读取差异?

Posted

技术标签:

【中文标题】调试NAudio MP3读取差异?【英文标题】:Debug NAudio MP3 reading difference? 【发布时间】:2010-05-15 02:20:58 【问题描述】:

我使用 NAudio 读取特定 MP3 的代码得到的结果与其他几个商业应用程序不同。

具体来说:我的基于 NAudio 的代码在“可听音频”(鼓拾音器)开始之前在此 MP3 的开头找到约 1.4 秒的静音,而其他应用程序(Windows Media Player、RealPlayer、WavePad)显示约 2.5 秒在同一个鼓拾音器之前的沉默。

特定的 MP3 是从 Amazon.com 下载的“Like A Rolling Stone”。测试了其他几个 MP3,没有一个显示我的代码和其他应用程序之间有任何类似的差异。大多数 MP3 不会以如此长时间的静音开始,所以我怀疑这就是差异的根源。

调试问题:

    我实际上无法找到一种方法来证明其他应用程序是正确的而 NAudio/me 是错误的,即将我的代码的结果逐块与“已知的良好参考实现”进行比较;因此我什至无法准确定义我需要调试的“错误”。

    由于我的代码在这 1.4 秒内读取了数千个样本而没有明显错误,所以我想不出如何缩小输入流中的位置/时间以查找错误。

    李>

    NAudio 代码的核心是对 acmStreamConvert() 的 P/Invoke 调用,这是一个 Windows“黑盒”调用,我想不出如何进行错误检查。

    李>

谁能想到调试这个的任何技巧/技术?

【问题讨论】:

【参考方案1】:

NAudio ACM 代码最初并非用于 MP3,而是用于解码恒定比特率电话编解码器。有一天,我尝试设置 WaveFormat 以指定 MP3 作为实验,结果听起来足够好。但是,我一直对使用 ACM 解码 MP3(尤其是 VBR)感到有点紧张(例如,如果传入 ID3 标签或专辑封面会发生什么 - 这会导致额外的沉默吗?),而且我从来没有 100%确信 NAudio 做得对 - 关于您应该如何使用 ACM 编解码器的文档很少。遗憾的是,没有可以在 NAudio 中使用的具有许可证的托管 MP3 解码器,因此 ACM 仍然是目前唯一的选择。

我不确定其他媒体播放器采用什么方法播放 MP3,但我怀疑其中许多都有自己的内置 MP3 解码器,而不是依赖于操作系统。

【讨论】:

感谢背景。因此,我不会对 NAudio MP3 解码抱有太多期望,但它仍然让我远远领先于自己从头开始弄清楚它,而且我仍然不知道为低预算的商业应用程序解码 MP3 的更好方法。 【参考方案2】:

我对自己的问题找到了一些部分答案:

    由于我的问题归结为消耗了太多 MP3 而没有产生足够的 PCM,因此我使用了条件命中计数断点来查找发生这种情况的位置,然后深入研究。

    这表明一些 acmStreamConvert() 调用返回成功,消耗 417 个 src 字节,但产生 0 个“使用的目标字节”。

接下来我计划尝试 acmStreamSize() 来询问编解码器它“想要”消耗多少 src 字节,而不是“告诉”它消耗 417。

编辑(跟进):我修好了!

它归结为传递 acmStreamConvert() 足够的 src 字节以使其快乐。给它 acmStreamSize() 请求的大小解决了某些地方的问题,但随后又出现在其他地方;将其请求的大小乘以 3 似乎可以解决我测试过的所有 MP3 中“使用的 0 个目标字节”的结果。

通过此修复,acmStreamConvert() 有时会返回更大的转换块(大约 32 KB),因此我还必须修改其他一些 NAudio 代码以传递更大的目标缓冲区来保存结果。

【讨论】:

acmStreamSize 非常适合 CBR,但无法为 VBR 提供有意义的答案。此外,并非 MP3 文件中的所有内容都是压缩音频。还有其他东西,如 ID3 标签等。我尝试删除它们,但总是有一些非音频内容被传递到 ACM 编解码器的机会。我还没有看到任何关于你应该如何解析 MP3 文件以计算出应该将哪些位发送到 ACM 编解码器的官方文档。

以上是关于调试NAudio MP3读取差异?的主要内容,如果未能解决你的问题,请参考以下文章

NAudio 的错误,在 MemoryStream,VB 中播放 mp3

NAudio在改变音高而不是文件时寻找一种从流中读取的方法

如何使用 C# NAudio 操作字节?

使用 NAudio 修剪 mp3 文件

Unity中使用NAudio创建AudioClip,读取数据时卡顿1-2秒

mp3 到样本数组 NAudio