WisdomSoft - for your serial experiences.

7.2 サウンド制御

XACT で設定されたサウンドデータを XNA Framework ゲームで再生します。

7.3.1 再生

XACT を用いて作成したプロジェクトを保存し xap ファイルを生成することができれば、これを XNA Game Studio のゲームプロジェクト内にある Content サブプロジェクトに項目として追加することで、画像ファイルなどと同じようにビルド時にコンテンツパイプラインによって処理されます。

図1
図1 XAP ファイルを追加

登録された xap ファイルは、プロジェクトの Content フォルダを参照するため、ウェーブバンクに登録しているファイルも Content フォルダ内に移動させてください。そうでなければ、ビルド時にファイルが見つからないというエラーが発生してしまいます。

ビルドが終了すると、実行ファイルが出力された場所にある Content フォルダ(例えば bin/x86/Debug/Content など)に、XACT プロジェクトのビルド結果として xgs、xwb、xsb という拡張子の 3 つのファイルが生成されています。xgs ファイルは、グローバル設定ファイルと呼ばれ、オーディオ全体の制御を行うオーディオエンジンを生成するために必要となります。xwb ファイルには、ウェーブバンクが含まれています。同様に xsb ファイルには、サウンドバンクが含まれます。

図2 生成されたファイル
図2 生成されたファイル

ゲーム内でサウンドを再生するには、最初に xgs ファイルからオーディオエンジンを作成しなければなりません。オーディオエンジンは Microsoft.Xna.Framework.Audio.AudioEngine クラスで表されます。

Microsoft.Xna.Framework.Audio.AudioEngine クラス.
public class AudioEngine : IDisposable

このクラスのコンストラクタに xgs ファイルを指定し、グローバル設定ファイルへのパスを通します。ウェーブバンクやサウンドバンクを読み込むには、関連するオーディオエンジンが必要となります。

AudioEngine クラスのコンストラクタ
public AudioEngine (string settingsFile)

settingsFile パラメータには、コンテンツパイプラインで生成された拡張子 xgs のグローバル設定ファイルを指定します。

次に、生成したオーディオエンジンからウェーブバンクを読み込みます。ウェーブバンクは Microsoft.Xna.Framework.Audio.WaveBank クラスで表されます。

Microsoft.Xna.Framework.Audio.WaveBank クラス
public class WaveBank : IDisposable

このクラスのコンストラクタには、関連するオーディオエンジンと xwb ファイルを指定します。

WaveBank クラスのコンストラクタ
public WaveBank (
         AudioEngine audioEngine,
         string nonStreamingWaveBankFilename
)

audioEngine パラメータに関連付けるオーディオエンジンを指定し、nonStreamingWaveBankFilename パラメータに読み込む xwb ファイルのパスを指定します。このコンストラクタで読み込むウェーブバンクは、すべてのデータをメモリに読み込む「In Memory」という種類のウェーブバンクでなければなりません。ウェーブバンクには、他に読み込みながら再生する「Streaming」という種類も存在しますが、これについては後述します。

次に、サウンドバンクを読み込みます。サウンドバンクは Microsoft.Xna.Framework.Audio.SoundBank クラスによって表されます。

Microsoft.Xna.Framework.Audio.SoundBank クラス
public class SoundBank : IDisposable

このクラスのコンストラクタも、WaveBank クラスのコンストラクタと同じようにオーディオエンジンと xsb ファイルのパスを指定します。

SoundBank クラスのコンストラクタ
public SoundBank (
         AudioEngine audioEngine,
         string filename
)

audioEngine パラメータに関連付けるオーディオエンジンを、filename パラメータに xsb ファイルのパスを指定します。

前述したように、XACT によってウェーブバンクに登録している音はサウンドバンクによってデザインされ、デザインされたサウンドは最終的にキューに追加されます。ゲームからは、サウンドバンク内のキューを再生することで、実際に音として結果を出力できます。キューを取得して制御する方法もありますが、この場では、もっとも簡単な PlayCue() メソッドによる再生を行いましょう。

SoundBank クラス PlayCue() メソッド
public void PlayCue (string name)

このメソッドは、サウンドバンク内の name パラメータに指定した名前のキューを再生します。再生されたキューを制御することはできないので、途中で停止することはできません。

サウンドに対する要求は、オーディオエンジンによって処理されます。オーディオエンジンが正しくデータを処理するために、ゲームは周期的にオーディオエンジンの Update() メソッドを呼び出さなければなりません。

AudioEngine クラス Update() メソッド
public void Update ()

通常、ゲームの Update() メソッド内でフレームごとにオーディオエンジンの Update() メソッドを呼び出します。このメソッドが呼び出されなければ、サウンドの再生が停止してしまいます。

コード1 (Win, Xbox 360)
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

public class Test : Game
{
    public static void Main(string[] args)
    {
        using (Game game = new Test()) game.Run();
    }

    private AudioEngine audio;
    private WaveBank wave;
    private SoundBank sound;

    protected override void Initialize()
    {
        audio = new AudioEngine("Content/TestAudio.xgs");
        wave = new WaveBank(audio, "Content/TestWave.xwb");
        sound = new SoundBank(audio, "Content/TestSound.xsb");
        sound.PlayCue("Test");
        base.Initialize();
    }

    protected override void Update(GameTime gameTime)
    {
        audio.Update();
        base.Update(gameTime);
    }
}

コード1を実行すると、TestAudio という名前のグローバル設定ファイルからオーディオエンジンを読み込み、TestWave ウェーブバンクと TestSound サウンドバンクを読み込みます。そして、読み込んだサウンドバンク内にある Test キューを再生します。XACT の設定が正しければ、キューに登録しているサウンドが再生されたはずです。

7.2.2 一時停止と再開

サウンドの一時停止や再開、停止などの制御を行うには GetCue() メソッドからキューを表すインスタンスを直接受け取る必要があります。

SoundBank クラス GetCue() メソッド
public Cue GetCue (string name)

name パラメータには、取得するキューの名前を指定します。このメソッドは、指定されたキューを表す Microsoft.Xna.Framework.Audio.Cue クラスのオブジェクトを返します。

Microsoft.Xna.Framework.Audio.Cue クラス
public sealed class Cue : IDisposable

このクラスは、サウンドバンクに登録されている 1 つのキューを表します。取得したキューからは Play() メソッドで再生、Pause() メソッドで一時停止、Resume() メソッドで停止位置から再生を再開、Stop() メソッドで停止できます。

Cue クラスPlay() メソッド
public void Play ()
Cue クラスPause() メソッド
blic void Pause ()
Cue クラスResume() メソッド
public void Resume ()
Cue クラスStop() メソッド
public void Stop (AudioStopOptions options)

Stop() メソッドの options パラメータには、停止方法を表す Microsoft.Xna.Framework.Audio.AudioStopOptions 列挙型のいずれかのメンバを指定します。

Microsoft.Xna.Framework.Audio.AudioStopOptions 列挙型
public enum AudioStopOptions

この列挙型には、Stop() メソッドが呼び出されてキューの再生が停止されるときに、サウンド側でデザインされた停止処理を実行する AsAuthored メンバと、停止の移行処理を無視して強制的にキューを停止する Immediate メンバが定義されています。

XACT から、サウンドのトラックに対して停止時にフェードアウトなどの終了処理を指定できます。Stop() メソッドで AsAuthored メンバを用いて停止した場合、サウンドデザイナが設定した ReleaseTime という変数の情報に従って停止移行処理を行います。一方、Immediate メンバを指定した場合は Stop() メソッドが呼び出された瞬間に再生を停止します。

キューが再生中かどうかは IsPlaying プロパティから取得できます。Pause() メソッドによってキューが一時停止しているかどうかは IsPaused プロパティで確認できます。キューが再生中の場合、一時停止されていても IsPlaying プロパティは true を返します。キューが停止しているかどうかは IsStopped プロパティで確認できます。

Cue クラス IsPlaying プロパティ
public bool IsPlaying { get; }
Cue クラス IsPaused プロパティ
public bool IsPaused { get; }
Cue クラス IsStopped プロパティ
public bool IsStopped { get; }

前述した、停止時にフェードアウトなどの移行処理が発生するキューであれば、キューが停止中かどうかを IsStopping プロパティから取得できます。

Cue クラス IsStopping プロパティ
public bool IsStopping { get; }

キューが再生中の場合、IsPlaying プロパティが true となり、IsStopped プロパティや IsStopping プロパティは false を返します。AsAuthored メンバを指定した Stop() メソッドが実行されると、キューは停止処理を開始し IsStopping プロパティが true になります。このとき、すでに IsPlaying プロパティは false を返すようになります。完全に停止したわけではないので IsStopped プロパティも false を返します。そして、完全に停止した時点で IsStopped プロパティが true を返すようになります。

コード2
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Input;

public class Test : Game
{
    public static void Main(string[] args)
    {
        using (Game game = new Test()) game.Run();
    }

    private AudioEngine audio;
    private WaveBank wave;
    private SoundBank sound;
    private Cue cue;

    protected override void Initialize()
    {
        audio = new AudioEngine("Content/TestAudio.xgs");
        wave = new WaveBank(audio, "Content/TestWave.xwb");
        sound = new SoundBank(audio, "Content/TestSound.xsb");
        base.Initialize();
    }

    protected override void Update(GameTime gameTime)
    {
        GamePadState state = GamePad.GetState(PlayerIndex.One);

        if (cue != null && cue.IsPlaying)
        {
            if (cue.IsPaused && state.Buttons.Y == ButtonState.Pressed)
            {
                cue.Resume();
                Window.Title = "Playing";
            }
            else if (state.Buttons.X == ButtonState.Pressed)
            {
                cue.Pause();
                Window.Title = "Paused";
            }

            if (state.Buttons.B == ButtonState.Pressed)
            {
                cue.Stop(AudioStopOptions.AsAuthored);
                Window.Title = "Stoped";
            }
        }
        else if (state.Buttons.A == ButtonState.Pressed)
        {
            cue = sound.GetCue("Test");
            cue.Play();
            Window.Title = "Playing";
        }

        audio.Update();
        base.Update(gameTime);
    }
}

コード2は、A ボタンを押すと GetCue() メソッドからキューを取得して再生します。その後、Y ボタンを押すと再生中のキューを一時停止し、X ボタンを押すと一時停止しているキューを再開します。B ボタンを押すと、キューを完全に停止します。ゲーム画面には何も表示しません。

7.2.3 ループ再生

一般に、ゲーム場面の演出として流される BGM は、対象の場面が続く限り永遠に再生し続けられます。サウンドデータの最後まで再生されると、再び先頭から繰り返し再生されます。このようなループ再生は BGM だけではなく、風や空調、雨、パーティ会場のざわめき、虫の鳴き声といった環境音の演出でも必要になります。

サウンドの再生回数は、プログラムではなく XACT によるサウンドデザインの段階で設定されます。XACT のサウンドバンクを開き、ループ再生したいサウンドを選択して画面左下に表示された「Looping」グループボックスに注目してください。この中にある「Loop Count」テキストボックスに、再生回数を表す整数を入力できます。デフォルトの設定は 0 で、繰り返し再生をしないことを表します。無限に繰り返す場合は「Infinite」チェックボックスにチェックを入れてください。

図3 Looping の設定
図3 Looping の設定

このサウンドのキューを再生すると、対象のサウンドは明示的に停止するまで永遠と再生を繰り返します。