1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

🦀ひとりWASM-4とRustでゲームをつくる⚙Advent Calendar 2022

Day 8

ラストのまほう 第8話『WASM-4で効果音を鳴らす』

Last updated at Posted at 2022-12-07

そういえば無音だと少し寂しいので何か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を大きくして音程が上がる感じにして、ATTACKDECAYSUSTEINはゼロにして、Releaseを短めにすることで素早く減衰する感じにしたら、ぴょーんという感じになりました。

wasm4.org_play_sound-demo(iPad Air).png

サウンドをコーディングする

サウンドデモのページのコメント欄に、デモと同じ入力項目のサウンドを作る関数を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くらいにすると、「ドッ」という衝突音みたいな感じ

参考文献

次回予告

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?