9

wav ファイルからウェーブを出力しようとしていますが、サンプルの長さをどのようにすればよいかわかりません。

これは私がアーカイブしたいものです(色なし): ミュージック wav

したがって、データを読み取るために、次のコードを使用します。

// first we need to read our wav file, so we can get our info:
byte[] wav = File.ReadAllBytes(filename);

// then we are going to get our file's info
info.NumChannnels = wav[22];
info.SampleRate = bytesToInt(wav[24], wav[25]);

// nr of samples is the length - the 44 bytes that where needed for the offset
int samples = (wav.Length - 44) / 2;

// if there are 2 channels, we need to devide the nr of sample in 2
if (info.NumChannnels == 2) samples /= 2;

// create the array
leftChannel = new List<float>();
if (info.NumChannnels == 2) rightChannel = new List<float>();
else rightChannel = null;

int pos = 44; // start of data chunk
for (int i = 0; i < samples; i++) {
    leftChannel.Add(bytesToFloat(wav[pos], wav[pos + 1]));
    pos += 2;
    if (info.NumChannnels == 2) {
        rightChannel.Add(bytesToFloat(wav[pos], wav[pos + 1]));
        pos += 2;
    }
}

BytesToFloat = 2 バイトを -1 から 1 の間の float に変換します

これでデータのリストが 2 つになりましたが、1 行を作成するために何個の数値を取得すればよいのでしょうか?

私を最も混乱させているのは、曲を再生すると、ほとんどの音楽プレーヤーで次のデータが表示されることです。これは、私の目には 1 つのサンプルの表現です。 ここに画像の説明を入力

しかし、これらのバーのそれぞれの値と、サンプルに含まれるバーの数をどのように知ることができますか?

4

1 に答える 1

11

あなたの質問は、オーディオの2つの異なる視覚化についてです。波形を描画するために、投稿したコードは描画の準備がほぼ整っていますが、サンプルごとに1つのエントリをリストに追加しています。多くの場合、オーディオは1秒あたり44100サンプルであるため、3分間の曲の波形には、全体で約800万ピクセルが必要になります。だからあなたがすることはそれらをバッチ処理することです。たとえば4410ピクセル(つまり100ms)ごとに、最高値と最低値のピクセルを見つけ、それを使用して線を引きます。実際、通常は、最大絶対値を見つけて対称波形を描くだけで済みます。

これは、サンプル値に簡単にアクセスできるようにNAudioを使用してWPFでオーディオファイルの基本的な波形を描画するためのコードです(WAVまたはMP3ファイルを実行できます)。左右のチャンネルからの分割は含めていませんが、追加するのはかなり簡単です。

var window = new Window();
var canvas = new Canvas();
using(var reader = new AudioFileReader(file))
{
    var samples = reader.Length / (reader.WaveFormat.Channels * reader.WaveFormat.BitsPerSample / 8);
    var f = 0.0f;
    var max = 0.0f;
    // waveform will be a maximum of 4000 pixels wide:
    var batch = (int)Math.Max(40, samples / 4000);
    var mid = 100;
    var yScale = 100;
    float[] buffer = new float[batch];
    int read;
    var xPos = 0;
    while((read = reader.Read(buffer,0,batch)) == batch)
    {
        for(int n = 0; n < read; n++)
        {
            max = Math.Max(Math.Abs(buffer[n]), max);
        }
        var line = new Line();
        line.X1 = xPos;
        line.X2 = xPos;
        line.Y1 = mid + (max * yScale); 
        line.Y2 = mid - (max * yScale);
        line.StrokeThickness = 1;
        line.Stroke = Brushes.DarkGray;
        canvas.Children.Add(line);
        max = 0;    
        xPos++;
    }
    canvas.Width = xPos;
    canvas.Height = mid * 2;
}
window.Height = 260;
var scrollViewer = new ScrollViewer();
scrollViewer.Content = canvas;
scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
window.Content = scrollViewer;
window.ShowDialog();

2番目の視覚化は、スペクトログラムまたはスペクトラムアナライザと呼ばれることもあります。これは1つのサンプルを表すのではなく、サンプルのブロックに存在する周波数を表します。この情報を取得するには、サンプルを高速フーリエ変換(FFT)に通す必要があります。通常、1024サンプルのブロックを通過します(2の累乗である必要があります)。残念ながら、DSPを初めて使用する場合、FFTの操作は難しい場合があります。これは、次の方法を学ぶ必要があるためです。

  • 窓関数を適用する
  • オーディオを正しい入力形式にします(多くのFFTは入力を複素数として期待します)
  • どのビン番号がどの周波数に対応するかを計算し、
  • 各ビンの大きさを見つけて、それをデシベルスケールに変換します。

StackOverflowで、これらの各トピックに関する詳細情報を見つけることができるはずです。この記事では、C#でFFTを使用する方法について少し説明しました。

于 2012-11-30T10:57:54.777 に答える