BGとスプライトを使ってパッド操作も出来るようになったので、次は音楽・・・の前に効果音を出してみます。
SGDKで音楽を流したり効果音を出す方法を調べてみると迷って悩みます。というのも、音(音楽)を出す方法がいくつかあり、どれがどういうものなのか、私のようなSGDKプログラミング初学者にはよくわからないのです。 SGDK付属のサンプル(sound)が優秀で非常に参考になるのでエミュレータで実行してみるとよいです。ただ、それぞれの音楽ドライバ違いがよくわかってません。
こうしてみると、XGM driverを使うのがよさそうです。
メガドラの音源はFM音源6ch YM2612とPSGだかDCSGのSN76489ですが、XGM driverでは、YM2612を使ってVGM形式の曲データとPCM再生をするようです。YM2612はCH6をPCM用に使えるので、FM 5ch + PCMという構成になります。PCM出力はXGM Driverがソフトウェアで音を合成することでPCM 4ch出力ができるっぽいですね。
PSG(DCSG)を使って効果音を出すとか出来ないんでしょうかね、よくわかりません。
まずは出したい効果音をWAVファイルで用意します。別に効果音じゃなくても音声でも音楽でもなんでもいいです。WAVファイルのフォーマットは、14KHz, 8bit, モノラルにしておきます。あとsignedです。
こんな音です→R09_0001_SE_14K.wav
リソース定義のファイル(resources.resとか)に一文追加します。
WAV se1_14k "R09_0001_SE_14K.wav" 5
画像を定義した時は
IMAGE block16_image "block16.png" -1
としましたが、それと同じです。
ところで、リソース定義の最後の数字ですが、これまで理解せずに使ってきました。詳しい事はSGDKのbin/rescomp.txtに書かれていますが、WAV形式のリソースをXGM Driverで使う時には5を指定するという決まりです。リソースの扱いについてはまたいずれ詳しく調べてみようと思います。
プログラム本体はこんな感じです。
#include#include "resource.h" int main() { u16 pad0 = 0, pad1 = 0; while(1) { pad1 = JOY_readJoypad(JOY_1); if ( (pad1 & BUTTON_A ) && !(pad0 & BUTTON_A) ) { SND_setPCM_XGM(64, se1_14k, sizeof(se1_14k)); SND_startPlayPCM_XGM(64, 10, SOUND_PCM_CH1); } pad0 = pad1; VDP_waitVSync(); } return (0); }
パッドのAボタンを押すと効果音が鳴ります。いつものことながら簡単ですね。使った関数は2つです。
XGM driverを使ってPCM再生をするには、まず、SND_setPCM_XGM()でデータを定義します。第一引数のidは効果音に割り当てるIDで、この番号を使ってPCM再生をします。IDに指定できる値は64から255です。似た関数にSND_setPCMFast_XGM()というのがあり、こちらの方が高速に動作するみたいです。
PCMの再生指示はSND_startPlayPCM_XGM()を使います。引数はSND_setPCM_XGM()で設定したIDと、プライオリティとPCMチャンネル番号です。プライオリティは、すでに同じチャンネルを使って音を出している時に意味を持ち、プライオリティ値の高い方(15が最高で0が最小です)が優先されて再生されます。
上記のサンプルを動作させてみたところ、ボタンを連打するとちゃんとPCMが重なって再生されました。みんなも16連打してみよう!→再確認したら重なってませんでした・・・。再生し直しになります。
SGDKのbinフォルダにxgm.txtというファイルがあり、そこにドライバの仕様について書かれていました。ざっと箇条書きします。
最初、PCMファイルは32KByteが上限かと思っていたのですが、32KByte以上のPCMファイルも再生できました。今のところ、140KByteほどのPCMファイルが再生できる事を確認済みです。ただ、10秒程度で140KByte、1MビットのROMを超えるサイズになりますから実用性はまるでないです。
PSG用の曲データをどうやって作るのかとかどうやって鳴らすのとか疑問はありますが、FM 5ch + PCM 4chを使いこなしてから改めて調べてみます。