変換後のフォーマットをユーザーに選択させる機能を持たせると便利です。フォーマット専用のUIをユーザーに提供する必要性が出てくるでしょう。ユーザーが選択したフォーマットを構造体経由で返します。);pfmtcは、ACMFORMATCHOOSE構造体のアドレスを指定します。MMSYSERR_NOERRORは0として定義されているため、他のACM関数と同じように扱って問題はありません。acmFormatChooseで列挙されるフォーマットは、優先順位の高いドライバが基になります。次に、acmFormatChosseで表示されるダイアログを示します。属性という名前のコンボボックスでサンプリングレートなどのフォーマットを選択します。Layer-3が表示されます。次に、acmFormatChosseを呼び出す例を示します。FALSE;}この自作関数は、lpwfにユーザーが選択したフォーマットを受け取るものとします。アドレスを指定することになるため、ここではそのままlpwfを指定するように指定してます。cbwfxは、pwfxのサイズです。cbStructは、ACMFORMATCHOOSE構造体のサイズを代入します。以上の3つのメンバです。変換先フォーマットを取得したら、次はそのフォーマットに変換可能であるかを調べてみましょう。acmFormatSuggestの方がドライバのテストという面において適切だといえます。変化の結果自体を推測させることが可能となっています。関数の戻り値が0であるかを調べることになります。TEXT("変換に失敗しました。0;}第5引数に指定している定数は、acmFormatSuggestに指定できる全ての定数です。適切に初期化しておかなければなりません。先に示したacmFormatChosseは、これらのメンバも適切に初期化しています。そのWAVEフォーマットを決定するためのダイアログをacmFormatChosseで表示します。TEXT("フォーマットが選択されませんでした。TEXT("このフォーマットには変換できません。TEXT("変換を終了しました。TEXT("変換ストリームのオープンに失敗しました。TEXT("変換に失敗しました。TEXT("ファイルのオープンに失敗しました。TEXT("RIFF/WAVE形式のMP3ファイルではありません。0);}DecodeToWaveでacmFormatSuggestを呼び出していないところに注目してください。ドライバにフォーマットを決定してもらうコードは不要になるのです。acmFormatChosseを内部で呼び出すChooseWaveFormatは、次のように呼び出されています。TEXT("フォーマットが選択されませんでした。acmFormatChosseで初期化されることから、事前に特別な初期化は必要ありません。ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCTを指定することになるでしょう。次に、ChooseWaveFormatの内部を見てみます。選択できるフォーマットを限定させるのが効果的です。どのメンバを有効にするのかを表す定数を格納します。WAVEFORMATEX構造体のアドレスです。WAVE_FORMAT_PCMのみとなります。サンプリングレート用のフラグとメンバを設定することになります。PCMでサンプリングレートが24KHzであるものに限られることになります。これは前々節で紹介したプログラムを実行すれば直ぐに分かります。最後にacmFormatSuggestが失敗したときの処理について見てみましょう。失敗したのかをユーザーに通知する機能を持たせると便利です。TEXT("このフォーマットには変換できません。pwfxのフォーマットを文字列化したものがszFormatに格納されます。これを利用すれば、wsprintfでpwfxのメンバを参照して文字列を整形する必要はなくなります。本来ならばそれらを参照するべきとといえます。成り立っていますが、それ故にあと少しの機能拡張が欲しくなることがあります。それを付け足せだけでも、使い勝手は更に上がるのではないでしょうか。フックプロシージャの機能を利用すれば、このような要望を叶えることができるかもしれません。pfnHookとlCustDataが有効なメンバとなります。上記の場合、acmFormatChooseHookProcがそれに当たります。lCustDataに指定したデータは、フックプロシージャのWM_INITDIALOGのlParamに渡ります。次に、フックプロシージャの処理例を示します。WM_COMMANDを捕らえればボタンの押下を検出することができます。本来の関数にメッセージが送られなくなります。ダイアログのコンボボックスに文字列が追加される前に送られることになっています。そこで0以外の値を返すことは文字列が追加されるのを防ぐことを意味しています。そのフォーマットを調べることによって、選択するつもりのないフォーマットを除外できます。lParamで表されるフォーマットの文字列は、コンボボックスに含まれないことになります。