Come è possibile determinare la lunghezza (es.la durata) di un .file wav in C#?
-
01-07-2019 - |
Domanda
In non compresso situazione so che ho bisogno di leggere l'intestazione wav, tirare fuori il numero di canali, bit e frequenza di campionamento e di lavoro fuori da lì:(canali) * (bit) * (campioni/s) * (secondi) = (dimensione file)
C'è un modo più semplice - una libreria, o in qualcosa .net framework, forse?
Come posso fare questo se l' .wav file è compresso con il codec mpeg per esempio)?
Soluzione
Si può prendere in considerazione le mciSendString(...) la funzione (di controllo di errore è omessi 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;
}
}
}
Altri suggerimenti
Download NAudio.dll dal link http://naudio.codeplex.com/
e poi usare questa funzione
public static TimeSpan GetWavFileDuration(string fileName)
{
WaveFileReader wf = new WaveFileReader(fileName);
return wf.TotalTime;
}
si ottiene la Durata
Non per togliere nulla la risposta già accettato, ma sono stato in grado di ottenere la durata di un file audio in diversi formati, tra cui AC3, che è quello che mi serviva al momento) utilizzando il Microsoft.DirectX.AudioVideoPlayBack
spazio dei nomi.Questo è parte del DirectX 9.0 per il Codice Gestito.L'aggiunta di un riferimento al fatto che il mio codice di 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 è abbastanza veloce, troppo!Ecco un riferimento per il Audio classe.
Nell' .net framework c'è una classe mediaplayer:
http://msdn.microsoft.com/en-us/library/system.windows.media.mediaplayer_members.aspx
Ecco un esempio:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2667714&SiteID=1&pageid=0#2685871
Ho avuto difficoltà con l'esempio del MediaPlayer-classe di cui sopra.Si potrebbe richiedere un certo tempo, prima che il giocatore ha aperto il file.Nel "mondo reale", è necessario registrarsi per il MediaOpened-evento, dopo che ha sparato il NaturalDuration è valido.In una console-app devi solo aspettare un paio di secondi 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();
}
}
}
Tenta di codice riportato di seguito da Come determinare la lunghezza di una .file wav in C#
string path = @"c:\test.wav";
WaveReader wr = new WaveReader(File.OpenRead(path));
int durationInMS = wr.GetDurationInMS();
wr.Close();
Sì, C'è una libreria che può essere utilizzato per ottenere il tempo di durata del file Audio.Questa libreria offre molte più funzionalità.
TagLib è distribuito sotto la GNU Lesser General Public License (LGPL) e la Mozilla Public License (MPL).
Ho implementato sotto il codice che restituisce il tempo di durata in secondi.
using TagLib.Mpeg;
public static double GetSoundLength(string FilePath)
{
AudioFile ObjAF = new AudioFile(FilePath);
return ObjAF.Properties.Duration.TotalSeconds;
}
Si potrebbe scoprire che il XNA biblioteca ha qualche supporto per lavorare con il WAV etc.se siete disposti ad andare a nanna.Esso è progettato per lavorare con C# per la programmazione di videogiochi, quindi potrebbe solo prendere cura di tutto ciò di cui hai bisogno.
C'è un po ' di tutorial (con - presumibilmente - codice di lavoro è possibile sfruttare) oltre a CodeProject.
L'unica cosa che devi essere un po ' attenti è che è perfettamente "normale" per un file WAV per essere composto di vari pezzi in modo da dovete scoot su tutto il file per assicurarsi che tutti i pezzi sono contabilizzate.
Che cosa è esattamente la propria applicazione facendo con compresso Wav?Compressi i file WAV sono sempre difficili - e cerco sempre di utilizzare un contenitore alternativo formato, in questo caso, come OGG o WMA.XNA librerie tendono ad essere progettato per lavorare con formati specifici - anche se è possibile che all'interno di un ANIMALE troverete un più generico wav metodo di riproduzione.Una possibile alternativa è cercare di SDL C# porta, anche se ho sempre e solo usato per giocare non compresso Wav - una volta aperto si può interrogare il numero di campioni per determinare la lunghezza.
Devo dire MediaInfo, Ho utilizzato per più di un anno con un encoding audio/video applicazione su cui sto lavorando.Esso fornisce tutte le informazioni per i file wav con quasi ogni altro formato.
MediaInfoDll Viene fornito con un esempio di codice C# su come farlo funzionare.
Ho intenzione di assumere che siete un po ' di familiarità con la struttura di un .File WAV :esso contiene un WAVEFORMATEX intestazione struct, seguita da un certo numero di altre strutture (o "pezzi"), contenente informazioni di vario tipo.Vedere Wikipedia per ulteriori informazioni sul formato di file.
Primo, scorrere l' .file wav e aggiungete il unpadded lunghezze dei "dati" pezzi " (i "dati" pezzo contiene i dati audio per il file;di solito c'è solo uno di questi, ma è possibile che ci potrebbero essere più di uno).Si dispone ora di totale la dimensione, in byte, di dati audio.
Avanti, ottenere il "media byte al secondo membro della WAVEFORMATEX intestazione struttura del file.
Infine, dividere la dimensione totale dei dati audio dalla media di byte al secondo - questo vi darà la durata del file, in pochi secondi.
Questo funziona abbastanza bene per non compressi e compressi.
tempo = FileLength / (Frequenza di Campionamento * Canali * Bit per campione /8)
ho testato soffiò il codice verrebbe a mancare,formati di file come "\\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;
}
}
mentre naudio opere
public static int GetSoundLength(string fileName)
{
using (WaveFileReader wf = new WaveFileReader(fileName))
{
return (int)wf.TotalTime.TotalMilliseconds;
}
}`
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
Scaricare "PresentationCore.dll" e "WindowsBase.dll" da:
http://www.search-dll.com/dll-files/download/windowsbase.dll.html
Incollare il file in applicazione della cartella bin di riferimento.Ora dovrebbe funzionare.