在未压缩的情况下,我知道我需要读取wav标头,提取通道数,位数和采样率并从那里开始计算: (频道)*(位)*(样本/秒)*(秒)=(文件大小)
是否有一种更简单的方法 - 一个免费的库,或者.net框架中的某些东西?
如果压缩.wav文件(例如使用mpeg编解码器),我该怎么做?
答案 0 :(得分:29)
下载NAudio.dll 从链接 http://naudio.codeplex.com/
然后使用此功能
public static TimeSpan GetWavFileDuration(string fileName)
{
WaveFileReader wf = new WaveFileReader(fileName);
return wf.TotalTime;
}
您将获得持续时间
答案 1 :(得分:19)
您可以考虑使用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;
}
}
}
答案 2 :(得分:5)
不要接受已经接受的答案,但我能够使用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类的参考。
答案 3 :(得分:3)
在.net框架中有一个媒体播放器类:
http://msdn.microsoft.com/en-us/library/system.windows.media.mediaplayer_members.aspx
以下是一个例子:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2667714&SiteID=1&pageid=0#2685871
答案 4 :(得分:2)
我在上面的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();
}
}
}
答案 5 :(得分:2)
从How to determine the length of a .wav file in C#
尝试以下代码 string path = @"c:\test.wav";
WaveReader wr = new WaveReader(File.OpenRead(path));
int durationInMS = wr.GetDurationInMS();
wr.Close();
答案 6 :(得分:2)
是的,有一个免费的库可用于获取音频文件的持续时间。该库还提供了更多功能。
TagLib根据GNU宽通用公共许可证(LGPL)和Mozilla公共许可证(MPL)分发。
我在下面的代码中实现了以秒为单位返回持续时间。
using TagLib.Mpeg;
public static double GetSoundLength(string FilePath)
{
AudioFile ObjAF = new AudioFile(FilePath);
return ObjAF.Properties.Duration.TotalSeconds;
}
答案 7 :(得分:1)
如果您愿意沿着这条路走下去,您可能会发现XNA library对使用WAV等有一些支持。它旨在与C#一起用于游戏编程,因此可能只需要处理您需要的内容。
答案 8 :(得分:1)
在CodeProject处有一些教程(可能是 - 你可以利用的工作代码)。
唯一需要注意的是,WAV文件由多个块组成是完全“正常”的 - 所以你必须对整个文件进行扫描以确保所有块都被考虑在内。
答案 9 :(得分:1)
您的应用程序究竟对压缩WAV有何作用?压缩的WAV文件总是很棘手 - 在这种情况下我总是尝试使用替代容器格式,例如OGG或WMA文件。 XNA库倾向于设计为使用特定格式 - 尽管在XACT中你可能会找到更通用的wav播放方法。一个可能的替代方案是查看SDL C#端口,虽然我只使用它来播放未压缩的WAV - 一旦打开,您可以查询样本数以确定长度。
答案 10 :(得分:1)
我将不得不说MediaInfo,我已经使用它超过一年的音频/视频编码应用程序我正在努力。它提供了wav文件的所有信息以及几乎所有其他格式。
MediaInfoDll附带有关如何使其正常工作的示例C#代码。
答案 11 :(得分:0)
我将假设您对.WAV文件的结构有些熟悉:它包含WAVEFORMATEX标头结构,后跟包含各种信息的许多其他结构(或“块”)。有关文件格式的详细信息,请参阅Wikipedia。
首先,遍历.wav文件并添加“数据”块的未填充长度(“数据”块包含文件的音频数据;通常只有其中一个,但有可能可能不止一个)。您现在拥有音频数据的总大小(以字节为单位)。
接下来,获取文件的WAVEFORMATEX头结构的“每秒平均字节数”成员。
最后,将音频数据的总大小除以每秒的平均字节数 - 这将为您提供文件的持续时间(以秒为单位)。
这对未压缩和压缩的文件非常有效。
答案 12 :(得分:0)
时间= FileLength /(采样率*通道*每个采样的位数/ 8)
答案 13 :(得分:0)
我已经测试了自爆代码会失败,文件格式如“ \\ ip \ dir \ *。wav'
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;
}
}
naudio工作时
public static int GetSoundLength(string fileName)
{
using (WaveFileReader wf = new WaveFileReader(fileName))
{
return (int)wf.TotalTime.TotalMilliseconds;
}
}`
答案 14 :(得分:-1)
Imports System.IO
Imports System.Text
Imports System.Math
Imports System.BitConverter
Public Class PulseCodeModulation
' Pulse Code Modulation WAV (RIFF) file layout
' Header chunk
' Type Byte Offset Description
' Dword 0 Always ASCII "RIFF"
' Dword 4 Number of bytes in the file after this value (= File Size - 8)
' Dword 8 Always ASCII "WAVE"
' Format Chunk
' Type Byte Offset Description
' Dword 12 Always ASCII "fmt "
' Dword 16 Number of bytes in this chunk after this value
' Word 20 Data format PCM = 1 (i.e. Linear quantization)
' Word 22 Channels Mono = 1, Stereo = 2
' Dword 24 Sample Rate per second e.g. 8000, 44100
' Dword 28 Byte Rate per second (= Sample Rate * Channels * (Bits Per Sample / 8))
' Word 32 Block Align (= Channels * (Bits Per Sample / 8))
' Word 34 Bits Per Sample e.g. 8, 16
' Data Chunk
' Type Byte Offset Description
' Dword 36 Always ASCII "data"
' Dword 40 The number of bytes of sound data (Samples * Channels * (Bits Per Sample / 8))
' Buffer 44 The sound data
Dim HeaderData(43) As Byte
Private AudioFileReference As String
Public Sub New(ByVal AudioFileReference As String)
Try
Me.HeaderData = Read(AudioFileReference, 0, Me.HeaderData.Length)
Catch Exception As Exception
Throw
End Try
'Validate file format
Dim Encoder As New UTF8Encoding()
If "RIFF" <> Encoder.GetString(BlockCopy(Me.HeaderData, 0, 4)) Or _
"WAVE" <> Encoder.GetString(BlockCopy(Me.HeaderData, 8, 4)) Or _
"fmt " <> Encoder.GetString(BlockCopy(Me.HeaderData, 12, 4)) Or _
"data" <> Encoder.GetString(BlockCopy(Me.HeaderData, 36, 4)) Or _
16 <> ToUInt32(BlockCopy(Me.HeaderData, 16, 4), 0) Or _
1 <> ToUInt16(BlockCopy(Me.HeaderData, 20, 2), 0) _
Then
Throw New InvalidDataException("Invalid PCM WAV file")
End If
Me.AudioFileReference = AudioFileReference
End Sub
ReadOnly Property Channels() As Integer
Get
Return ToUInt16(BlockCopy(Me.HeaderData, 22, 2), 0) 'mono = 1, stereo = 2
End Get
End Property
ReadOnly Property SampleRate() As Integer
Get
Return ToUInt32(BlockCopy(Me.HeaderData, 24, 4), 0) 'per second
End Get
End Property
ReadOnly Property ByteRate() As Integer
Get
Return ToUInt32(BlockCopy(Me.HeaderData, 28, 4), 0) 'sample rate * channels * (bits per channel / 8)
End Get
End Property
ReadOnly Property BlockAlign() As Integer
Get
Return ToUInt16(BlockCopy(Me.HeaderData, 32, 2), 0) 'channels * (bits per sample / 8)
End Get
End Property
ReadOnly Property BitsPerSample() As Integer
Get
Return ToUInt16(BlockCopy(Me.HeaderData, 34, 2), 0)
End Get
End Property
ReadOnly Property Duration() As Integer
Get
Dim Size As Double = ToUInt32(BlockCopy(Me.HeaderData, 40, 4), 0)
Dim ByteRate As Double = ToUInt32(BlockCopy(Me.HeaderData, 28, 4), 0)
Return Ceiling(Size / ByteRate)
End Get
End Property
Public Sub Play()
Try
My.Computer.Audio.Play(Me.AudioFileReference, AudioPlayMode.Background)
Catch Exception As Exception
Throw
End Try
End Sub
Public Sub Play(playMode As AudioPlayMode)
Try
My.Computer.Audio.Play(Me.AudioFileReference, playMode)
Catch Exception As Exception
Throw
End Try
End Sub
Private Function Read(AudioFileReference As String, ByVal Offset As Long, ByVal Bytes As Long) As Byte()
Dim inputFile As System.IO.FileStream
Try
inputFile = IO.File.Open(AudioFileReference, IO.FileMode.Open)
Catch Exception As FileNotFoundException
Throw New FileNotFoundException("PCM WAV file not found")
Catch Exception As Exception
Throw
End Try
Dim BytesRead As Long
Dim Buffer(Bytes - 1) As Byte
Try
BytesRead = inputFile.Read(Buffer, Offset, Bytes)
Catch Exception As Exception
Throw
Finally
Try
inputFile.Close()
Catch Exception As Exception
'Eat the second exception so as to not mask the previous exception
End Try
End Try
If BytesRead < Bytes Then
Throw New InvalidDataException("PCM WAV file read failed")
End If
Return Buffer
End Function
Private Function BlockCopy(ByRef Source As Byte(), ByVal Offset As Long, ByVal Bytes As Long) As Byte()
Dim Destination(Bytes - 1) As Byte
Try
Buffer.BlockCopy(Source, Offset, Destination, 0, Bytes)
Catch Exception As Exception
Throw
End Try
Return Destination
End Function
End Class
答案 15 :(得分:-8)
从以下网址下载“PresentationCore.dll”和“WindowsBase.dll”:
http://www.search-dll.com/dll-files/download/windowsbase.dll.html
将文件粘贴到应用程序bin文件夹中以供参考。它现在应该工作。