¿Cómo puedo determinar la longitud (es decir,la duración) de la una .archivo wav en C#?

StackOverflow https://stackoverflow.com/questions/82319

  •  01-07-2019
  •  | 
  •  

Pregunta

En el sin comprimir situación sé que tengo que leer el wav encabezado, sacar el número de canales de bits y frecuencia de muestreo y el trabajo que desde allí:(canales) * (bits) * (muestras/s) * (segundos) = (tamaño de archivo)

Hay una forma más simple - una biblioteca libre, o algo en el .net framework, tal vez?

¿Cómo puedo hacer esto si el .wav archivo está comprimido (con el códec mpeg por ejemplo)?

¿Fue útil?

Solución

Usted puede considerar el uso de la mciSendString(...) la función (comprobación de error se ha omitido para mayor claridad):

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

Otros consejos

Descargar NAudio.dll desde el enlace http://naudio.codeplex.com/

y, a continuación, utilizar esta función

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

obtendrá la Duración

No tomar nada que lejos de que la respuesta ya está aceptado, pero yo era capaz de obtener la duración de un archivo de audio (varios formatos diferentes, incluyendo AC3, que es lo que yo necesitaba en ese momento) el uso de la Microsoft.DirectX.AudioVideoPlayBack espacio de nombres.Esto es parte de DirectX 9.0 para el Código Administrado.La adición de una referencia que hizo que mi código es tan simple como esto...

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

Y es bastante rápido, demasiado!Aquí una referencia para el Audio clase.

He tenido dificultades con el ejemplo de la MediaPlayer-clase anterior.Podría tomar algún tiempo, antes de que el jugador haya abierto el archivo.En el "mundo real" debe registrarse en el MediaOpened-evento, después de que se ha disparado, el NaturalDuration es válido.En la consola de la aplicación sólo tienes que esperar un par de segundos después de la 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();
    }
  }
}

Pruebe el código de abajo Cómo determinar la longitud de una .archivo wav en C#

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

Sí, Hay una biblioteca libre que puede ser utilizado para obtener el tiempo de duración del archivo de Audio.Esta biblioteca también ofrece muchas más funcionalidades.

TagLib

TagLib se distribuye bajo la GNU Lesser General Public License (LGPL) y la Licencia Pública de Mozilla (MPL).

He implementado a continuación el código que devuelve el tiempo de duración en segundos.

using TagLib.Mpeg;

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

Usted puede encontrar que el XNA biblioteca tiene algún tipo de soporte para trabajar con archivos WAV, etc.si usted está dispuesto a ir por ese camino.Está diseñado para trabajar con C# para la programación de juegos, por lo que sólo podría tener cuidado de lo que usted necesita.

Hay un poco de un tutorial (con - presumiblemente - código de trabajo puede aprovechar) en CodeProject.

La única cosa que usted tiene que ser un poco cuidadoso de es que es perfectamente "normal" para un archivo WAV a estar compuesto de varios trozos - así que usted tiene para meterse en el archivo completo para asegurarse de que todos los trozos se contabilizan.

¿Cuál es exactamente su aplicación haciendo comprimido Wav?Comprime los archivos WAV son siempre complicado, yo siempre tratamos de utilizar una alternativa de formato contenedor, en este caso, como OGG o WMA.El XNA las bibliotecas tienden a ser diseñados para trabajar con formatos específicos - aunque es posible que dentro de XACT usted encontrará una más genérica wav método de reproducción.Una posible alternativa es buscar en el SDL C# puerto, aunque sólo la he usado para jugar sin comprimir Wav - una vez abierto puede consultar el número de muestras para determinar la longitud.

Voy a tener que decir MediaInfo, He estado usando durante más de un año con una codificación de audio/vídeo de la aplicación en el que estoy trabajando.Dan toda la información de los archivos wav, junto con casi cualquier otro formato.

MediaInfoDll Viene con un ejemplo de código de C# sobre cómo conseguir trabajo.

Voy a suponer que estás un poco familiarizado con la estructura de una .Archivo WAV :contiene un WAVEFORMATEX encabezado struct, seguido por un número de otras estructuras (o "trozos") que contiene varios tipos de información.Ver Wikipedia para obtener más información sobre el formato de archivo.

En primer lugar, iterar a través de el .archivo wav y agregar la no acolchadas longitudes de los "datos" en trozos (los "datos" fragmento contiene los datos de audio para el archivo;por lo general hay sólo uno de estos, pero es posible que haya más de uno).Ahora tiene el tamaño total en bytes de los datos de audio.

La próxima, obtener el "promedio de bytes por segundo", miembro de la WAVEFORMATEX encabezado de la estructura del archivo.

Por último, dividir el tamaño total de los datos de audio por el promedio de bytes por segundo - esto le dará a usted la duración del archivo, en cuestión de segundos.

Esto funciona razonablemente bien para comprimir y archivos comprimidos.

tiempo = FileLength / (Frecuencia de Muestreo * Canales * Bits por muestra /8)

he probado sopló código de fallar,formatos de archivo, como "\\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;
    }
}

mientras naudio obras

    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

Descargar "PresentationCore.dll" y "WindowsBase.dll" a partir de:

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

Pegar los archivos en la aplicación de la carpeta bin de referencia.Debería funcionar ahora.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top