長さを決定するにはどうすればよいですか(つまり、C# の .wav ファイルの長さ)

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

  •  01-07-2019
  •  | 
  •  

質問

非圧縮の状況では、wav ヘッダーを読み取り、チャンネル数、ビット数、サンプル レートを取り出し、そこから計算する必要があることがわかっています。(チャンネル) * (ビット) * (サンプル/秒) * (秒) = (ファイルサイズ)

もっと簡単な方法はありますか?無料のライブラリか、.net Framework の何かでしょうか?

.wav ファイルが圧縮されている場合 (mpeg コーデックなどを使用して)、これを行うにはどうすればよいですか?

役に立ちましたか?

解決

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

他のヒント

リンクからnaudio.dllをダウンロードしますhttp://naudio.codeplex.com/

そしてこの関数を使用します

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

期間を取得します

すでに受け入れられている回答から何も損なうわけではありませんが、 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

しかもかなり速いですよ!参考資料はこちら オーディオ クラス。

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

以下のコードを試してください C# で .wav ファイルの長さを確認する方法

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

はい、音声ファイルの継続時間を取得するために使用できる無料のライブラリがあります。このライブラリはさらに多くの機能も提供します。

タグリブ

TagLib は、GNU Lesser General Public License (LGPL) および Mozilla Public License (MPL) に基づいて配布されます。

期間を秒単位で返す以下のコードを実装しました。

using TagLib.Mpeg;

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

もしかしたら、 XNAライブラリ WAV などの操作をサポートしています。あなたがその道を進んでいくつもりなら。ゲーム プログラミング用に C# で動作するように設計されているため、必要なものだけを処理できる可能性があります。

ここにはちょっとしたチュートリアル (おそらく、利用できる実際に動作するコードが含まれています) があります。 コードプロジェクト.

少し注意しなければならない唯一のことは、WAV ファイルが複数のチャンクで構成されるのは完全に「正常」であるということです。そのため、すべてのチャンクが含まれていることを確認するには、ファイル全体を調べなければなりません。

あなたのアプリケーションは圧縮 WAV を使って具体的に何をしているのでしょうか?圧縮された WAV ファイルは常に注意が必要です。この場合、私は常に OGG や WMA ファイルなどの代替コンテナ形式を使用するようにしています。XNA ライブラリは特定の形式で動作するように設計される傾向がありますが、XACT 内でより一般的な wav 再生方法が見つかる可能性もあります。考えられる代替案は、SDL C# ポートを調べることです。ただし、私はこれまで非圧縮 WAV の再生にのみ使用したことがあります。これを開くと、サンプル数をクエリして長さを決定できます。

言わなければなりません メディア情報, 私は現在取り組んでいるオーディオ/ビデオエンコードアプリケーションで1年以上使用しています。wav ファイルと他のほぼすべての形式に関するすべての情報が提供されます。

メディア情報Dll 動作させる方法に関するサンプル C# コードが付属しています。

.WAV ファイルの構造についてはある程度理解しているものと仮定します。これには、WAVEFORMATEX ヘッダー構造体が含まれており、その後にさまざまな種類の情報を含む他の多数の構造体 (または「チャンク」) が続きます。見る ウィキペディア ファイル形式の詳細については、を参照してください。

まず、.wav ファイルを繰り返し処理し、「データ」チャンクのパディングされていない長さを合計します (「データ」チャンクにはファイルのオーディオ データが含まれます。通常、これらは 1 つだけですが、複数ある可能性もあります)。これで、オーディオ データの合計サイズがバイト単位でわかりました。

次に、ファイルの WAVEFORMATEX ヘッダー構造体の「1 秒あたりの平均バイト数」メンバーを取得します。

最後に、オーディオ データの合計サイズを 1 秒あたりの平均バイト数で割ります。これにより、ファイルの長さが秒単位で求められます。

これは、非圧縮ファイルでも圧縮ファイルでもかなりうまく機能します。

時間 = ファイルの長さ / (サンプル レート * チャンネル * サンプルあたりのビット数 /8)

テストしたところ、壊れたコードは失敗します。ファイル形式は「\\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;
    }
}

naudioが動作している間

    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

「PresentationCore.dll」と「WindowsBase.dll」を次からダウンロードします。

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

参照用にアプリケーションの bin フォルダーにファイルを貼り付けます。これで動作するはずです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top