如何确定C#中.wav文件的长度?
在未压缩的情况下,我知道我需要读取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文件夹中以供参考。现在应该可以工作了。