TETORICA-FM2612 · RUNTIME GUIDE

Runtime の構成と選び方

公開済み npm package のどの API を使うか、アプリ・ゲームへの組み込み方に合わせて選びます。

npm install tetorica-fm2612

チップ別の基本例(npm 0.2.40)

Web: createSoundChip(name, {execution: 'worklet'})
     → WorkletTransport → Synth(Main)→ WASM(Worklet)
Node: createSoundChip(name)
      → AudifyTransport → Synth / WASM(呼び出し元)→ 音声出力

演奏するコードは同じ Synth の API。DirectTransport の PCM / WAV 手順は専用例へ分けています。 MegaSynth はゲームへの埋め込み用の統合 API として別枠に残しています。

FM 発音 · DirectTransport の PCM / WAV

Mixer の音量プリセット

new SoundChipMixer(SOUNDCHIP_MIXER_PRESETS.calibrated) を選ぶと、チップごとの測定と聴感バランス方針による音量倍率を使えます。 createSoundChip(name, {execution: 'worklet', mixer, audioContext}) へ渡して接続します。プリセットの指定は任意です。

個別の Volume / Pan / Mute · 従来値と calibrated の比較

音源を直接操作する

generated/*.js + *.wasm  チップのエミュレーター
          ↓
createSoundChip()        レジスタ・PCM 生成の入口
          ↓
DirectTransport         synth の命令を chip に渡す
          ↓
YM2612Synth など         noteOn / preset / operator
          ↓
generateStereo(frames)   時間を進めて Float32 PCM を生成
          ↓
Web Audio / encodeWav()  ブラウザ再生 / Web・Node の WAV 保存

generateStereo() を呼ぶとチップの時間が進みます。Node では AudioContext や音声ドライバーは不要です。 createSoundChip('ym2612') は Web / Node に応じて WASM を自動読み込みします。

DirectTransport の PCM 生成 · レジスタ直接操作 · PCM / WAV 出力

リアルタイムで組み込む

YM2612WorkletTransport は synth の命令を AudioWorklet へ送り、音声スレッドで PCM を生成します。 processor の読み込み、WASM の転送、ready 待機を自分で扱う例が AudioWorklet の最小例です。

MegaSynthは、その初期化と終了、FM、Web Audio の FX、イベント録音をまとめます。 start() 後に fm を操作し、終了時は close() を呼びます。

発音 + delay / reverb · イベント JSON の録音・再生 · 音符の looper

Playground は liveLoop・play・beat を含むコードを実行します。 load() → play(name, {execution: 'worker'}) でゲームの UI と演奏コードを別スレッドに置けます。 stop() は演奏停止、finalize() は Worker・音声リソースの解放です。

Playground Runtime を組み込む

DX7:Playground の音源

DX7 は Playground の script 内で await useSoundChip('dx7') として生成します。 MIDI ノート番号を指定し、最大16ボイスでメロディと和音を演奏できます。音声生成は Main / Worker のどちらも AudioWorklet 内です。

await dx7.loadSysex(bytes) → dx7.voices → dx7.selectVoice(index) で音色を読み込んで選択します。 ファイル読込みはホストで行い、データを script に渡します。

この API は package root の createSoundChip() と別です。直接 PCM を生成する Node / ブラウザ向けコアは 別 package tetorica-msfa-dx7-wasm の createDX7() を使用します。

DX7 メロディと和音 · SysEx と音色選択

OPL / OPL2 / Y8950 FM / OPL3

OPLSynth の音名・音色APIで4モデルを操作します。Webは createSoundChip(name, {execution:'worklet'}) → OPLWorkletTransport → OPLSynth、Nodeは OPLDirectTransport とPCM生成によるWAV保存です。

0始まりの9CH、OPL3は18CH。OPL3は4-opペアと左右出力に対応します。Y8950の例はFM部分です。

4モデルで基本演奏 · OPL2の音作り · 5種類のRhythm · OPL3の4-opとStereo

Master System / MSX / MSX Audio

AY8910Synth は3CHのトーンと共有ノイズ・エンベロープ、YM2413Synth は9CHのOPLL音色と5種類のRhythmを操作します。 OPLLのUser patchは全User音色CHで共有されます。RhythmモードはメロディーCH6〜8を使います。

単体のWeb例は createSoundChip() → AY8910WorkletTransport / YM2413WorkletTransport → Synth。 合奏例は Playground({chip:'msx'}) の ay と opll、 chip:'msx-audio' ではさらにY8950 FMの opl を使います。Main / Workerの両方で音声生成はAudioWorklet内です。

NodeはDirectTransportで生成した各音源のPCMを共通レートへ変換して混ぜ、WAVに保存します。音声デバイスは不要です。

OPLL音色とPSG · OPLL Rhythm · AYトーンとノイズ · AYエンベロープ · MSX合奏 · MSX Audio合奏

PS1 SPU:ADPCM音色・live ADSR・共有Reverb

encodePs1AdpcmCycle()で112点のPCMをソフトウェア変換し、Ps1Spu/Ps1Synthへ読み込みます。 サンプルの基準音程を明示し、setEnvelope()で鳴っている音のADSRを編集します。

Reverbはvoice別sendと1つの共有effectを組み合わせます。左右returnは独立です。 Webは専用AudioWorklet endpoint、Nodeは44.1 kHzの実SPU PCMをWAVへ保存します。

PCMから音色・ADSR · 共有Reverb。

Saturn SCSP:PCM・LFO・2slot変調

ScspSynthでsigned PCM8/PCM16・forward loop・envelope・mixを操作します。32の物理slotを持ち、内部レートは44.1 kHzです。 setLfo()はpitch/amplitudeのhardware LFOをlive変更し、resetで位相をholdします。

setModulation()はsound stackによるsample address変調です。2slotの例ではfull loopとguard領域を確保します。 X/Y offsetはslot番号ではありません。公開0.2.40の範囲を使い、DSP/SSF/68000は扱いません。

PCM形式とloop · hardware LFO · 2slotの変調。

PCM変換はソフトウェアの前処理

encodeBrr()はS-DSP用BRR、encodeAdpcmA()はYM2610/B用ADPCM-Aを作ります。 チップがPCMを変換するのではなく、ソフトウェアで符号化したデータを実コアが復号します。

Game Boyの比較・preview helperはPCMをWave RAM向けに準備し、独立した実APUで音を確認します。 音源や音声デバイスの寿命も、各例のコードへ明記しています。

PCM → BRR · PCM → ADPCM-A · Game Boy Wave preview。

C64 SID:6581 / 8580 Preview

Web:  createSidAudio(context, gainNode, {model})
      → createSidClient(endpoint.port, endpoint)
      → 3 voice / ADSR / shared filter → AudioWorklet
Node: createSoundChip('sid', {model: '6581'}) // または '8580'
      → new SidSynth({core}) → core.render(frames) → encodeWav()
      専用SidCore.create() / Sid8580Core.create()の例も保持

npm 0.2.40の共通factoryとSID専用APIを使います。両モデルで3ボイスの波形・hardware ADSR・共有LP/BP/HPを試せます。 Cutoffは0〜2047、Resonanceは0〜15のチップコード。選んだfilter出力を同じCutoff/Resonanceで加算します。

Webのモデル変更は新しい音源を作ります。Nodeは48 kHzのmono PCMを左右へ複製して保存します。 同じ音符・同じPAL clockでモデルを比較し、元の12 Hz host DC blockerと固定の出力gainを保ちます。

3ボイス・ADSR・モデル比較 · 共有Filterの音作り · 共通factoryでWAV生成(Node)。 C64 CPUやゲーム曲は使いません。元ソース・license・再build手順もvendor内へコピーします。

PC Engine / HuC6280

Webは Playground({chip:'huc6280'}) の主音源 pce をMain / Workerから操作します。 物理6CH、各32点・5-bit波形、独立した左右Panを使えます。NoiseはCH4・5、LFOはCH1からCH0への変調です。

Nodeは Huc6280AudioEngine と Huc6280DirectTransport を Huc6280Synth へ渡し、 processFrames() で時間を進めてWAVを生成します。音声ドライバーやゲームROMは不要です。

波形とメロディ · NoiseとPan · ハードウェアLFO

PC Engine CD-ROM² / CD-DA / MSM5205

Webは Playground({chip:'huc6280', pcEngineCd:true}) の pce・adpcm・cdda をMain/Workerで操作します。 HuC6280、MSM5205、CD-DAには独立したMixer入力があり、同じAudioContextの時計で再生します。

CD-DAは44.1 kHz stereo PCM16 WAVとtrack manifestを受け付けます。 MSM5205はPCM/WAVを4-bit ADPCMへ変換し、64 KiB RAMから再生します。範囲はnibble単位、rateは0〜15です。

Nodeは createCddaOffline({sources}) と同期PCMエンジンを組み合わせ、 共通の48 kHzフレーム時計でWAVへ保存します。音声デバイスは不要です。 これらは createSoundChip() とは別の音声APIです。

CD-DAのトラック操作 · ADPCMのサンプル変換 · 3系統の合奏

WonderSwan

createSoundChip('wonderswan', {execution:'worklet'}) → WonderSwanWorkletTransport → WonderSwanSynth。 物理4CH、32点・4-bit波形、左右Volumeを使い、VoiceはCH1、SweepはCH2、NoiseはCH3を使用します。

Voice PCMはunsigned 8-bitのデータを事前に作り、transport.scheduleWrites() へ絶対AudioContext秒・絶対レジスターアドレスでまとめて予約します。 音声スレッドが時刻どおりにレジスターを書き、JavaScriptタイマーで各バイトを送る必要はありません。

NodeはDirect factoryとWonderSwanDirectTransportでPCMを生成してWAVに保存します。Webの中心値補正と異なり、Node例はraw DACのDC成分を残します。

4CHの波形とメロディ · NoiseとSweep · 時刻付きVoice PCM

POKEY / Dual POKEY

createSoundChip('pokey', {execution:'worklet'}) → PokeyWorkletTransport → PokeySynth。 物理4CHの矩形波・Noise、共有polynomial・clock・結合タイマーを操作します。結合時は下側がtimer helper、上側のCHが発音します。

Dual例は独立したPOKEYを2台生成します。それぞれ4物理CHとmono出力を持ち、4+4CHの音声をホストで加算します。

NodeはDirect factoryのコアを PokeyAudioEngine へ渡し、Synthの書き込みもengineを経由させて processFrames() でWAVを生成します。 Webと同じ10 Hz DC blocker、明示的な出力gain 0.25を使い、音声デバイスや実時間待機は不要です。

4CHのメロディ · Noiseと結合タイマー · 2台・8CHの演奏

SNES / SPC(実験的実装)

楽器として使う useSoundChip('snes') は、SPC700 CPU を実行しない独立した S-DSP です。 BRR を明示的な基準音程で登録し、0〜7 の固定チャンネルに音色を割り当てて演奏します。 Web は Playground の Main / Worker、Node は SnesDspCore と SnesSynth で PCM を生成します。

SPC ファイルの楽曲再生には CPU と DSP の両方を動かす SpcCore を使用します。 ブラウザ再生は SpcRuntimeSynth が AudioWorklet と出力側のリサンプリングを担当します。 どちらも内部は 32,000 Hz のステレオで、音声デバイスの 44.1 / 48 kHz や BPM と別の値です。

これらは package root の Yamaha 向け createSoundChip() とは別の入口です。 実ゲーム由来 SPC、Tauri、長時間再生の互換性は確認を継続中です。ゲーム音楽や Nintendo IPL ROM は同梱しません。

BRR のメロディと和音 · SPC ファイルを再生

VGM と音色ファイル

VgmPlayer は VGM のコマンドと待ち時間を処理し、GenesisAudioEngine が YM2612 + Sega PSG の PCM を生成します。 VgmRuntime はブラウザの読み込み・再生・一時停止・停止・音声出力をまとめます。 VGM の出力 Worklet は生成済み PCM を再生する方式です。チップを音声スレッドで動かす synth Worklet とは役割が異なります。

VGM 再生(Web / Node)

tfi.js と vgi.js は音色バイナリを logical preset に変換します。 operator 番号は 1〜4。fm.setPreset() に渡して発音し、同じ形式へ export できます。

TFI import / export · VGI import / export

API を探す

機能 → import パス → 主な API の一覧から入口を選べます。 例えば音程変換は import {hzToBlockFnum} from 'tetorica-fm2612/pitch.js' です。

引数・options・戻り値は、インストール済み package の .d.ts / .d.mts とエディターの補完・定義へ移動で確認できます。 例えば node_modules/tetorica-fm2612/pitch.d.ts を参照してください。

ブラウザでの配置と実行環境

この examples は import map で tetorica-fm2612 の bare import を、コピーした npm package へ解決します。 npm run dev と npm run build が package の JS・WASM・Worker・Worklet・ライセンスを vendor に配置します。 自分のアプリでも package 内の相対配置を保ち、runtimeAssetUrl() で必要なアセットの URL を取得します。

個別の Sega PSG・Game Boy・OKIM6258 ラッパーや VgmRuntime は、生成済みローダーと WASM バイト列を渡す API を使います。 MegaSynth / Playground は Worklet と WASM の URL を指定します。具体的な手順は各例のソースに省略せず記載しています。

ブラウザでは HTTP サーバーで配信し、AudioWorklet は HTTPS または localhost で実行します。 音声は Play などのユーザー操作から開始します。Node は22以降に対応します。 Web Audio を使う埋め込み例は Web 専用、PCM 生成・WAV 出力・音色変換は Node でも実行できます。

npm run build の dist/ を静的ホストに配置できます。GitHub Pages の repository 配下でも相対 URL で動作します。

配布物には RUNTIME.md、soundchip.md、runtime-manifest.json、 THIRD_PARTY_LICENSES.txt、licenses/、sources/ が含まれます。 Package の説明・APIも参照してください。