it-swarm-pt.tech

Como posso determinar o comprimento (ou seja, a duração) de um arquivo .wav em c #?

Na situação descompactada eu sei que preciso ler o cabeçalho wav, extrair o número de canais, bits e taxa de amostragem e trabalhá-lo a partir daí: (canais) * (bits) * (samples/s) * (segundos) = (tamanho do arquivo)

Existe uma maneira mais simples - uma biblioteca livre, ou algo no framework .net, talvez?

Como eu faria isso se o arquivo .wav fosse compactado (com o codec mpeg, por exemplo)?

26
John Sibly

Você pode considerar o uso da função mciSendString (...) (a verificação de erros é omitida para maior clareza):

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;
        }
    }
}
18
Jan Zich

Baixe NAudio.dll a partir do link http://naudio.codeplex.com/

e então use esta função

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

você vai ter a duração

29
Monti Pal

Não tirar nada da resposta já aceita, mas consegui obter a duração de um arquivo de áudio (vários formatos diferentes, incluindo o AC3, que era o que eu precisava no momento) usando o namespace Microsoft.DirectX.AudioVideoPlayBack. Isso faz parte do DirectX 9.0 para código gerenciado . Adicionar uma referência a isso tornou meu código tão simples quanto isso ...

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

E é bem rápido também! Aqui está uma referência para a classe Audio .

5
Josh Stodola
3
Cetra

Sim, há uma biblioteca gratuita que pode ser usada para obter a duração do tempo do arquivo de áudio. Esta biblioteca também oferece muitas outras funcionalidades.

TagLib

O TagLib é distribuído sob a GNU Licença Pública Geral Menor (LGPL) e Licença Pública da Mozilla (MPL).

Implementei abaixo o código que retorna a duração do tempo em segundos.

using TagLib.Mpeg;

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

Eu tive dificuldades com o exemplo da classe MediaPlayer acima. Pode levar algum tempo antes que o player abra o arquivo. No "mundo real" você tem que se registrar para o evento MediaOpened, depois que ele é disparado, o NaturalDuration é válido. Em um aplicativo de console, você só precisa aguardar alguns segundos após a abertura.

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

Tente código abaixo de como determinar o comprimento de um arquivo .wav em c #

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

Eu vou ter que dizer MediaInfo , eu tenho usado por mais de um ano com um aplicativo de codificação de áudio/vídeo em que estou trabalhando. Ele fornece todas as informações para arquivos wav junto com quase todos os outros formatos.

MediaInfoDll vem com código C # de amostra sobre como fazê-lo funcionar.

1
sieben

Você pode achar que a biblioteca XNA tem algum suporte para trabalhar com WAV, etc., se você estiver disposto a seguir esse caminho. Ele foi projetado para funcionar com o C # para programação de jogos, portanto, basta cuidar do que você precisa.

1
xan

Há um pouco de um tutorial (com - presumivelmente - código de trabalho que você pode aproveitar) em CodeProject .

A única coisa que você tem que ter um pouco de cuidado é que é perfeitamente "normal" para um arquivo WAV ser composto de vários pedaços - então você tem que fugir de todo o arquivo para garantir que todos os pedaços são contabilizados.

1
moobaa

O que exatamente seu aplicativo está fazendo com WAVs compactados? Arquivos WAV compactados são sempre complicados - eu sempre tento usar um formato de contêiner alternativo, neste caso, como arquivos OGG ou WMA. As bibliotecas XNA tendem a ser projetadas para trabalhar com formatos específicos - embora seja possível que dentro do XACT você encontre um método de reprodução de arquivos mais genérico. Uma alternativa possível é olhar para a porta SDL C #, embora eu tenha usado apenas para reproduzir WAVs descompactados - uma vez aberto, você pode consultar o número de amostras para determinar o comprimento.

1
Bubba

eu testei código blew iria falhar, formatos de arquivo são 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;
    }
}

enquanto o naudio funciona

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

Suponho que você esteja familiarizado com a estrutura de um arquivo .WAV: ele contém uma estrutura de cabeçalho WAVEFORMATEX, seguida por várias outras estruturas (ou "pedaços") contendo vários tipos de informações. Veja Wikipedia para mais informações sobre o formato do arquivo.

Primeiro, percorra o arquivo .wav e some os comprimentos não preenchidos dos fragmentos de "dados" (o fragmento "data" contém os dados de áudio do arquivo; normalmente, há apenas um deles, mas é possível que possa haver mais de um). Agora você tem o tamanho total, em bytes, dos dados de áudio.

Em seguida, obtenha o membro "average bytes per second" da estrutura do cabeçalho WAVEFORMATEX do arquivo.

Por fim, divida o tamanho total dos dados de áudio pela média de bytes por segundo - isso fornecerá a duração do arquivo, em segundos.

Isso funciona razoavelmente bem para arquivos compactados e não compactados.

0
GogglesPisano

time = FileLength/(Taxa de amostragem * Canais * Bits por amostra/8)

0
Martin Abilev