MP3 から PCM を抽出するために FMOD ライブラリを使用しています。2 チャンネル全体 - 16 ビットのものを取得し、44100hz のサンプル レートは 1 秒間に 44,100 サンプルの「サウンド」であることも取得します。私が得られないのは、16ビット値が正確に何を表しているのかということです。xy 軸に座標をプロットする方法は知っていますが、何をプロットしているのでしょうか? Y 軸は時間を表し、X 軸は何を表しますか? 騒音レベル?振幅と同じですか?この値を構成するさまざまなサウンドを特定するにはどうすればよいですか。つまり、16 ビットの数値からスペクトルを取得するにはどうすればよいでしょうか。
これは別の質問かもしれませんが、実際に私が本当に答える必要があるのは、25 ミリ秒ごとに振幅を取得するにはどうすればよいかということです。44,100 個の値を取り、40 (40 * 0.025 秒 = 1 秒) で割りますか? これにより、1102.5 サンプルが得られます。では、1102 の値をブラックボックスに入力して、その瞬間の振幅を取得しますか?
元の投稿を編集して、すぐにテストする予定のコードを追加しました: (注: フレームレートを 25 ミリ秒から 40 ミリ秒に変更しました)
// 44100 / 25 frames = 1764 samples per frame -> 1764 * 2 channels * 2 bytes [16 bit sample] = 7056 bytes
private const int CHUNKSIZE = 7056;
uint bytesread = 0;
var squares = new double[CHUNKSIZE / 4];
const double scale = 1.0d / 32768.0d;
do
{
result = sound.readData(data, CHUNKSIZE, ref read);
Marshal.Copy(data, buffer, 0, CHUNKSIZE);
//PCM samples are 16 bit little endian
Array.Reverse(buffer);
for (var i = 0; i < buffer.Length; i += 4)
{
var avg = scale * (Math.Abs((double)BitConverter.ToInt16(buffer, i)) + Math.Abs((double)BitConverter.ToInt16(buffer, i + 2))) / 2.0d;
squares[i >> 2] = avg * avg;
}
var rmsAmplitude = ((int)(Math.Floor(Math.Sqrt(squares.Average()) * 32768.0d))).ToString("X2");
fs.Write(buffer, 0, (int) read);
bytesread += read;
statusBar.Text = "writing " + bytesread + " bytes of " + length + " to output.raw";
} while (result == FMOD.RESULT.OK && read == CHUNKSIZE);
mp3 をロードした後、私の rmsAmplitude は 3C00 から 4900 の範囲にあるようです。広がりを期待していました。