標準MP3ファイルには、id3タグと呼ばれる曲情報が含まれています。現在の主流となっています。次のような情報を含んでいます。id3v2タグが存在するかどうかを表す指標。常にID3という文字列が格納されている。id3v2のバージョン。1バイト目がメジャーバージョンとなり、2バイト目が改訂番号となる。拡張ヘッダやフッタが存在するかどうか表すビット群。id3v2タグのサイズ(ただし、タグヘッダのサイズは除く)。事実上有効なのは28ビット、即ち256メガバイトとなる。この値を確認すればId3v2形式かどうかを見極めることが可能です。ポインタはMP3データを指すことになるでしょう。タグサイズの取得について補足するため、次に1つの例を示します。最上位ビットが常に0でなければならないという決まりがありました。次のように1ビット次のバイトへ移行して格納されることになっています。00000011確かに、第1バイトの最上位ビットが0になっていることが確認できます。各バイトを適切にシフトし、論理和で結合する必要がでてきます。Rate)の違いも理解しておく必要があります。全てのフレームのビットレートが同一である場合はCBR形式と呼ばれます。フレームによってビットレートが異なる場合は、VBA形式になります。このCBRとVBRの違いは、次の処理で影響が出ることを確認しています。変換先データ(今回の場合WAVEデータ)のサイズを予測して返す関数でした。VBRの場合は本来望むサイズよりも小さいサイズを返すことがあるようです。acmStreamSizeを使わずにWAVEデータのサイズを取得する方法を考える必要があります。WAVEデータのサイズというのは、曲の長さ(秒数)が分かれば求められるようになっています。曲が5秒ちょうどならば、この値に5を掛ければよいのです。それでは、曲の長さをどう求めるかですが、これもMP3データに含まれるフレーム数が分かれば可能になっています。MP3データにおける1フレームは1152サンプルで構成されていました。これで1152を割り、その結果にフレーム数を掛ければ曲の長さが分かります。MP3データに含まれるフレーム数を取得するのは、それほど難解ではありません。データの中でフレームヘッダが見つかった回数がフレームの総数になりますす。したことを考慮してXINGヘッダと呼ばれるものがあります。このヘッダは、次のような形式になっています。XINGヘッダが存在するかどうかを表す指標。常にXingという文字列が格納されている。0x0001が含まれている場合はフレーム数が後続に格納されていることを意味する。Indicatorが格納されていることを意味する。MP3データに含まれるフレームの総数。特定の時間にシークするために必要な情報。注目すべきなのは、フラグに0x0001という値が含まれる場合です。それを取得することでMP3データをループする必要がなくなります。今回のプログラムは、id3v1及びid3v2の標準MP3ファイルを再生します。取得したMP3データをACMを介してWAVEデータに変換する点も同一です。TEXT("変換ストリームのオープンに失敗しました。TEXT("変換に失敗しました。TEXT("ファイルのオープンに失敗しました。TRUE;}ReadMP3Fileでは、まずファイル全体をロードしています。タグのサイズを取得します。先頭メンバのidを参照してID3という文字を調べることができます。そこにタグヘッダのサイズを加算することで、完全なタグサイズを取得できます。id3v1のためのコードだということが分かります。id3v1タグはファイルの最後から128バイトの位置に存在します。先頭3バイトがTAGという文字列であるかを調べています。IsId3v2の後には次のコードが実行されます。lpData;}lpMp3Dataには、MP3データの先頭を格納したいと思っています。それではメモリを解放する際に、タグヘッダの部分が含まれないことになります。そこにMP3データをコピーするようにしています。dwSizeにタグサイズが含まれてはならないため、dwTagSize分だけ引くことになります。この関数がMP3データからWAVEデータのサイズします。次の処理に注目します。GetFrameHeaderでフレームヘッダを取得しています。このときに+4をしているのはフレームヘッダの領域をカットするためです。ヘッダの指標となるXingが見つかった場合の処理は、次のようになっています。0;}まず、指標のサイズ分だけlpを進めます。次に、フラグの値を取得し、0x0001が含まれるかどうかを調べます。dwFlagsへの代入に*((LPDWORD)lp)としていないのは、データがビッグエンディアン形式で格納されているからです。フレームフラグ分だけlpを進めて実際にフレームの数を取得します。続いて、XINGヘッダがないときの処理を見ていきます。{dwOffset++;}}GetFrameHeaderを繰り返すことで、フレームの数を更新していきます。見つかった場合はフレーム分のサイズを足すことができます。ループは、オフセットの値がMP3データのサイズより低い限り可能です。最後に、取得したフレーム数からWAVEデータのサイズを求める処理を確認します。dSecond);フレーム数から曲の長さを求めるための計算式は既に述べた通りです。これをnAvgBytesPerSecに掛ければ、dSecond秒再生するために必要なサイズが求まります。