SEGA SOUND / INTRODUCTION

JavaScriptでMega CDのRF5C164を鳴らす

波形をメモリーへ入れ、読む速さと左右の音量を変える。PCM音源の基本を、動くコードで試します。

このページの試し方

各例のRunで再生、Stopで停止します。コードの値を一つ変えて、もう一度Runして聴き比べてください。再生は自動では始まりません。比較するときは、先にもう一方の例をStopしてください。

サンプルは最後に音源を解放する短い演奏です。実機のスピーカーやアンプの音色を再現するものではありません。

音を合成する代わりに、波形を読む

Sega Mega CDのRF5C164は、波形RAMから音のデータを読み、最大8チャンネルで再生するPCM音源です。64 KiBのRAMをチャンネル間で共有し、各チャンネルに開始位置・ループ位置・再生速度・音量・左右出力を設定します。

CDの音楽トラックを再生するCD-DAとは別の機能です。このページでは、外部ROMやゲームから取り出した音を使わず、自作のサイン波をRAMに入れて鳴らします。

1. 波形を入れて、ループ再生する

256点で1周期のサイン波を生成します。loadMemory()でチップ形式のバイトを転送し、keyOn()で再生。stepForHz(440)を220に変えると、同じデータをゆっくり読んで約1オクターブ低く鳴らします。

loadMemory()へ渡す配列はWAVファイルのバイト列ではありません。WAV / FLACを使う場合のloadSample()とは区別してください。

このコードを別タブのPlaygroundで編集 ↗

2. 同じ波形で、音程と左右を変える

左に440 Hz、右に660 Hzを目標にした設定で1秒鳴らし、その後左だけを約220 Hzに下げます。この波形とコアでの実測は左が約440 Hz、右が約651 Hzです。左右で違う音程が聞こえることと、ピッチ変更時もRAMを転送し直さないことを確かめます。

panのleft / rightはそれぞれ0〜15のレベルです。0はその側へ出力せず、15は最大です。イヤホンなどで左右を分けて比較できます。

このコードを別タブのPlaygroundで編集 ↗

波形の形式と、再生する速さ

設定意味
start開始RAMアドレス。256 byte境界。
loopStart0xffのマーカーを読んだときに戻るRAMアドレス。
step16 bitのアドレス進み幅。小数部11 bit。2048で内部更新1回に1 byte進みます。
volume0〜255のチャンネル音量。
pan左右それぞれ0〜15の出力レベル。

波形の1 byteはbit 7が符号(1が正)、下位7 bitが振幅です。0xffはループマーカーなので、正の最大波形値として使いません。この例の振幅は100に抑えています。

内部更新レートはclock / 384(このランタイムの既定12.5 MHzでは約32.55 kHz)。PCM出力の48 kHzなどのレートとは別です。再生速度が速いとRAMアドレスを飛び越すため、この例では末尾に8 byteのマーカーを並べ、220〜660 Hzの比較でループを検出できるようにしています。

stepForHz()は256点が1周期の波形に合わせた近似です。任意の録音サンプルでは、その元の音程と長さを考えて再生速度を決めます。setPitch()に渡す数値はMIDI番号でもHzでもなく、rawのstepです。

awaitはブラウザーの音源へ転送・設定が届くのを待つために使います。sleep()はJavaScript側の発音時間です。サンプルは最後にdispose()で解放します。