Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I determine the length (i.e. duration) of a .wav file in C#?

In the uncompressed situation I know I need to read the wav header, pull out the number of channels, bits, and sample rate and work it out from there: (channels) * (bits) * (samples/s) * (seconds) = (filesize)

Is there a simpler way - a free library, or something in the .net framework perhaps?

How would I do this if the .wav file is compressed (with the mpeg codec for example)?

like image 930
John Sibly Avatar asked Sep 17 '08 11:09

John Sibly


People also ask

What is sample width in WAV file?

Every wav file has a sample width, or, the number of bytes per sample. Typically this is either 1 or 2 bytes. The wav module supplies more convenient access to this data.

How do I read a wave file?

Windows and Mac are both capable of opening WAV files. For Windows, if you double-click a WAV file, it will open using Windows Media Player. For Mac, if you double-click a WAV, it will open using iTunes or Quicktime.


10 Answers

Download NAudio.dll from the link https://www.dll-files.com/naudio.dll.html

and then use this function

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

you will get the Duration

like image 167
Monti Pal Avatar answered Oct 11 '22 16:10

Monti Pal


You may consider using the mciSendString(...) function (error checking is omitted for clarity):

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;
        }
    }
}
like image 40
Jan Zich Avatar answered Oct 11 '22 16:10

Jan Zich


I had difficulties with the example of the MediaPlayer-class above. It could take some time, before the player has opened the file. In the "real world" you have to register for the MediaOpened-event, after that has fired, the NaturalDuration is valid. In a console-app you just have to wait a few seconds after the open.

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();
    }
  }
}
like image 45
Lars Avatar answered Oct 11 '22 16:10

Lars


Not to take anything away from the answer already accepted, but I was able to get the duration of an audio file (several different formats, including AC3, which is what I needed at the time) using the Microsoft.DirectX.AudioVideoPlayBack namespace. This is part of DirectX 9.0 for Managed Code. Adding a reference to that made my code as simple as this...

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

And it's pretty fast, too! Here's a reference for the Audio class.

like image 28
Josh Stodola Avatar answered Oct 11 '22 15:10

Josh Stodola


Yes, There is a free library that can be used to get time duration of Audio file. This library also provides many more functionalities.

TagLib

TagLib is distributed under the GNU Lesser General Public License (LGPL) and Mozilla Public License (MPL).

I implemented below code that returns time duration in seconds.

using TagLib.Mpeg;

public static double GetSoundLength(string FilePath)
{
    AudioFile ObjAF = new AudioFile(FilePath);
    return ObjAF.Properties.Duration.TotalSeconds;
}
like image 34
Manish Nayak Avatar answered Oct 11 '22 17:10

Manish Nayak


In the .net framework there is a mediaplayer class:

http://msdn.microsoft.com/en-us/library/system.windows.media.mediaplayer_members.aspx

Here is an example:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2667714&SiteID=1&pageid=0#2685871

like image 32
Cetra Avatar answered Oct 11 '22 16:10

Cetra


Try code below from How to determine the length of a .wav file in C#

    string path = @"c:\test.wav";
    WaveReader wr = new WaveReader(File.OpenRead(path));
    int durationInMS = wr.GetDurationInMS();
    wr.Close();
like image 28
Aleks Avatar answered Oct 11 '22 17:10

Aleks


i have tested blew code would fail,file formats are like "\\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;
    }
}

while naudio works

    public static int GetSoundLength(string fileName)
     {
        using (WaveFileReader wf = new WaveFileReader(fileName))
        {
            return (int)wf.TotalTime.TotalMilliseconds;
        }
     }`
like image 35
item.wu Avatar answered Oct 11 '22 16:10

item.wu


You might find that the XNA library has some support for working with WAV's etc. if you are willing to go down that route. It is designed to work with C# for game programming, so might just take care of what you need.

like image 28
xan Avatar answered Oct 11 '22 16:10

xan


There's a bit of a tutorial (with - presumably - working code you can leverage) over at CodeProject.

The only thing you have to be a little careful of is that it's perfectly "normal" for a WAV file to be composed of multiple chunks - so you have to scoot over the entire file to ensure that all chunks are accounted for.

like image 39
moobaa Avatar answered Oct 11 '22 15:10

moobaa