XAPO用の自作クラスは別にCLSIDは不要と言えば不要にできる
XAPOクラスにはCLSID(COMクラスID)が必要です。なのでVisualStudioの機能が使える人はそれで生成してVS用の特殊なプロパティを書いてCLSIDとの対応付けをして…と面倒この上作業を必要とします。がしかし、これは実は必要ないかもしれません。
というのもCLSIDはCoCreateInstanceで必要だったり、IUnknown::QueryInterfaceで利用しない限り必要でないからです。そしてXAudio2のボイスはQueryInterfaceにはIUnknown, IXAPO, IXAPOParametersの取得しか要請しないため、作成したプログラマとユーザが要請しない限り専用のCLSIDは不要である、ということにできます。
といってもXAPO_REGISTRATION_PROPERTIES構造体にはCLSIDを登録する必要があります。面倒なのでCLSID()で初期化すれば良いと思います。自分でQueryInterfaceを使って自作XAPOクラスへ変換しようとしないのが確実であるならば、この方法はオススメだと思います。
[余談というか本題] XAPOクラスを最初から自作とかしんどい
[追記 2011/02/17] ヘッダ名はSampleAPOBaseなのですが、クラス名はCSampleXAPOBaseでした。治しました。
というのは、XAPO_REGISTRATION_PROPERTIESとかを自前で用意したりだとか、無駄にメソッドが多いだとかで辛いです。とは言っても公式で用意されているBaseクラスは/MT, /MTdでコンパイルできない*1のがあったりというのは置いといて、そのBaseクラスをさらにラップしたクラスがありますのでこれをオススメします。
DirectX SDKに付属のサンプルでXAudio2CustomAPOというサンプルにはSampleAPOBase.hというヘッダがあり、CSampleXAPOBaseクラステンプレートというIXAPOParamatersBaseを継承したパラメータを持つエフェクトクラスの高レベルラッパがあります。IXAPOParamatersBaseが要するすべてのメソッドの単純なオーバーライドがされているのでこっちはCSampleXAPOBaseが要求するDoProcessメソッドをオーバーライドするだけです。
さて、自作XAPOクラスをこいつで作ります。必要なパラメータとクラスそのものをテンプレートに渡します。CRTPですね。
#include "SampleAPOBase.h" // 適当なパラメータ struct hoge_parameter { float gain; }; // 継承して作成 class __declspec( uuid("{00000000-0000-0000-0000-000000000000}")) // 面倒だけどCLSIDを要するので適当に付けとく hoge_effects : public CSampleXAPOBase<hoge_effects,hoge_parameter> { protected: void DoProcess( const hoge_parameter& params, FLOAT32* __restrict pData, UINT32 cFrames, UINT32 cChannels ){ // pDataはcFrame * cChannels * 4Byte分のオーディオデータが入っている // XAudio2は内部ではオーディオデータはすべて32bit(4Byte)浮動小数点数で処理されている for( UINT32 i = 0; i < cFrames * cChannels; ++i ) { pData[i] *= params.gain; } } }; // 作成時はCreateInstanceを使うと良い? hoge_effects* p; if( FAILED(hoge_effects::CreateInstance(0,0,&p)) ) { throw std::runtime_error("effect create failed."); }
※2011/02/18 コメントから、CreateInstanceのメソッド名を完全に間違えてました。
CSampleXAPOBaseが内部で__uuidof使ってるので適当にCLSIDはつけておきます。面倒な方はCSampleXAPOBaseのXAPO_REGISTRATION_PROPERTIES構造体の変数の__uuidofを消してCLSID()に書き換えれば動くはずです。
__restrictは最適化のためのキーワードです。CreateInstanceメソッドはstaticメソッドで引数はIXAPO::Initializeメソッドに直接引き渡される引数と、作成したインスタンスを格納するポインタです。ちなみにIXAPO::Initializeはこれを書いてる時点では特に何もしてなかったはずです。そのうち拡張するかもしれないのでこのようなメソッドがある、とMSDNには書かれていました。
後は普通にボイスに渡してパラメータで初期化したりすれば良いだけなので簡単ですね。簡単すぎです。これがMTコンパイルでも通れば…。MSDNに報告してるんですが去年報告して結局改善されなかったので皆さんもMSDNに報告してくれないでしょうか。お願いいたします。
*1:詳しくは僕のツイッター見たりだとかググってみればどこかにあります