そういえば無音だと少し寂しいので何かBGMを流したいです。あと、ジャンプしたときなどに効果音があるとゲームとして雰囲気が出てきそうな気がします。
筆者が以前ゲームを作っていたときは素材サイトからフリーの効果音を借りてきて使っていたのですが、WASM-4の場合はそういう現実の音を録音したサンプリング音源を流す機能はありません。ゲームボーイのような古いハードウェアは、サンプリング音源を乗せるメモリも無ければ、それを処理する強力な汎用CPUもありません。矩形波や三角波のような単純な波形を生成するサウンド専用ハードウェアを組み込んで、それを操作することで音を鳴らしていたらしいです。
WASM-4ではゲームボーイのサウンドを模したようなシンプルな機構があり、矩形波や三角波を音声として出力できるほか、ノイズを出力できます。矩形波はトランペットやエレキギターのような華やかではっきりした音が出ますし、三角波は比較的柔らかいストリングス系のような音がします。パーカッションにはノイズを流すといい感じになるみたいです。
tone
関数
WASM-4のサウンド関連の関数は、次のtone関数1個だけです。シンプルってレベルじゃねーぞ!
tone (frequency: i32, duration: i32, volume: i32, flags: i32)
-
frequency
周波数、つまり音の高さです。単位は hz.また、上位16ビットと下位16ビットで別々に指定することができ、連続的に変化させることができます。 -
durations
音の長さ。単位はフレーム、つまり1/60秒。4ビットづつ、アタック、ディケイ、サスティン、リリースの長さを指定できます。 -
volume
音の大きさ。0から100。上位16ビットと下位16ビットで、サスティンとピークを指定できます。つまり、音が立ち上がった瞬間の音量と、音を引き伸ばしているときの音量を指定できます -
flags
チャンネル(0-3)とデューティ比(0-3)、パン(0-2)を指定するフラグ。チャンネルは 1:矩形波1、2:矩形波2、3:三角波、4:ノイズで、波形を指定します。デューティ比は簡単にいえば波形を変化させるもので、少し音質が変わります。パンは左右のどちらから音を出すかを指定します。
アタック、ディケイ、サスティン、リリースについては、WASM-4以外でもよく使われる一般的な仕組みです。このあたりの図を見るとわかりやすいです。
波形とかデューティ比について細かく話し始めると、ただでさえ過酷なひとりアドベントカレンダーが地獄になってしまうので割愛させていただきます。まあいろいろパラメータを変えると音質が変わるとだけ理解しておけばOKです。
サウンドデモで音作り
理屈だけ頭に入れても、実際にどんな音がなるのかはやってみないとわかりません。あとは以下の公式デモでいろいろ試して好みの音を探っていくのが良さそうです。
とりあえずジャンプの効果音をつけたいので、どうにかして「ぴょーん」という感じの効果音を作ってみます。筆者はもちろんこの種のサウンドプログラミングなどしたことがないので、勘で音を作ってみます。
なんかFREQ1
よりFREQ2
を大きくして音程が上がる感じにして、ATTACK
、DECAY
、SUSTEIN
はゼロにして、Release
を短めにすることで素早く減衰する感じにしたら、ぴょーんという感じになりました。
サウンドをコーディングする
サウンドデモのページのコメント欄に、デモと同じ入力項目のサウンドを作る関数をGoで書いてくれた兄貴がいたので、これをRustに移植して使います。
use crate::wasm4;
pub struct Sound {
pub freq1: u32,
pub freq2: u32,
pub attack: u32,
pub decay: u32,
pub sustain: u32,
pub release: u32,
pub volume: u32,
pub channel: u32,
pub mode: u32,
}
pub fn play(sound: Sound) {
let freq = sound.freq1 | sound.freq2 << 16;
let duration = sound.attack << 24 | sound.decay << 16 | sound.sustain | sound.release << 8;
let flags = sound.channel | sound.mode << 2;
wasm4::tone(freq, duration, sound.volume, flags);
}
とはデモで作ったパラメータをそのまま設定すればOKです。
play(Sound {
freq1: 490,
freq2: 750,
attack: 0,
decay: 0,
sustain: 0,
release: 31,
volume: 18,
channel: 68,
mode: 1,
})
これでぴょーんという音が鳴りました。簡単ですね。実際にどういう音になったかは、このゲームの最新のデモを見てください。
他にもいろいろ試してみました。
- チャンネルを3(ノイズ)にしてサスティンを10くらいまで下げ、周波数を100から1000まで一気に上げる→「ズシャッ!」という斬撃みたいな感じ
- チャンネルを3(ノイズ)にしてアタックやディケイを長めに取り、周波数を900くらいにする→「シャー……」という波打ち際の音みたいな感じ
- チャンネルを2(三角波)にして周波数を500から100くらいまでゆっくり下げると、「ヒューン」という落下音みたいな感じ
- チャンネルを3(ノイズ)にして周波数は100~200くらい、リリースだけを10くらいにすると、「ドッ」という衝突音みたいな感じ
参考文献
次回予告