Подтвердить что ты не робот

Как я могу определить длину (то есть продолжительность) WAV файла в С#?

В несжатой ситуации я знаю, что мне нужно прочитать заголовок wav, вытащить количество каналов, бит и частоту дискретизации и оттуда оттуда: (каналы) * (бит) * (выборки/с) * (секунды) = (размер файла)

Есть ли более простой способ - бесплатная библиотека или что-то в рамках .net, возможно?

Как бы это сделать, если файл .wav сжимается (например, с помощью кодека mpeg)?

4b9b3361

Ответ 1

Вы можете использовать функцию 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

Загрузить файл NAudio.dll из ссылки http://naudio.codeplex.com/

а затем используйте эту функцию

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

вы получите продолжительность

Ответ 3

Не отнимать ничего от уже принятого ответа, но я смог получить длительность аудиофайла (несколько разных форматов, включая AC3, что мне было нужно в то время), используя пространство имен Microsoft.DirectX.AudioVideoPlayBack. Это часть DirectX 9.0 для управляемого кода. Добавление ссылки сделало мой код таким простым...

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

И это тоже довольно быстро! Здесь ссылка на аудио класс.

Ответ 5

У меня возникли трудности с примером вышеперечисленного класса 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();
    }
  }
}

Ответ 7

Да, есть бесплатная библиотека, которая может использоваться для получения продолжительности аудиофайла. Эта библиотека также предоставляет гораздо больше функциональных возможностей.

TagLib

TagLib распространяется под лицензией GNU Lesser General Public License (LGPL) и публичной лицензией Mozilla (MPL).

Я выполнил ниже код, который возвращает продолжительность времени в секундах.

using TagLib.Mpeg;

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

Ответ 9

Там немного учебника (с предположительным рабочим кодом, который вы можете использовать) на CodeProject.

Единственное, о чем вы должны быть немного осторожны, это то, что он идеально "нормален" для WAV файла, состоящего из нескольких фрагментов, поэтому вам нужно запустить весь файл, чтобы убедиться, что все куски учтены.

Ответ 10

Что именно делает ваше приложение со сжатыми WAV? Сжатые файлы WAV всегда сложны - я всегда стараюсь использовать альтернативный формат контейнера в этом случае, например, файлы OGG или WMA. Библиотеки XNA, как правило, предназначены для работы с определенными форматами - хотя возможно, что в XACT вы найдете более общий метод воспроизведения wav. Возможной альтернативой является просмотр порта SDL С#, хотя я использовал его только для воспроизведения несжатых WAV. После открытия вы можете запросить количество выборок для определения длины.

Ответ 11

Мне нужно сказать MediaInfo, я использую его более года с приложением для кодирования аудио/видео Я работаю на. Он предоставляет всю информацию для wav файлов вместе с почти любым другим форматом.

MediaInfoDll Поставляется с образцом кода С# о том, как заставить его работать.

Ответ 12

Я предполагаю, что вы знакомы со структурой файла .WAV: он содержит структуру заголовка WAVEFORMATEX, а затем ряд других структур (или "кусков" ), содержащих различные виды информации. См. Wikipedia для получения дополнительной информации о формате файла.

Во-первых, выполните итерацию через .wav файл и добавьте недописанную длину фрагментов данных (фрагмент данных содержит аудиоданные для файла, обычно есть только один из них, но возможно, что может быть более одного). Теперь у вас есть общий размер в байтах аудиоданных.

Далее, получите член "средний байт в секунду" структуры заголовка WAVEFORMATEX файла.

Наконец, разделите общий размер аудиоданных на средние байты в секунду - это даст вам продолжительность файла в секундах.

Это хорошо работает для несжатых и сжатых файлов.

Ответ 13

время = FileLength/(частота дискретизации * каналы * биты на выборку /8)

Ответ 14

я проверил блю код не получится, форматы файлов такие как \\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;
    }
}

пока наудио работает

    public static int GetSoundLength(string fileName)
     {
        using (WaveFileReader wf = new WaveFileReader(fileName))
        {
            return (int)wf.TotalTime.TotalMilliseconds;
        }
     }'

Ответ 15

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