06
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

XAudio2でエフェクト設定する

TwinTail開発で詰まった事について

単純にどうやってエフェクト設定すればいいの?
という資料があんまり無かった(つまりみんな余裕で分かるでしょって事ですね…)ので
書いておきます。
(今回の実装にそって)

まずCSampleXAPOBase(SampleAPOBase.h内)を使う事前提で話します

こいつはIUnknownを継承していますのでIUnknownにdynamic_cast可能です。
IUnknownっていうのはなんかXAPOで使うほにゃらららしいよく分からん><

で、こいつはDoProcessを実装すればいいという事
GCXAPOEffectがCSampleXAPOBaseを継承したクラスです。
.NetでラッピングしてるだけですねーVoiceはIXAudio2Voiceのラッパ
よくあるイベントの実装もして速度がどんどん落ちるけど開発のしやすさが.Netの利点だからそれは壊したくないと
ユーザーはEffectオーバーライドしてOnDoProcess実装すればいいだけ

(gcrootとかVoice^の^とかdelegateとかはネイティブの人は知らなくて宜しいです)

実装はこんな感じ



public delegate void VoiceEffectEvent(Voice^ voice,array<float>^ data,UINT32 frames,UINT32 channels);

   public ref class Effect
   {

   public:
       event VoiceEffectEvent^ DoProcess;

       ///<summary>ボイスのエフェクトの実装です。dataの要素数はframes*channelsと一致します</summary>
   public protected:
       virtual void OnDoProcess(Voice^ voice,array<float>^ data,UINT32 frames,UINT32 channels )
       {
           DoProcess(voice,data,frames,channels);

       }
   };

   struct XAPOParameter
   {
   };

   class
       __declspec( uuid("{00000000-0000-0000-0000-000000000000}"))
GCXAPOEffect:public CSampleXAPOBase<GCXAPOEffect,XAPOParameter>
   {

       gcroot<Effect^> voiceEffect;
       gcroot<Voice^> voice;
   protected:
       void DoProcess(const XAPOParameter& params,FLOAT32* __restrict pData,UINT32 cFrames,UINT32 cChannels)
       {

           IntPtr pdata(pData);
           UINT32 len=cFrames*cChannels;
           array<float>^ data = gcnew array<float>(len);
           System::Runtime::InteropServices::Marshal::Copy(pdata,data,0,len);
           voiceEffect->OnDoProcess(voice,data,cFrames,cChannels);
           System::Runtime::InteropServices::Marshal::Copy(data,0,pdata,static_cast<int>(len));

       }
   public:
       GCXAPOEffect(Voice^ voice,Effect^ effect)
       {
           voiceEffect = effect;
           this->voice=voice;
       }
       GCXAPOEffect(){}
   };





でVoiceにはこのGCXAPOEffect:public CSampleXAPOBaseを投げるわけ

CSampleXAPOBase
の第一型引数は自分自身(GCXAPOEffect)
第二型引数はDoProcessで使われる構造体だとか。よくわかんないしできてもそれを.Netにつなげるのが難しそうなので空の構造体渡してみた。

ここまでは
CSampleXAPOBase
を継承してDoProcessオーバーライドして実装すればOK

次にこれをvoiceに投げられる形にしてあげる


まず
XAUDIO2_EFFECT_DESCRIPTOR* descriptors=new XAUDIO2_EFFECT_DESCRIPTOR[エフェクト数];
って配列と

XAUDIO2_EFFECT_DESCRIPTOR* descriptor;
ってのを作る(これは各エフェクト毎に必要)

descriptor->InitialState = TRUE;
descriptor->OutputChannels = 2;
は出力に必要なチャネル数(作成時に使用したWAVEFORMATと同じである必要あり)とすぐに適用するかどうか?


でpEffectに作ったエフェクトをキャストして入れればいい
その後 pEffect->Release()を呼ぶともう一度pEffect->Release()を呼んだときにエフェクトが解放されるようになる
なんで他のところでエフェクト使う気がないなら呼んでおく

その後にdescriptors配列に入れていけばOK

の配列をさらに
XAUDIO2_EFFECT_CHAIN型ってのを作って
それのpEffectDescriptorsに入れて
最後にEffectCountに要素数入れて準備完了

後はIXAudio2::SetEffect(XAUDIO2_EFFECT_CHAIN*pEffectChain);
にそれの参照投げれば終わり

走り書きで書いてみた…
眠い…現在午前三時…ぐー
スポンサーサイト

Comment

Secret

検索フォーム

RSSリンクの表示

リンク

リンクというか個人的によく使うアルゴリズムの解説サイト… C#でなかったりする

ブロとも申請フォーム

この人とブロともになる

QRコード

QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。