DirectXTKとAudio
Step 00 DirectXTK Audio の基本
この回の目的
この回では、DirectXTK Audio で使う基本的なクラスの役割を整理します。
音を鳴らすプログラムでは、いきなりコードを書く前に、次の3つを分けて考えることが大切です。
AudioEngine … 音を鳴らす仕組み全体
SoundEffect … 音声ファイル1個分のデータ
SoundEffectInstance … 実際に再生中の音
この3つの違いが分かると、DirectXTK Audio のコードがかなり読みやすくなります。
1. DirectXTK Audio で音を鳴らす流れ
DirectXTK Audio では、おおまかに次の流れで音を鳴らします。
AudioEngine を作る
↓
SoundEffect で wav ファイルを読み込む
↓
SoundEffect::Play() で音を鳴らす
一番単純な考え方は、これです。
AudioEngine … 音を鳴らす機械本体
SoundEffect … wav ファイルを読み込んだ音の素材
Play() … その音を鳴らす命令
2. AudioEngine
AudioEngine は、DirectXTK Audio の中心になるクラスです。
std::unique_ptr<DirectX::AudioEngine> audioEngine_;
AudioEngine は、音を鳴らすための仕組み全体を管理します。
簡単に言うと、
AudioEngine = 音を鳴らす機械本体
です。
これがないと、音声ファイルを読み込んでも音を鳴らすことができません。
3. SoundEffect
SoundEffect は、音声ファイル1個分のデータを表します。
std::unique_ptr<DirectX::SoundEffect> sound_;
例えば、次のような音声ファイルを読み込んだものです。
shot.wav
jump.wav
damage.wav
実際のコードでは、次のように作ります。
sound_ = std::make_unique<DirectX::SoundEffect>(
audioEngine_.get(),
L"Assets/Audio/shot.wav"
);
イメージとしては、
SoundEffect = 音の素材
です。
短い効果音であれば、SoundEffect の Play() を呼ぶだけで再生できます。
sound_->Play();
4. SoundEffectInstance
SoundEffectInstance は、実際に再生中の音を表します。
std::unique_ptr<DirectX::SoundEffectInstance> instance_;
SoundEffectInstance は、SoundEffect から作ります。
instance_ = sound_->CreateInstance();
イメージとしては、次のようになります。
SoundEffect = 音の素材
SoundEffectInstance = 実際に鳴っている音
例えば、engine.wav というエンジン音があったとします。
engine.wav
これは音の素材なので、SoundEffect として読み込みます。
その音を実際に鳴らしながら、あとから音量を変えたり、止めたり、ループさせたりしたい場合は、SoundEffectInstance を使います。
instance_->Play(true);
instance_->SetVolume(0.5f);
instance_->Stop();
5. SoundEffect と SoundEffectInstance の違い
ここが一番大切です。
| クラス | 役割 | 向いている使い方 |
|---|---|---|
SoundEffect |
音声ファイルのデータ | 短いSEを鳴らす |
SoundEffectInstance |
再生中の音 | BGM、ループ音、音量変更、停止、一時停止 |
6. 短い効果音なら SoundEffect::Play()
例えば、弾を撃つ音です。
shotSound_->Play();
これは、
鳴らす
↓
終わったら自動で終わる
という使い方です。
この方法に向いている音は、次のようなものです。
ジャンプ音
攻撃音
決定音
ダメージ音
爆発音
何度も重なって鳴ってもよい音に向いています。
7. 止めたり音量を変えたいなら SoundEffectInstance
例えば、BGMです。
bgmInstance_ = bgmSound_->CreateInstance();
bgmInstance_->Play(true);
BGMは、あとから操作したくなることが多いです。
bgmInstance_->SetVolume(0.5f);
bgmInstance_->Pause();
bgmInstance_->Resume();
bgmInstance_->Stop();
この方法に向いている音は、次のようなものです。
BGM
足音ループ
エンジン音
環境音
3D空間で鳴らす音
8. たとえで考える
次のように考えると分かりやすいです。
AudioEngine
→ 音を鳴らすゲーム機本体
SoundEffect
→ wav ファイルを読み込んだ音の素材
SoundEffectInstance
→ 今、実際に鳴っている音
または、音楽プレイヤーにたとえると、こうなります。
AudioEngine
→ 音楽プレイヤー本体
SoundEffect
→ 音楽ファイル
SoundEffectInstance
→ 実際に再生中の曲
9. なぜ SoundEffect だけではだめなのか
短い効果音だけなら、SoundEffect::Play() で十分です。
shotSound_->Play();
しかし、次のようなことをしたい場合は、SoundEffect だけでは扱いにくくなります。
ループさせたい
途中で止めたい
一時停止したい
再開したい
音量を少しずつ変えたい
3D空間の位置を反映したい
このような場合は、SoundEffectInstance を使います。
10. SoundEffectInstance を使うときの注意
SoundEffectInstance は、元になった SoundEffect の音データを使います。
つまり、次のような関係です。
SoundEffect
└─ SoundEffectInstance
そのため、SoundEffectInstance を使っている間に、元の SoundEffect を先に消してはいけません。
危険な順番はこれです。
SoundEffect を先に消す
↓
SoundEffectInstance が使う音データがなくなる
↓
正しく動かない可能性がある
安全な考え方は、次の順番です。
作る順番
AudioEngine
↓
SoundEffect
↓
SoundEffectInstance
消す順番
SoundEffectInstance
↓
SoundEffect
↓
AudioEngine
11. 今回作るオーディオエンジンでの使い分け
今回のオーディオエンジンでは、次のように使い分けます。
SE
SEは SoundEffect を使います。
Audio::LoadSE("shot", shotPath);
Audio::PlaySE("shot");
内部では、次のような処理になります。
sounds_["shot"]->Play();
SEは短く、鳴らしたら終わるものが多いからです。
BGM
BGMは SoundEffectInstance を使います。
Audio::LoadBGM("stage", bgmPath);
Audio::PlayBGM("stage", true);
Audio::StopBGM();
内部では、次のような処理になります。
bgmInstance_ = bgmSound_->CreateInstance();
bgmInstance_->Play(true);
BGMはループさせたり、止めたり、音量を変えたりしたいからです。
12. 最初に覚えること
最初は、これだけ覚えれば大丈夫です。
AudioEngine は、音を鳴らす仕組み本体。
SoundEffect は、wav ファイルを読み込んだ音データ。
SoundEffectInstance は、再生中の音を操作するためのもの。
使い分けは、次のように考えます。
短いSE
→ SoundEffect::Play()
BGM、ループ音、3D音、音量操作したい音
→ SoundEffectInstance
確認問題
問題1
AudioEngine は何をするためのクラスですか。
答え:
問題2
SoundEffect は何を表しますか。
答え:
問題3
BGMのように、ループさせたり止めたりしたい音には、SoundEffect と SoundEffectInstance のどちらを使うとよいですか。
答え:
問題4
短いジャンプ音を1回鳴らすだけなら、次のどちらが向いていますか。
A. SoundEffect::Play()
B. SoundEffectInstance を作って管理する
答え:
No Comments