ChiptuneSynth の完全リファレンス — Web Audio API 対応の 4 トラック・チップチューン・シンセサイザー
// 1. Include the library
<script src="chiptune-synth.js"></script>
// 2. Create and initialize
const synth = new ChiptuneSynth();
await synth.init();
// 3. Play a note
synth.playNoteByName('C', 4, 0, 0.5);
// 4. Or play a sound effect
synth.playPreset('coin');
// 5. Load an instrument
synth.loadInstrument('violin', 0);
synth.playNoteByName('A', 4, 0, 1.0); init()` を呼び出してください。4つのトラック(Lead、Bass、Drums、FX)、デフォルトのエンベロープ、および空のビブラート設定を持つ新しいシンセサイザーインスタンスを作成します。
const synth = new ChiptuneSynth(); Web Audio API コンテキストを初期化し、マスターゲイン、アナライザー、トラックごとのゲインノード、およびノイズバッファを作成します。再生を行う前に一度呼び出す必要があります。
await synth.init(); すべてのノートを停止し、AudioContextを閉じます。シンセの使用が終了した際に呼び出してください。
指定されたトラックで、指定された周波数(Hz)のノートを再生します。
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
| frequency | 数値 | — | 周波数(Hz)(例:A4の場合は440) |
| trackIndex | 番号 | 0 | トラックインデックス:0=リード、1=ベース、2=ドラム、3=FX |
| duration | 番号 | 10 | 秒単位の持続時間。10以上の値は持続音を作成します |
| startTime | 数値 | 現在 | AudioContext 開始時刻(スケジューリング用) |
const noteId = synth.playNote(440, 0, 0.5); // A4, Lead, 0.5s stopNote() を使用して手動で制御する持続音には、duration = 10 以降を使用してください。これがキーボードや MIDI の動作原理です。音名でノートを再生します。
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
| note | 文字列 | — | 音名:C、C#、D、D#、E、F、F#、G、G#、A、A#、B(Db、Eb、Gb、Ab、Bbも含む) |
| オクターブ | オクターブ | 4 | オクターブ (1-7) |
| トラックインデックス | 番号 | 0 | 対象トラック |
| 再生時間 | 番号 | 10 | 秒単位の持続時間 |
synth.playNoteByName('C', 4, 0, 0.5); // Middle C on Lead
synth.playNoteByName('Eb', 3, 1, 1.0); // Eb3 on Bass 指定したノートを、そのリリースエンベロープとともに停止します。playNote()またはplayNoteByName()によって返されるnoteIdを使用します。
すべてのトラックにわたるアクティブなノートをすべて即座に停止します。
1回の呼び出しで、組み込みのSFXプリセットを読み込んで再生します。ゲームのサウンドエフェクトに最適です。
synth.playPreset('coin');
synth.playPreset('explosion');
synth.playPreset('jump'); | 名前 | 説明 | 使用例 |
|---|---|---|
| laser | 下降するザップビーム | 射撃、ビーム |
| コイン | 上昇する明るい音 | アイテム収集 |
| ジャンプ | 素早い上昇スイープ | ジャンプ、バウンド |
| 爆発 | ノイズバーストの減衰 | 破壊、死 |
| パワーアップ | 上昇するスイープファンファーレ | パワーアップ、アップグレード |
| ヒット | 鋭い衝撃音 | ダメージ、衝突 |
| ビープ音 | UIの短めのクリック | メニュー選択、UI |
| 低音 | 深い三角形のドスンという音 | 低音のドロップ、衝撃 |
| 撃つ | 素早い放電ショット | 連射武器 |
| 1UP | 上昇ファンファーレ | 追加ライフ、ボーナス |
プリセットの設定(波形、エンベロープ、エフェクト)を、再生せずにトラックに読み込みます。手動でノートをトリガーする前にトラックを設定するのに便利です。
指定されたトラックに完全なインストゥルメント・プリセットを読み込み、波形、エンベロープ、ビブラート、モジュレーションを設定します。
synth.loadInstrument('violin', 0);
synth.playNoteByName('A', 4, 0, 2.0); | 名前 | タイプ | 説明 |
|---|---|---|
| piano | トライアングル | 明るい打楽器のような音色で、余韻が短い |
| ヴァイオリン | ノコギリ波 | ビブラートのかかった温かみのある弓奏 |
| チェロ | ノコギリ波 | 低音域の深い弓奏 |
| フルート | 正弦波 | ビブラートを伴う柔らかく息の通った音色 |
| オルガン | スクエア | サステインのあるパイプオルガンの音色 |
| brass | 鋸歯波 | 力強いホルン/トランペットの音 |
| ハーモニカ | スクエア | トレモロ付き葦のようなPWM音色 |
| シンセリード | スクエア | クラシック・チップチューン・リード |
| シンセパッド | ソー | フィルター付きワイドユニゾン・パッド |
| シンセベース | ソー歯波 | パンチのあるシンセベース |
| マリンバ | サイン波 | パーカッシブなマレット音色 |
| エレクトリックギター | スクエア | オーバードライブ・ギター・エミュレーション |
トラックの1つ以上のプロパティを更新します。変更は、現在再生中のノートにリアルタイムで反映されます。
synth.updateTrack(0, {
type: 'sawtooth',
volume: 0.4,
unisonVoices: 4,
unisonDetune: 20
}); | プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
| タイプ | 文字列 | 'square' | 波形: 'square', 'triangle', 'sawtooth', 'sine', 'noise' |
| 音量 | 数値 | 0.3 | トラック音量 (0-1) |
| デューティサイクル | 数値 | 0.5 | 矩形波のパルス幅 (0-1) |
| デチューン | 数値 | 0 | セント単位の微調整 (1200 = 1 オクターブ) |
| オクターブオフセット | 数値 | 0 | オクターブシフト (±) |
| semitoneOffset | 数値 | 0 | 半音シフト (±) |
| ピッチエンベロープ | 数値 | 0 | 半音単位でのピッチエンベロープの深さ |
| glide | 数値 | 0 | ポルタメント時間(秒) |
トラックオブジェクトのプロパティを直接設定することもできます:
synth.tracks[0].type = 'sawtooth';
synth.tracks[0].volume = 0.4;
synth.updateLiveNotes(0); // Apply to active notes トラックの振幅エンベロープを設定します。ノートのフェードイン、サスティン、フェードアウトの挙動を制御します。
synth.updateEnvelope(0, {
attack: 0.1, // Fade-in time (seconds)
decay: 0.2, // Decay to sustain level
sustain: 0.6, // Held level (0-1)
release: 0.5 // Fade-out after note stops
}); | プロパティ | 型 | 範囲 | 説明 |
|---|---|---|---|
| attack | 数 | 0~5秒 | 最大音量に達するまでの時間 |
| 減衰 | 数値 | 0~5秒 | ピークからサスティンレベルまで低下する時間 |
| サスティン | 数値 | 0-1 | ノートを保持している間の音量レベル(0 = 減衰後にオフ) |
| release | 数値 | 0-10秒 | ノート停止後のフェードアウト時間 |
| トラック | アタック | ディケイ | サスティン | リリース |
|---|---|---|---|---|
| 0 - リード | 0.01 | 0.10 | 0.7 | 0.20 |
| 1 - 低音 | 0.01 | 0.20 | 0.8 | 0.15 |
| 2 - ドラム | 0.001 | 0.10 | 0.0 | 0.05 |
| 3 - エフェクト | 0.005 | 0.30 | 0.0 | 0.20 |
トラックのピッチ変調(ビブラート)を設定します。
synth.updateVibrato(0, {
rate: 5, // Speed in Hz
depth: 12 // Amount in cents
}); | プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
| rate | 数値 | 0 | LFO速度(Hz)(0 = オフ) |
| 深度 | 数値 | 0 | セント単位のピッチ偏差 (0 = オフ) |
各トラックには、サウンドの周波数特性を調整するためのオプションのフィルターがあります。
synth.tracks[0].filterEnabled = true;
synth.tracks[0].filterType = 'lowpass';
synth.tracks[0].filterCutoff = 2000;
synth.tracks[0].filterQ = 5;
synth.updateLiveNotes(0); | プロパティ | タイプ | デフォルト | 説明 |
|---|---|---|---|
| filterEnabled | ブール値 | false | フィルタの有効化/無効化 |
| filterType | 文字列 | 'lowpass' | 'lowpass', 'highpass', 'bandpass', 'notch' |
| filterCutoff | 数値 | 20000 | カットオフ周波数(Hz) |
| filterQ | 数値 | 0.1 | 共振 / Q値 |
| filterKeyTrack | 数値 | 0 | キートラッキング 0-100 (カットオフはピッチに追従) |
| filterEnvAmount | 数値 | 0 | フィルターエンベロープの深さ(半音) |
| filterEnvAttack | 数値 | 0.01 | フィルターエンベロープのアタック(秒) |
| filterEnvRelease | 数値 | 0.2 | フィルターエンベロープのリリース(秒) |
複数のデチューンされたオシレーターを重ねて、厚みのある広大なサウンドを作り出します。パッドやリード音に不可欠です。
synth.tracks[0].unisonVoices = 8;
synth.tracks[0].unisonDetune = 25; // cents between voices
synth.tracks[0].unisonSpread = 80; // stereo spread % | プロパティ | タイプ | デフォルト | 説明 |
|---|---|---|---|
| ユニゾンボイス | 数 | 1 | オシレーター数 (1-16) |
| unisonDetune | 数値 | 0 | デチューンの広がり(セント単位) |
| ユニゾンスプレッド | 数値 | 0 | ステレオ・パンニング・スプレッド (0-100%) |
synth.tracks[0].tremoloRate = 6; // Hz
synth.tracks[0].tremoloDepth = 50; // 0-100 synth.tracks[0].filterEnabled = true;
synth.tracks[0].filterCutoff = 1000;
synth.tracks[0].lfoFilterRate = 3; // Hz
synth.tracks[0].lfoFilterDepth = 2000; // Hz range | プロパティ | タイプ | 説明 |
|---|---|---|
| tremoloRate | 数値 | トレモロ速度(Hz)(0 = オフ) |
| tremoloDepth | 数値 | トレモロの量 (0-100) |
| lfoFilterRate | 数値 | フィルターLFOの速度(Hz)(0 = オフ) |
| lfoFilterDepth | 数値 | フィルターLFOの範囲(Hz) |
接続されたコントローラーからのMIDI入力を有効にします。検出されたMIDI入力デバイスの名前を配列として返します。
const inputs = await synth.enableMIDI({
track: 0,
channel: 0, // 0 = all channels
onConnect: (name) => console.log('Connected:', name),
onDisconnect: (name) => console.log('Disconnected:', name),
onNoteOn: (note, vel, ch) => { /* MIDI note 0-127 */ },
onNoteOff: (note, ch) => { /* ... */ },
onCC: (cc, value, ch) => { /* CC 0-127 */ }
}); | プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
| track | 番号 | 0 | MIDI ノート用のターゲットトラック |
| チャンネル | 番号 | 0 | MIDIチャンネルフィルター(1~16、0 = すべて) |
| onConnect | onConnect | — | MIDIデバイスが接続されたときに呼び出される |
| onDisconnect | 関数 | — | MIDIデバイスが切断されたときに呼び出されます |
| onNoteOn | 関数 | — | note on 時に呼び出される (note, velocity, channel) |
| onNoteOff | 関数 | — | ノートオフ時に呼び出される (note, channel) |
| onCC | 関数 | — | コントロールチェンジ時に呼び出される (cc, value, channel) |
| CC | 名前 | エフェクト |
|---|---|---|
| 1 | モジュレーション・ホイール | ビブラートの強さを調整します |
| 7 | Volume | トラックの音量を調整します |
| 64 | サステイン・ペダル | サステイン |
| 120 | すべての音声をオフ | すべての音を停止 |
| 123 | すべての音符をオフ | すべてのノートを停止 |
MIDI入力を無効にし、保持されているすべてのMIDIノートを停止します。
MIDI 入力を受け取るトラックを変更します。
MIDI チャンネルフィルターを設定します(0 = すべてのチャンネル)。
現在 MIDI が有効かどうかを返します。
オシロスコープ形式の視覚化を描画するための、時間領域の波形データを返します。値の範囲は 0~255 です(128 = 中心)。
function draw() {
const data = synth.getWaveformData();
// Draw on canvas...
ctx.beginPath();
data.forEach((v, i) => {
const x = (i / data.length) * width;
const y = (v / 255) * height;
i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
});
ctx.stroke();
requestAnimationFrame(draw);
} スペクトル可視化用の周波数領域(FFT)データを返します。値の範囲は 0~255 です。
マスター出力音量を設定します(0~1)。
現在のマスター音量を返します。
すべてのトラック、エンベロープ、ビブラートをデフォルト値にリセットします。
音名とオクターブを Hz 単位の周波数に変換します。
ChiptuneSynth.noteToFrequency('A', 4); // → 440
ChiptuneSynth.noteToFrequency('C', 4); // → 261.63 MIDI ノート番号 (0~127) を Hz 単位の周波数に変換します。
周波数を最も近い MIDI ノート番号に変換します。
利用可能なすべてのSFXプリセット名の配列を返します。
ChiptuneSynth.getPresetNames();
// → ['laser','coin','jump','explosion','powerup','hit','blip','bass','shoot','1up'] 利用可能なすべての楽器プリセット名の配列を返します。
楽器名をキーとするオブジェクトを返します。各値には、完全な定義(トラック設定、エンベロープ、ビブラート、フィルターなど)が含まれます。
const instruments = ChiptuneSynth.getInstruments();
// { piano: { name, label, icon, type, volume, ... }, violin: { ... }, ... }
// Access a specific instrument definition
const piano = instruments.piano;
console.log(piano.type); // 'triangle'
console.log(piano.label); // 'Piano' トラック設定、エンベロープ、ビブラート、フィルターを組み合わせて、独自のインストゥルメントを作成できます。以下に、サウンドをゼロから構築する方法を示します。
トラックを手動で設定し、そのトラック上でノートを演奏します:
// Create a retro pluck bass
synth.updateTrack(1, {
type: 'sawtooth',
volume: 0.5,
octaveOffset: -1
});
synth.updateEnvelope(1, {
attack: 0.005,
decay: 0.3,
sustain: 0.0,
release: 0.1
});
synth.playNoteByName('E', 2, 1, 0.4); プリセットのパターンを再現します。トラックを設定し、ノートを演奏すれば、あとはエンベロープが処理してくれます:
// Custom "warp" SFX on FX track (3)
function playWarp() {
synth.updateTrack(3, {
type: 'square',
volume: 0.3,
dutyCycle: 0.25,
pitchEnv: -24 // pitch drops 2 octaves
});
synth.updateEnvelope(3, {
attack: 0.01,
decay: 0.4,
sustain: 0.0,
release: 0.1
});
synth.playNote(880, 3, 0.5);
}
// Now call playWarp() anytime! 複数の機能を組み合わせて表現力豊かな楽器を作成:
// Dreamy synth pad with filter sweep
function setupDreamPad(track) {
synth.updateTrack(track, {
type: 'square',
volume: 0.25,
dutyCycle: 0.3,
unisonVoices: 6,
unisonDetune: 18,
unisonSpread: 70
});
synth.updateEnvelope(track, {
attack: 0.8,
decay: 0.5,
sustain: 0.6,
release: 2.0
});
synth.updateVibrato(track, {
rate: 4,
depth: 8
});
// Add filter with LFO modulation
synth.tracks[track].filterEnabled = true;
synth.tracks[track].filterType = 'lowpass';
synth.tracks[track].filterCutoff = 1200;
synth.tracks[track].filterQ = 3;
synth.tracks[track].lfoFilterRate = 0.3;
synth.tracks[track].lfoFilterDepth = 800;
}
setupDreamPad(0);
synth.playNoteByName('C', 4, 0, 3.0); 複数のトラックを重ねて複雑なサウンドを作成:
// Layered "epic hit" — noise + bass + lead
function playEpicHit() {
// Layer 1: noise crash
synth.updateTrack(2, { type: 'noise', volume: 0.4 });
synth.updateEnvelope(2, { attack:0.001, decay:0.3, sustain:0, release:0.1 });
synth.playNote(200, 2, 0.4);
// Layer 2: sub bass thump
synth.updateTrack(1, { type: 'sine', volume: 0.6, pitchEnv: 12 });
synth.updateEnvelope(1, { attack:0.001, decay:0.25, sustain:0, release:0.1 });
synth.playNote(60, 1, 0.3);
// Layer 3: bright accent
synth.updateTrack(0, { type: 'square', volume: 0.2 });
synth.updateEnvelope(0, { attack:0.001, decay:0.1, sustain:0, release:0.2 });
synth.playNote(440, 0, 0.15);
} カスタム楽器を構成オブジェクトとして整理:
// Define instrument configs
const myInstruments = {
retroLead: {
track: { type: 'square', dutyCycle: 0.25, volume: 0.3 },
env: { attack: 0.02, decay: 0.15, sustain: 0.5, release: 0.3 },
vib: { rate: 5.5, depth: 10 }
},
fatBass: {
track: { type: 'sawtooth', volume: 0.5, unisonVoices: 3, unisonDetune: 10 },
env: { attack: 0.01, decay: 0.2, sustain: 0.7, release: 0.1 },
vib: { rate: 0, depth: 0 }
}
};
// Apply an instrument to a track
function applyInstrument(name, trackIndex) {
const inst = myInstruments[name];
synth.updateTrack(trackIndex, inst.track);
synth.updateEnvelope(trackIndex, inst.env);
synth.updateVibrato(trackIndex, inst.vib);
}
applyInstrument('retroLead', 0);
synth.playNoteByName('C', 5, 0, 0.5); | トラック | インデックス | 波形 | 音量 |
|---|---|---|---|
| リード | 0 | 正方形 | 0.30 |
| 低音 | 1 | トライアングル | 0.40 |
| ドラム | 2 | ノイズ | 0.50 |
| エフェクト | 3 | ノコギリ波 | 0.25 |
ノートごとのgainNodeは、ADSRエンベロープ(正規化0→1→サスティン)のみを処理します。トラックの音量は、別の_trackGains[]ノードによって制御されます。このアーキテクチャにより、演奏中のノートのADSRスケジュールを中断することなく、リアルタイムでパラメータを変更することが可能です。