SID / FILTER / INTRODUCTION
SIDのフィルターで音の明るさを変える
同じノコギリ波を鳴らしたまま、出てくる音の成分を変える。設定をJavaScriptへ持ち出すところまで試します。
MOS 6581 · PAL · Tetorica approximation
小さな聴き比べの実験
まずBypassで単音を鳴らし、そのまま操作します。3CHとも同じSaw設定です。和音のチェックはCH2・CH3を追加し、CH1は鳴らしたままです。「設定を戻す」は初期設定へ戻します。「停止」はソフトウェア側で出力をフェードして音源を解放します。
停止中です。「音を鳴らす」を押すまで再生しません。
1. 音符はそのまま、Filterの出力を変える
ノコギリ波には、基音とそれより高い倍音が含まれます。Filterは、その成分のバランスを変えます。出力を切り替えても、発振器に設定した音程は変えていません。
- Bypassのまま音を鳴らすを押します。元のSaw音とSpectrumを確かめます。
- LPを選び、Cutoffを1200付近から200付近へゆっくり下げ、戻します。Spectrumの高い周波数側を見比べてください。
- 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が、送られた複数の音に共通して働きます。
- CH2のチェックだけを外します。CH2は直接出力へ、CH1・CH3はFilterへ進みます。
- Cutoffを動かし、直接の音とFilterを通る音が重なる様子を聴きます。
- CH2を戻すと、3CHとも同じFilterへ入ります。全チェックを外すと、すべて直接出力です。
| 画面のCH | コードのchannel | 経路のbit値 |
|---|---|---|
| CH1 | 0 | 1 |
| CH2 | 1 | 2 |
| CH3 | 2 | 4 |
画面の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を再発音しません。