Come posso determinare la lunghezza di un file .wav in C #?

Nella situazione non compressa so che ho bisogno di leggere l’intestazione wav, estrarre il numero di canali, bit e frequenza di campionamento e lavorarci fuori da lì: (canali) * (bit) * (campioni / s) * (secondi) = (file)

C’è un modo più semplice – una libreria libera, o qualcosa del framework .net, forse?

Come farei questo se il file .wav è compresso (con il codec mpeg per esempio)?

Puoi prendere in considerazione l’utilizzo della funzione mciSendString (…) (il controllo degli errori è omesso per chiarezza):

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; } } } 

Scarica NAudio.dll dal link http://naudio.codeplex.com/

e quindi utilizzare questa funzione

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

otterrai la Durata

Non togliere nulla dalla risposta già accettata, ma sono stato in grado di ottenere la durata di un file audio (diversi formati, incluso AC3, che è ciò di cui avevo bisogno in quel momento) utilizzando lo spazio dei nomi Microsoft.DirectX.AudioVideoPlayBack . Questo fa parte di DirectX 9.0 per il codice gestito . Aggiungere un riferimento a questo ha reso il mio codice semplice come questo …

 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 

Ed è anche abbastanza veloce! Ecco un riferimento per la class Audio .

Ho avuto difficoltà con l’esempio della class MediaPlayer sopra. Potrebbe volerci del tempo, prima che il giocatore abbia aperto il file. Nel “mondo reale” devi registrarti per l’evento MediaOpened, dopo che è stato triggersto, la NaturalDuration è valida. In una console-app devi solo aspettare qualche secondo dopo l’apertura.

 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(); } } } 

Prova il codice qui sotto da Come determinare la lunghezza di un file .wav in C #

  string path = @"c:\test.wav"; WaveReader wr = new WaveReader(File.OpenRead(path)); int durationInMS = wr.GetDurationInMS(); wr.Close(); 

Sì, esiste una libreria gratuita che può essere utilizzata per ottenere la durata del file audio. Questa libreria offre anche molte altre funzionalità.

TagLib

TagLib è distribuito sotto GNU Lesser General Public License (LGPL) e Mozilla Public License (MPL).

Ho implementato sotto il codice che restituisce la durata in secondi.

 using TagLib.Mpeg; public static double GetSoundLength(string FilePath) { AudioFile ObjAF = new AudioFile(FilePath); return ObjAF.Properties.Duration.TotalSeconds; } 

Potresti scoprire che la libreria XNA ha qualche supporto per lavorare con WAV ecc. Se sei disposto a seguire questa strada. È progettato per funzionare con C # per la programmazione di giochi, quindi potrebbe semplicemente occuparsi di ciò di cui hai bisogno.

C’è un po ‘di tutorial (con – presumibilmente – codice funzionante che puoi sfruttare) su CodeProject .

L’unica cosa che devi fare attenzione è che è perfettamente “normale” che un file WAV sia composto da più blocchi, quindi devi eseguire lo scoot sull’intero file per assicurarti che tutti i pezzi siano stati presi in considerazione.

Che cosa fa esattamente la tua applicazione con WAV compressi? I file WAV compressi sono sempre difficili: cerco sempre di utilizzare un formato contenitore alternativo in questo caso, ad esempio i file OGG o WMA. Le librerie XNA tendono ad essere progettate per funzionare con formati specifici, sebbene sia ansible che all’interno di XACT trovi un metodo di riproduzione wav più generico. Una ansible alternativa è quella di guardare nella porta SDL C #, sebbene l’abbia mai usata solo per riprodurre file WAV non compressi. Una volta aperto, puoi interrogare il numero di campioni per determinare la lunghezza.

Devo dire MediaInfo , lo uso da più di un anno con un’applicazione di codifica audio / video su cui sto lavorando. Fornisce tutte le informazioni per i file wav insieme a quasi ogni altro formato.

MediaInfoDll Viene fornito con codice C # di esempio su come farlo funzionare.

Presumo che tu abbia una certa familiarità con la struttura di un file .WAV: contiene una struttura di intestazione WAVEFORMATEX, seguita da un numero di altre strutture (o “blocchi”) contenenti vari tipi di informazioni. Vedi Wikipedia per maggiori informazioni sul formato del file.

In primo luogo, scorrere il file .wav e sumre le lunghezze non riempite dei blocchi “dati” (il blocco “dati” contiene i dati audio per il file, di solito c’è solo uno di questi, ma è ansible che ci possa essere più di una). Ora hai la dimensione totale, in byte, dei dati audio.

Quindi, ottenere il membro “byte medi al secondo” della struttura di intestazione WAVEFORMATEX del file.

Infine, dividi la dimensione totale dei dati audio in base ai byte medi al secondo – questo ti darà la durata del file, in secondi.

Funziona abbastanza bene per i file non compressi e compressi.

 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 (ie Linear quantization) ' Word 22 Channels Mono = 1, Stereo = 2 ' Dword 24 Sample Rate per second eg 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 eg 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 

Scaricare “PresentationCore.dll” e “WindowsBase.dll” da:

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

Incolla i file nella cartella bin dell’applicazione per riferimento. Dovrebbe funzionare ora.