SID / FILTER / INTRODUCTION

SIDのフィルターで音の明るさを変える

同じノコギリ波を鳴らしたまま、出てくる音の成分を変える。設定をJavaScriptへ持ち出すところまで試します。

MOS 6581 · PAL · Tetorica approximation

小さな聴き比べの実験

まずBypassで単音を鳴らし、そのまま操作します。3CHとも同じSaw設定です。和音のチェックはCH2・CH3を追加し、CH1は鳴らしたままです。「設定を戻す」は初期設定へ戻します。「停止」はソフトウェア側で出力をフェードして音源を解放します。

共有Filterへ送るCH

Bypass中は全CHが直接出力されます。Filterの出力を選ぶと、チェックしたCHをFilterへ送ります。

停止中です。「音を鳴らす」を押すまで再生しません。

出力のSpectrum
縦軸は−90〜0 dBFSで固定、横軸は20 Hzから最大20 kHzまでの対数目盛です(出力サンプルレートの半分が上限)。このページの固定Gainを通ったブラウザー出力を測ります。実機SIDの校正測定ではありません。

1. 音符はそのまま、Filterの出力を変える

ノコギリ波には、基音とそれより高い倍音が含まれます。Filterは、その成分のバランスを変えます。出力を切り替えても、発振器に設定した音程は変えていません。

  1. Bypassのまま音を鳴らすを押します。元のSaw音とSpectrumを確かめます。
  2. LPを選び、Cutoffを1200付近から200付近へゆっくり下げ、戻します。Spectrumの高い周波数側を見比べてください。
  3. Cutoffを固定し、BPとHPも試します。音量だけでなく、どの周波数の成分が残っているかに注目します。
出力聴き比べるところ
Bypass各CHがFilterを通らず、直接出力へ進みます。
LP · ローパス低い周波数側が残りやすく、Cutoff付近より高い成分が減ります。
BP · バンドパスCutoff付近の帯域が残りやすくなります。
HP · ハイパス高い周波数側が残りやすく、低い成分が減ります。

どのモードでもSIDのVolumeとページのGainは同じです。出力の音量はモードによって異なり、自動でそろえていません。極端な設定では、GateがOnのままでも音がとても小さくなることがあります。

2. CutoffとResonanceを分けて試す

LPを選び、まずResonanceを0にします。Cutoffで通し方の変わる境目を動かします。次にCutoffを500付近へ固定し、Resonanceをゆっくり上げてください。その付近の強調と、音量の変化を見比べます。

CutoffはSIDの11 bitの設定値で0〜2047、Resonanceは4 bitで0〜15です。どちらも百分率ではありません。このページでは、Cutoffのコードを正確なHzの値として表示しません。

この実験はTetoricaの6581・PAL近似モデルで動きます。経路や設定項目はSIDに対応し、音声はデジタルの近似で生成します。実機の6581には個体や外付けFilter部品による違いがあります。ここでは、このモデルの変化を比較し、一つのコードに共通のHz値を決めつけないようにします。

3. 3CHで一つのFilterを共有する

CH2 / CH3を重ねるをチェックし、LPで3CHともFilterへ送ります。一つのCutoffと一つのResonanceが、送られた複数の音に共通して働きます。

  1. CH2のチェックだけを外します。CH2は直接出力へ、CH1・CH3はFilterへ進みます。
  2. Cutoffを動かし、直接の音とFilterを通る音が重なる様子を聴きます。
  3. CH2を戻すと、3CHとも同じFilterへ入ります。全チェックを外すと、すべて直接出力です。
画面のCHコードのchannel経路のbit値
CH101
CH212
CH324

画面のCH1・CH2・CH3は、APIでは0・1・2です。経路のbit値を1 + 2 + 4と足すと全CHをFilterへ送れます。CH1とCH3だけならrouting: 5です。選ばないCHは直接出力へ進みます。

このページのBypassはmode: "off", routing: 0です。CHをFilterへ送ったままmode: "off"だけにすると、そのCHが出てくるFilterの経路がなくなります。Bypassとは異なる設定です。

SIDは複数のFilter出力を加算することもでき、LP+HPはNotchの組合せです。この最初の実験では一種類ずつ比較します。組合せはSID SynthやAPIで試せます。

4. 設定をコードで読み、変更する

下の例は上の操作に追従します。Playgroundへ開いて編集できます。一つずつ値を変えてこのページと比べてください。比較するときは、先に鳴っている方を停止します。

コピーする例は4秒間鳴らし、短いReleaseを待ってclientを解放します。ページの実験は「停止」まで続きます。Playgroundや自分のアプリでは、MasterやMixerの設定で出力音量が変わります。

const sid = await useSoundChip('sid');
try {
  await sid.initialize();
  const notes = ['C3', 'E3', 'G3'];
  for (let ch = 0; ch < 3; ch++) {
    await sid.setVoice(ch, {
      waveform: 'saw', pulseWidth: 2048,
      attack: 2, decay: 6, sustain: 9, release: 4,
      sync: false, ring: false, test: false,
    });
    await sid.setNote(ch, notes[ch]);
  }

  // One shared hardware filter. Unrouted voices remain dry.
  // Bypass uses mode 'off' AND routing 0 to keep the voices audible.
  await sid.setFilter({
    mode: 'off', cutoff: 500, resonance: 5,
    routing: 0, volume: 8, voice3off: false,
  });
  for (const ch of [0]) await sid.keyOn(ch);

  // JavaScript waiting controls the performance; the SID clock runs in audio.
  await sleep(4);
  await sid.allNotesOff();
  await sleep(0.4);
} finally {
  sid.dispose();
}

自分のアプリへ持ち出す

PlaygroundはuseSoundChip()やsleep()を用意しています。自分のWebアプリでは、npmのSID clientを初期化します。既存の02-filter例に音声の初期化まで含まれており、setVoice()・setNote()・setFilter()の操作をこの実験と対応づけられます。Synthへのリンクは別の編集画面を開き、このページの設定を自動転送するものではありません。

どこまでがチップの機能?

Sawの発振器、各CHのEnvelope、経路、Filterの出力、Cutoff、ResonanceはSIDの操作です。ページのつまみ、和音の選択、音名の変換、Spectrum、固定の出力Gain、停止時のフェードはソフトウェアです。Filterの操作は鳴っている同じSIDへ設定を書き込み、保持中のCH1を再発音しません。