如何确定C#中.wav文件的长度?

时间:2020-03-05 18:58:38  来源:igfitidea点击:

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

有没有更简单的方法免费提供库,或者是.net框架中的某些内容?

如果.wav文件被压缩(例如,使用mpeg编解码器),我该怎么办?

解决方案

回答

如果我们愿意走XNA库,可能会发现XNA库对使用WAV等提供了一些支持。它旨在与Cfor游戏编程一起使用,因此可能只是照顾我们所需的内容。

回答

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

我们唯一需要注意的一点是,由多个块组成的WAV文件完全"正常",因此我们必须遍历整个文件以确保考虑到所有块。

回答

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

回答

在.net框架中,有一个mediaplayer类:

http://msdn.microsoft.com/zh-CN/library/system.windows.media.mediaplayer_members.aspx

这是一个例子:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2667714&SiteID=1&pageid=0#2685871

回答

我们可以考虑使用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;
        }
    }
}

回答

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

MediaInfoDll随附有关如何使其工作的示例Ccode。

回答

我假设我们对.WAV文件的结构有点熟悉:它包含WAVEFORMATEX标头结构,然后是包含各种信息的许多其他结构(或者"块")。有关文件格式的更多信息,请参见Wikipedia。

首先,循环访问.wav文件,并添加"数据"块的未填充长度("数据"块包含该文件的音频数据;通常只有其中一个,但有可能存在超过一个)。现在,我们具有音频数据的总大小(以字节为单位)。

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

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

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

回答

我在上面的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();
    }
  }
}

回答

不用从已经接受的答案中脱颖而出,但是我能够使用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

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

回答

从以下位置下载" PresentationCore.dll"和" WindowsBase.dll":

http://www.search-dll.com/dll-files/download/windowsbase.dll.html

将文件粘贴到应用程序bin文件夹中以供参考。现在应该可以工作了。