音楽を再生する。(ストリーミング再生?)

久々にXNAの話題です。
ゲームに欠かせないのは音楽!というわけで、XNAでの音楽の鳴らし方を俺的まとめ。
メモリに全部読み込んで再生する方法はぐぐったら結構出てきたので、ここではストリーミング再生をする方法を紹介します。
(まあ、これが正しいのかどうかはわかりませんが…)


【STEP 1:XACTでXNA用にサウンドファイルを変換】
まずは、WAV等をXNA用のサウンドファイル(*.xap)に変換します。
そのために必要なソフトがMicrosoft Cross-Platform Audio Creation Tool(XACT)です。
まあ、XNA Game Studioに入ってますので、ご心配なく。
XACTの使い方は、以下サイトが詳しいです。
[ソーサリーフォース:XNAサウンドを再生するためのファイルを作る]
http://sorceryforce.com/xna/tips_createsoundfile.html
で、ストリーミング再生する場合は、作成したファイルのWaveBankのTypeをStreamingにしておく必要がありますので、お忘れなく。


【STEP 2:プロジェクトに作成した*.xapファイルを組み込む】
STEP 1で作成したファイルをプロジェクトのContent以下に組み込みます。
ちなみに、私はContent配下にsoundsというフォルダを作って、その中に*.xapファイルを入れてます。


【STEP 3:コーディング!】
問題はここからです。
私はかなり詰まったんですよー。
とりあえず一番簡単なコードを。(緑色のところが追加したコードです。)

namespace SoundPlaySample
{
	public class Game1 : Microsoft.Xna.Framework.Game
	{
		GraphicsDeviceManager graphics;
		SpriteBatch spriteBatch;

		AudioEngine audioEngineMusics = null;
		WaveBank waveBankMusics = null;
		SoundBank soundBankMusics = null;

		public Game1()
		{
			graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
		}

		protected override void Initialize()
		{
			// TODO: Add your initialization logic here
			this.audioEngineMusics = new AudioEngine(@"Content\soundPlaySample.xgs");
			this.soundBankMusics = new SoundBank(this.audioEngineMusics, @"Content\soundPlaySample.xsb");
			this.waveBankMusics = new WaveBank(this.audioEngineMusics, @"Content\soundPlaySample.xwb", 0, 1024);
			this.audioEngineMusics.Update();
			this.soundBankMusics.PlayCue("sample");

			base.Initialize();
		}

		protected override void LoadContent()
		{
			// Create a new SpriteBatch, which can be used to draw textures.
			spriteBatch = new SpriteBatch(GraphicsDevice);

			// TODO: use this.Content to load your game content here
		}

		protected override void UnloadContent()
		{
			// TODO: Unload any non ContentManager content here
		}

		protected override void Update(GameTime gameTime)
		{
			// Allows the game to exit
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
				this.Exit();

			// TODO: Add your update logic here
			this.audioEngineMusics.Update();

			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime)
		{
			GraphicsDevice.Clear(Color.CornflowerBlue);

			// TODO: Add your drawing code here

			base.Draw(gameTime);
		}
	}
}

ポイントは以下の通りです。

  1. WaveBankのコンストラクタを呼ぶ際に、第3,4引数を付けること。(詳細はhttp://msdn.microsoft.com/ja-jp/library/bb195735(XNAGameStudio.20).aspxを参照)
  2. インスタンス作成後、「soundBankMusics.PlayCue」実行前に一度「audioEngineMusics.Update()」を実行すること。
  3. Update毎に「audioEngineMusics.Update()」を実行すること。

以上のどれかが欠けると、エラーになってしまいます。
まあ、ヘルプ読むとちゃんと書いてあったりするんですが、そこまで読むのは面倒っちゃ面倒なんで。


ストリーミング再生をすることで、メモリ使用量は節約できますが、ディスクIOは増えてしまいますので、一長一短なんですよね〜。
まあ、適材適所で使い分けていければいいのかなーと思います。