圧縮されていない状況では、wav ヘッダーを読み取り、チャンネル数、ビット数、サンプル レートを取り出して、そこから計算する必要があることがわかっています: (チャンネル) * (ビット) * (サンプル/秒) * (秒) = (ファイルサイズ)
より簡単な方法はありますか - 無料のライブラリ、または .net フレームワークの何かですか?
.wav ファイルが圧縮されている場合 (たとえば、mpeg コーデックで)、これを行うにはどうすればよいですか?
圧縮されていない状況では、wav ヘッダーを読み取り、チャンネル数、ビット数、サンプル レートを取り出して、そこから計算する必要があることがわかっています: (チャンネル) * (ビット) * (サンプル/秒) * (秒) = (ファイルサイズ)
より簡単な方法はありますか - 無料のライブラリ、または .net フレームワークの何かですか?
.wav ファイルが圧縮されている場合 (たとえば、mpeg コーデックで)、これを行うにはどうすればよいですか?
リンクhttps://www.dll-files.com/naudio.dll.htmlからNAudio.dllをダウンロードし ます。
次に、この関数を使用します
public static TimeSpan GetWavFileDuration(string fileName)
{
WaveFileReader wf = new WaveFileReader(fileName);
return wf.TotalTime;
}
あなたは期間を取得します
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;
}
}
}
すでに受け入れられている回答から何かを奪うことはありませんが、 Microsoft.DirectX.AudioVideoPlayBack
名前空間を使用して、オーディオ ファイル (当時必要だった AC3 を含むいくつかの異なる形式) の長さを取得することができました。これはマネージ コード用の 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
そして、それもかなり速いです!Audioクラスのリファレンスは次のとおりです。
上記の 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();
}
}
}
.net フレームワークには、mediaplayer クラスがあります。
http://msdn.microsoft.com/en-us/library/system.windows.media.mediaplayer_members.aspx
次に例を示します。
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2667714&SiteID=1&pageid=0#2685871
C# で .wav ファイルの長さを確認する方法 から以下のコードを試してください。
string path = @"c:\test.wav";
WaveReader wr = new WaveReader(File.OpenRead(path));
int durationInMS = wr.GetDurationInMS();
wr.Close();
XNA ライブラリには、WAV などを操作するためのサポートがいくつかあることに気付くかもしれません。ゲーム プログラミング用に C# で動作するように設計されているため、必要なことだけを行うことができます。
CodeProjectには、少しのチュートリアルがあります (おそらく、活用できる実際のコードが含まれています) 。
少し注意しなければならないことは、WAV ファイルが複数のチャンクで構成されているのは完全に「正常」であることだけです。そのため、すべてのチャンクが考慮されるように、ファイル全体をスクートする必要があります。
あなたのアプリケーションは、圧縮された WAV を使って正確に何をしていますか? 圧縮された WAV ファイルは常に注意が必要です。この場合、OGG や WMA ファイルなどの別のコンテナー形式を常に試して使用します。XNA ライブラリは、特定の形式で動作するように設計されている傾向がありますが、XACT 内では、より一般的な wav 再生方法が見つかる可能性があります。考えられる代替手段は、SDL C# ポートを調べることです。ただし、私は圧縮されていない WAV を再生するためにしか使用したことがありません。開いたら、サンプル数を照会して長さを判断できます。
私はMediaInfoと言わざるを得ません。私は、取り組んでいるオーディオ/ビデオ エンコーディング アプリケーションで 1 年以上使用しています。他のほとんどすべての形式とともに、wav ファイルのすべての情報を提供します。
MediaInfoDllには、動作させる方法に関するサンプル C# コードが付属しています。
あなたが .WAV ファイルの構造にある程度精通していることを前提としています。このファイルには、WAVEFORMATEX ヘッダー構造体が含まれており、その後にさまざまな種類の情報を含む他の構造体 (または「チャンク」) が続きます。ファイル形式の詳細については、ウィキペディアを参照してください。
最初に、.wav ファイルを繰り返し処理し、「データ」チャンクのパディングされていない長さを合計します (「データ」チャンクには、ファイルのオーディオ データが含まれます。通常、これらは 1 つだけですが、存在する可能性があります。複数の)。これで、オーディオ データの合計サイズ (バイト単位) がわかりました。
次に、ファイルの WAVEFORMATEX ヘッダー構造体の「1 秒あたりの平均バイト数」メンバーを取得します。
最後に、オーディオ データの合計サイズを 1 秒あたりの平均バイト数で割ります。これにより、ファイルの長さが秒単位でわかります。
これは、圧縮されていないファイルと圧縮されたファイルに対してかなりうまく機能します。
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