如何确定 C# 中 .wav 文件的长度(即持续时间)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/82319/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:20:18  来源:igfitidea点击:

How can I determine the length (i.e. duration) of a .wav file in C#?

提问by John Sibly

In the uncompressed situation I know I need to read the wav header, pull out the number of channels, bits, and sample rate and work it out from there: (channels) * (bits) * (samples/s) * (seconds) = (filesize)

在未压缩的情况下,我知道我需要读取 wav 标头,提取通道数、位数和采样率并从那里计算出来:(通道)*(位)*(样本/秒)*(秒) =(文件大小)

Is there a simpler way - a free library, or something in the .net framework perhaps?

有没有更简单的方法 - 一个免费的库,或者 .net 框架中的东西?

How would I do this if the .wav file is compressed (with the mpeg codec for example)?

如果 .wav 文件被压缩(例如使用 mpeg 编解码器),我将如何执行此操作?

采纳答案by Jan Zich

You may consider using the mciSendString(...) function (error checking is omitted for clarity):

您可以考虑使用 mciSendString(...) 函数(为清楚起见,省略了错误检查):

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace Sound
{
    public static class SoundInfo
    {
        [DllImport("winmm.dll")]
        private static extern uint mciSendString(
            string command,
            StringBuilder returnValue,
            int returnLength,
            IntPtr winHandle);

        public static int GetSoundLength(string fileName)
        {
            StringBuilder lengthBuf = new StringBuilder(32);

            mciSendString(string.Format("open \"{0}\" type waveaudio alias wave", fileName), null, 0, IntPtr.Zero);
            mciSendString("status wave length", lengthBuf, lengthBuf.Capacity, IntPtr.Zero);
            mciSendString("close wave", null, 0, IntPtr.Zero);

            int length = 0;
            int.TryParse(lengthBuf.ToString(), out length);

            return length;
        }
    }
}

回答by xan

You might find that the XNA libraryhas some support for working with WAV's etc. if you are willing to go down that route. It is designed to work with C# for game programming, so might just take care of what you need.

如果您愿意沿着这条路走下去,您可能会发现XNA 库对使用 WAV 等提供了一些支持。它旨在与 C# 一起用于游戏编程,因此可能会满足您的需求。

回答by moobaa

There's a bit of a tutorial (with - presumably - working code you can leverage) over at CodeProject.

CodeProject上有一些教程(可能带有您可以利用的工作代码)。

The only thing you have to be a little careful of is that it's perfectly "normal" for a WAV file to be composed of multiple chunks - so you have to scoot over the entire file to ensure that all chunks are accounted for.

唯一需要注意的是,WAV 文件由多个块组成是完全“正常的” - 因此您必须遍历整个文件以确保所有块都被考虑在内。

回答by moobaa

What exactly is your application doing with compressed WAVs? Compressed WAV files are always tricky - I always try and use an alternative container format in this case such as OGG or WMA files. The XNA libraries tend to be designed to work with specific formats - although it is possible that within XACT you'll find a more generic wav playback method. A possible alternative is to look into the SDL C# port, although I've only ever used it to play uncompressed WAVs - once opened you can query the number of samples to determine the length.

您的应用程序究竟在使用压缩的 WAV 做什么?压缩的 WAV 文件总是很棘手 - 在这种情况下,我总是尝试使用替代容器格式,例如 OGG 或 WMA 文件。XNA 库倾向于设计为使用特定格式 - 尽管在 XACT 中您可能会找到更通用的 wav 播放方法。一种可能的替代方法是查看 SDL C# 端口,尽管我只用它来播放未压缩的 WAV - 一旦打开,您可以查询样本数以确定长度。

回答by sieben

I'm gonna have to say MediaInfo, I have been using it for over a year with a audio/video encoding application I'm working on. It gives all the information for wav files along with almost every other format.

我不得不说MediaInfo,我已经使用它一年多了,我正在开发一个音频/视频编码应用程序。它提供了 wav 文件的所有信息以及几乎所有其他格式。

MediaInfoDllComes with sample C# code on how to get it working.

MediaInfoDll附带有关如何使其工作的示例 C# 代码。

回答by sieben

I'm going to assume that you're somewhat familiar with the structure of a .WAV file : it contains a WAVEFORMATEX header struct, followed by a number of other structs (or "chunks") containing various kinds of information. See Wikipediafor more info on the file format.

我将假设您对 .WAV 文件的结构有些熟悉:它包含一个 WAVEFORMATEX 头结构,然后是一些包含各种信息的其他结构(或“块”)。有关文件格式的更多信息,请参阅维基百科

First, iterate through the .wav file and add up the the unpadded lengths of the "data" chunks (the "data" chunk contains the audio data for the file; usually there is only one of these, but it's possible that there could be more than one). You now have the total size, in bytes, of the audio data.

首先,遍历 .wav 文件并将“数据”块的未填充长度相加(“数据”块包含文件的音频数据;通常只有其中一个,但也有可能超过一个)。您现在拥有音频数据的总大小(以字节为单位)。

Next, get the "average bytes per second" member of the WAVEFORMATEX header struct of the file.

接下来,获取文件的 WAVEFORMATEX 标头结构的“每秒平均字节数”成员。

Finally, divide the total size of the audio data by the average bytes per second - this will give you the duration of the file, in seconds.

最后,将音频数据的总大小除以每秒的平均字节数 - 这将为您提供文件的持续时间,以秒为单位。

This works reasonably well for uncompressed and compressed files.

这对于未压缩和压缩的文件相当有效。

回答by Lars

I had difficulties with the example of the MediaPlayer-class above. It could take some time, before the player has opened the file. In the "real world" you have to register for the MediaOpened-event, after that has fired, the NaturalDuration is valid. In a console-app you just have to wait a few seconds after the open.

我在上面的 MediaPlayer 类示例中遇到了困难。在播放器打开文件之前可能需要一些时间。在“现实世界”中,您必须注册 MediaOpened 事件,在触发之后,NaturalDuration 是有效的。在控制台应用程序中,您只需在打开后等待几秒钟。

using System;
using System.Text;
using System.Windows.Media;
using System.Windows;

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {
      if (args.Length == 0)
        return;
      Console.Write(args[0] + ": ");
      MediaPlayer player = new MediaPlayer();
      Uri path = new Uri(args[0]);
      player.Open(path);
      TimeSpan maxWaitTime = TimeSpan.FromSeconds(10);
      DateTime end = DateTime.Now + maxWaitTime;
      while (DateTime.Now < end)
      {
        System.Threading.Thread.Sleep(100);
        Duration duration = player.NaturalDuration;
        if (duration.HasTimeSpan)
        {
          Console.WriteLine(duration.TimeSpan.ToString());
          break;
        }
      }
      player.Close();
    }
  }
}

回答by Josh Stodola

Not to take anything away from the answer already accepted, but I was able to get the duration of an audio file (several different formats, including AC3, which is what I needed at the time) using the Microsoft.DirectX.AudioVideoPlayBacknamespace. This is part of DirectX 9.0 for Managed Code. Adding a reference to that made my code as simple as this...

不要从已经接受的答案中删除任何内容,但是我能够使用Microsoft.DirectX.AudioVideoPlayBack命名空间获得音频文件的持续时间(几种不同的格式,包括 AC3,这是我当时需要的) 。这是DirectX 9.0 for Managed Code 的一部分。添加对它的引用使我的代码如此简单......

Public Shared Function GetDuration(ByVal Path As String) As Integer
    If File.Exists(Path) Then
        Return CInt(New Audio(Path, False).Duration)
    Else
        Throw New FileNotFoundException("Audio File Not Found: " & Path)
    End If
End Function

And it's pretty fast, too! Here's a reference for the Audioclass.

而且速度也非常快!这是Audio类的参考。

回答by Monti Pal

Download NAudio.dll from the link http://naudio.codeplex.com/

从链接http://naudio.codeplex.com/下载 NAudio.dll

and then use this function

然后使用这个功能

public static TimeSpan GetWavFileDuration(string fileName)       
{     
    WaveFileReader wf = new WaveFileReader(fileName);
    return wf.TotalTime; 
}

you will get the Duration

你会得到持续时间