0

Wave ファイル形式と C++ の両方を学習しているときに好奇心から、Wave 形式の正規のレイアウトについて詳しく説明しているこのページにたどり着きました。

さて、サンプルレートを読み取るC++プログラムを書いてみました

char buffer[4];
// already read other values before reading sample rate
inFile.read(buffer, 4);
// conversion using little endian
sampleRate = (long) buffer[0] + ((long) buffer[1] << 8) + ((long) buffer[2] << 16) + ((long) buffer[3] << 24);

16 進エディタで、サンプル ウェーブ ファイルのサンプル レートが であることがわかります44 ac 00 00。これは 44100 レートに変換されます。ただし、上記のコードでは、常に -21436 になります

いくつかのデバッグの後、生の 16 進数値「ac」は 10 進数で 172 に変換される必要があることが判明しましたが、C++ は 16 進数値を「ffffffac」と想定し、10 進数で -84 に変換します。C++ が単純な "ac" であると想定した場合、正しいサンプル レート値が得られます。

問題は、Wave ファイルからデータを読み取り、実際に正しいサンプル レートを取得するにはどうすればよいかということです。先頭の「f」を取り除くために魔法をかける必要がありますか?

事前にたくさんありがとう!

4

2 に答える 2

3

The simplest approach is as follows:

// simply store bytes directly into sampleRate
long sampleRate = 0;
inFile.read(&sampleRate, 4);

This, as you may suspect, assumes your system is little Endian. To fix your example, you must avoid the sign extension that is taking place when you cast to long. Declare buffer of type unsigned char. See the following.

unsigned char buffer[4];
inFile.read(buffer, 4);
long sampleRate = (long)buffer[0] + ((long)buffer[1] << 8) + ((long)buffer[2] << 16) + ((long)buffer[3] << 24);
于 2012-12-05T01:33:21.203 に答える
1

コードを修正するには 2 つの方法があります。1 つ目は、すべてを符号なしにすることで、符号なし算術演算が全体で使用されるようにすることです。2 つ目は、ビット マスクを使用して符号拡張を削除することです。

sampleRate = ((long) buffer[0] & 0xff) + (((long) buffer[1] << 8) & 0xff00) + (((long) buffer[2] << 16) & 0xff0000) + ((long) buffer[3] << 24);
于 2012-12-05T01:35:43.187 に答える