从 MemoryStream 打开音频 (wav) 文件以确定持续时间

发布于 2024-09-14 08:23:33 字数 569 浏览 8 评论 0原文

Is there a way, either within the Framework or by using P/Invoke to determine the duration of a wav file that's held in a MemoryStream?

I've already had a look at Managed DirectX and another similar question, but everything seems to work with paths, rather than providing any way to pass in a stream. One of the links in the question I've referenced (A simple C# Wave editor....) makes it fairly clear that I could parse the MemoryStream to determine the duration of the wav file. Ideally I'd like to not re-invent the wheel.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风尘浪孓 2024-09-21 08:23:33

我同意亚历克斯的观点。
我花时间编写了一个包含三行代码的小程序,用于打印 wav 文件的持续时间。

        var stream=new MemoryStream(File.ReadAllBytes("test.wav"));
        var wave = new WaveFileReader(stream);
        Console.WriteLine(wave.TotalTime); // wave.TotalTime -> TimeSpan

下载 NAudio 库:您将在包中找到 NAudio.dll。

只需在您的项目中引用 NAudio.dll 即可。

在撰写本文时,它的版本是 1.3。

正如作者在博客中所说,WaveFileReader 也接受 Stream ;不仅仅是文件路径。

请记住,1.3 版本是为 x86 构建的。如果您希望它在 x64 上运行,您需要强制您的项目使用 x86。
如果您想要 x64 的 NAudio.dll(像我一样),您需要使用“任何 cpu”重新编译。
对我来说,这两种解决方案都很有效。

I agree with Alex.
I took the time to put together a small program with three lines of code that prints the duration of a wav file.

        var stream=new MemoryStream(File.ReadAllBytes("test.wav"));
        var wave = new WaveFileReader(stream);
        Console.WriteLine(wave.TotalTime); // wave.TotalTime -> TimeSpan

Download NAudio library: you will find NAudio.dll in the package.

Just reference NAudio.dll in your project.

At time of writing it's release 1.3.

Like the author says on his blog, WaveFileReader accept a Stream too; not just a file path.

Remember that version 1.3 is built for x86. If you want it to work on x64 you need to force your project to x86.
If you want NAudio.dll for x64 (like me) you need to recompile with 'any cpu'.
For me both solutions worked like a charm.

海风掠过北极光 2024-09-21 08:23:33

尝试以下计算

streamSize == headerSizeIfAny + playTime *抽样*singleSampleSize - >

playTime = (streamSize[以字节为单位] - headerSizeIfAny) / (采样[每秒采样数] * singleSampleSize[字节])

Try following calculation

streamSize == headerSizeIfAny + playTime * sampling * singleSampleSize ->

playTime = ( streamSize[in bytes] - headerSizeIfAny ) / ( sampling [samples per second] * singleSampleSize[bytes])

自在安然 2024-09-21 08:23:33

看看这个:

http://www.sonicspot.com/guide/wavefiles.html

所以

typedef struct {
  WORD wFormatTag; 
  WORD nChannels; 
  DWORD nSamplesPerSec; 
  DWORD nAvgBytesPerSec; 
  WORD nBlockAlign; 
  WORD wBitsPerSample; 
  WORD cbSize;} WAVEFORMATEX; 

你有你的内存流... 寻找 0x10 (跳过 Riff 头) + 0x08 (用于格式头) = 24

你就在上面的结构中。

使用stream.ReadInt16()stream.ReadInt32()读取想要的结构成员。

然后,查找 54,读取一个 DWORD,这些字节就是您的示例数据。

然后根据这些变量计算出您的持续时间。

注意:这仅适用于存储在内存流中的最简单的 PCM 波形文件。对于其他人,您必须尊重标头并正确解析它们,找到数据块并根据其大小计算持续时间。

Check this out:

http://www.sonicspot.com/guide/wavefiles.html

and this

typedef struct {
  WORD wFormatTag; 
  WORD nChannels; 
  DWORD nSamplesPerSec; 
  DWORD nAvgBytesPerSec; 
  WORD nBlockAlign; 
  WORD wBitsPerSample; 
  WORD cbSize;} WAVEFORMATEX; 

So you have your memorystream... Seek to 0x10 (to skip Riff header) + 0x08 (for format header) = 24

And you are in the structure above.

Use stream.ReadInt16() and stream.ReadInt32() to read wanted structure members.

Then, seek to 54, read one DWORD, and that many bytes is your sample data.

Then figure out your duration from this variables.

NOTE: that will work for ONLY THE SIMPLEST PCM wave files stored in your memorystream. For others, you'll have to honor headers and properly parse them, finding the data chunk and calculating duration according to it's size.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文