ISound/CDirectSound/CDirectMusic/CSound




サウンドの再生の基底クラスは、ISoundです。
サウンドというのは、wav,mp3,ogg,mid..等を指します。

ただ、再生するためのクラスは(拡張子ごとに)それぞれ異なります。

そこで、再生するファイル名がわかった時点で、そのファイルを再生するためのクラスのインスタンスを生成する必要があります。

これは、CSoundFactoryというクラスが担います。

CSoundFactoryの詳しい実装については、「やね本1」で書きましたが、以下のことに注意する必要があります。

1.wavの再生にはDirectSound(⇒yaneSDK3rdではCDirectSoundというクラス)を用いる
2.MIDIの再生にはDirectMusicかMCIを用いる
3.DirectMusicは再生周波数を変更したりするために初期化の際にDirectSoundのポインタが必要
4.3.により、factoryは、DirectSoundとDirectMusicを必要に応じて生成する必要があり、かつDirectMusicを生成するときは、あわせてDirectSoundも生成しなければならない

ということです。

まあ、まどろっこしいことは忘れて、ISurfaceに対して、CPlaneを用意したの同様、ISoundに対してCSoundというのを用意してあります。

list-1 CSound
 class CSound {
/**
    smart_ptr<ISound> といちいち書くのは面倒極まりないので..

    ※
        ISurfaceに対するCPlaneと同じ。
        ISoundに対してはCSound。
*/
public:

    LRESULT Load(const string& strFileName);
    /// ↑このファイル(wav,mp3,mid,ogg..)を読み込む

    /// ポインタのふりをするための仕掛け
    ISound& operator*() const  {return *get(); }
    ISound* operator->() const {return get();  }

    /// ISurfaceへの暗黙の変換
    operator ISound* () const { return get(); }

    /**
        Null Check
            loadに失敗すれば、このクラスの抱えているポインタsmart_ptr<ISound>は
            Nullになるので、それを検出する。
    */
    bool    isNull() const { return p_.isNull(); }

    ISound* get() const { return p_.get(); }

    static void SetFactory(smart_ptr<ISoundFactory>&pFactory)
        { pFactory_ = pFactory; }
    static smart_ptr<ISoundFactory> GetFactory()
        { return pFactory_; }

protected:
    smart_ptr<ISound> p_; // p_; ←って泣いてるの?

    static ThreadLocal<smart_ptr<ISoundFactory> > pFactory_;
};


このクラスを用いれば、

list-2 CApp.h
class CApp : public CAppFrame {
public:
    virtual void    MainThread();   //  これがメインスレッド

protected:
    CSoundFactory   soundFactory_;
};


などと書いておけば、以降、サウンドが使いたいときは、単にCSoundと書くだけで良いわけです。(CSoundFactoryがコンストラクタで、CSound::SetFactoryを行ないます)

list-3
    CSound sound;
    sound.Load("moemoe.wav");
    //  ↑この時点で、自動的にwavファイルを再生するためのクラスが生成される

    if (!sound.isNull()) {
        sound->Play();
        //  ↑生成されたインスタンスに対して再生
    }


CSound::Loadのときに、CSoundFactoryから、再生に必要なインスタンスを生成します。
生成されたインスタンスは、smart_ptr<ISound>としてCSoundが保持します。

枠-1
        sound->Play();


は、CSoundが、このsmart_ptr<ISound>に委譲します。(以下の部分)

枠-2 CSound
    ISound* operator->() const {return get();  }