Comment puis-je déterminer la longueur (c'est-à-dire la durée) d'un fichier .wav en C #?

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

  •  01-07-2019
  •  | 
  •  

Question

Dans la situation non compressée, je sais que je dois lire l'en-tête wav, extraire le nombre de canaux, de bits et la fréquence d'échantillonnage, puis résoudre le problème: (canaux) * (bits) * (échantillons / s) * (secondes) = (taille du fichier)

Existe-t-il un moyen plus simple: une bibliothèque libre ou quelque chose dans le framework .net peut-être?

Comment procéder si le fichier .wav est compressé (avec le codec mpeg par exemple)?

Était-ce utile?

La solution

Vous pouvez envisager d'utiliser la fonction mciSendString (...) (la vérification des erreurs est omise pour plus de clarté):

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

Autres conseils

Télécharger NAudio.dll du lien http://naudio.codeplex.com/

puis utilisez cette fonction

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

vous obtiendrez la durée

Ne rien enlever à la réponse déjà acceptée, mais j’ai pu obtenir la durée d’un fichier audio (plusieurs formats, y compris AC3, ce dont j’avais besoin à l’époque) en utilisant de Microsoft. DirectX.AudioVideoPlayBack espace de noms. Cela fait partie de DirectX 9.0 pour le code géré . Ajouter une référence à cela a rendu mon code aussi simple que cela ...

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

Et c'est assez rapide aussi! Voici une référence pour la classe Audio .

J'ai eu des difficultés avec l'exemple de la classe MediaPlayer ci-dessus. Cela pourrait prendre un certain temps avant que le lecteur ait ouvert le fichier. Dans le "monde réel" vous devez vous inscrire à l'événement MediaOpened. Après son déclenchement, NaturalDuration est valide. Dans une application console, il vous suffit d'attendre quelques secondes après l'ouverture.

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

Essayez le code ci-dessous à partir de Comment déterminer la longueur d'un fichier .wav en C #

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

Oui, il existe une bibliothèque gratuite qui peut être utilisée pour obtenir la durée du fichier audio. Cette bibliothèque fournit également de nombreuses autres fonctionnalités.

TagLib

TagLib est distribué sous licence LGPL (GNU Lesser General Public License) et Mozilla Public License (MPL).

J'ai implémenté le code ci-dessous qui renvoie la durée en secondes.

using TagLib.Mpeg;

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

Vous constaterez peut-être que la bibliothèque XNA prend en charge certains types de fichiers. travailler avec WAV, etc. si vous êtes prêt à aller dans cette voie. Il est conçu pour fonctionner avec C # pour la programmation de jeux. Vous pouvez donc vous occuper de ce dont vous avez besoin.

Il y a un peu de didacticiel (avec - vraisemblablement - un code de travail que vous pouvez utiliser) à CodeProject .

La seule chose à laquelle vous devez faire attention, c’est que c’est parfaitement "normal". pour qu'un fichier WAV soit composé de plusieurs morceaux - vous devez donc parcourir tout le fichier pour vous assurer que tous les morceaux sont comptabilisés.

Que fait exactement votre application avec les WAV compressés? Les fichiers WAV compressés sont toujours délicats. J'essaie toujours d'utiliser un format de conteneur alternatif dans ce cas, tel que les fichiers OGG ou WMA. Les bibliothèques XNA ont tendance à être conçues pour fonctionner avec des formats spécifiques - bien qu'il soit possible que XACT contienne une méthode de lecture wav plus générique. Une alternative possible est d’examiner le port SDL C #, bien que je ne l’aie jamais utilisé que pour lire des fichiers WAV non compressés. Une fois ouvert, vous pouvez interroger le nombre d’échantillons pour déterminer la longueur.

Je dois dire que MediaInfo , je l'utilise depuis plus d'un an avec une application d'encodage audio / vidéo sur laquelle je travaille. Il donne toutes les informations pour les fichiers wav avec presque tous les autres formats.

MediaInfoDll Livré avec un exemple de code C # pour savoir comment l'obtenir. travail.

Je suppose que vous connaissez un peu la structure d'un fichier .WAV: il contient une structure d'en-tête WAVEFORMATEX, suivie d'un certain nombre d'autres structures (ou "chunks") contenant divers types d'informations. . Consultez Wikipedia pour plus d'informations sur le format de fichier.

Tout d'abord, parcourez le fichier .wav et additionnez les longueurs non complétées du paramètre "data". morceaux (le morceau "data" contient les données audio du fichier; il n'y en a généralement qu'un, mais il est possible qu'il en existe plusieurs). Vous avez maintenant la taille totale, en octets, des données audio.

Ensuite, obtenez les "octets moyens par seconde". membre de la structure d'en-tête WAVEFORMATEX du fichier.

Enfin, divisez la taille totale des données audio par le nombre moyen d'octets par seconde. Cela vous donnera la durée du fichier, en secondes.

Cela fonctionne relativement bien pour les fichiers non compressés et compressés.

time = FileLength / (fréquence d'échantillonnage * canaux * bits par échantillon / 8)

J'ai testé le code de vidage qui échouerait, les formats de fichier ressemblent à "\\ 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;
    }
}

pendant que naudio fonctionne

    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

Télécharger " PresentationCore.dll " et " WindowsBase.dll " à partir de:

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

Collez les fichiers dans le dossier bin de votre application pour référence. Cela devrait fonctionner maintenant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top