主演示
CDN v3.0.0

将这两个标签添加到页面 — </body> 或在 <head> :

合成引擎
<script src="https://cdn.chiptune-synth.8binami.com/3.0.0/chiptune-synth.min.js"></script>
音色库 (170+ instruments)
<script src="https://cdn.chiptune-synth.8binami.com/3.0.0/chiptune-sound-font.min.js"></script>

API Documentation

Complete reference for ChiptuneSynth — 4-track chiptune synthesizer for the Web Audio API

Table of Contents

Quick Start

// 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);
The AudioContext requires a user gesture (click/tap) to start. Always call init() inside a click handler or after user interaction.

Constructor & Initialization

new ChiptuneSynth()

创作s a new synthesizer instance with 4个音轨 (Lead, 贝斯, Drums, FX), default envelopes, and empty vibrato settings.

const synth = new ChiptuneSynth();

synth.init() async

Initializes the Web Audio API context, creates master gain, analyser, per-track gain nodes, and noise buffer. Must be called once before any playback.

await synth.init();

synth.dispose()

Stops all notes and closes the AudioContext. Call when you're done with the synth.

播放back Methods

synth.play音符(frequency, trackIndex, duration, startTime) → noteId

播放s a note at the given frequency (Hz) on the specified track.

ParameterTypeDefaultDescription
frequencynumberFrequency in Hz (e.g. 440 for A4)
trackIndexnumber0Track index: 0=Lead, 1=贝斯, 2=Drums, 3=FX
durationnumber10Duration in seconds. Values ≥10 create sustained notes
startTimenumbernowAudioContext time to start (for scheduling)
const noteId = synth.playNote(440, 0, 0.5);  // A4, Lead, 0.5s
Use duration = 10 or higher for sustained notes that you control manually with stopNote(). This is how the keyboard and MIDI work.

synth.play音符ByName(note, octave, trackIndex, duration) → noteId

播放s a note by its musical name.

ParameterTypeDefaultDescription
notestring音符 name: C, C#, D, D#, E, F, F#, G, G#, A, A#, B (also Db, Eb, Gb, Ab, Bb)
octavenumber4八度 (1-7)
trackIndexnumber0Target track
durationnumber10Duration in seconds
synth.playNoteByName('C', 4, 0, 0.5);  // Middle C on Lead
synth.playNoteByName('Eb', 3, 1, 1.0); // Eb3 on Bass

synth.stop音符(noteId)

Stops a specific note with its release envelope. Use the noteId returned by playNote() or playNoteByName().

synth.stopAll音符s()

Immediately stops all active notes across all tracks.

Presets & 乐器

synth.playPreset(name)

Loads and plays a built-in SFX preset in one call. Perfect for game sound effects.

synth.playPreset('coin');
synth.playPreset('explosion');
synth.playPreset('jump');

Available SFX Presets (10)

NameDescriptionUse Case
laserDescending zap beam射击ing, beams
coinRising bright dingCollecting items
jumpQuick ascending sweep跳跃ing, bouncing
explosion噪音 burst decayDestruction, death
powerupRising sweep fanfarePower-ups, upgrades
hitSharp impact noiseDamage, collision
blipShort UI clickMenu selection, UI
bassDeep triangle thump贝斯 drops, impacts
shootQuick zap shotRapid fire weapons
1upAscending fanfareExtra lives, bonuses

synth.loadPreset(name)

Loads a preset's configuration (waveform, envelope, effects) onto a track without playing it. Useful for setting up a track before triggering notes manually.

synth.loadInstrument(name, trackIndex) → boolean

Loads a full instrument preset onto the specified track, configuring waveform, envelope, vibrato, and modulation.

synth.loadInstrument('violin', 0);
synth.playNoteByName('A', 4, 0, 2.0);

Available 乐器 (12)

NameTypeDescription
pianotriangleBright percussive tone with quick decay
violinsawtoothWarm bowed string with vibrato
cellosawtoothDeep bowed string, low register
flutesineSoft breathy tone with vibrato
organsquare延音ed pipe organ tone
brasssawtoothBold horn/trumpet sound
harmonicasquareReedy PWM tone with tremolo
synthLeadsquareClassic chiptune lead
synthPadsawtoothWide unison pad with filter
synth贝斯sawtoothPunchy synth bass
marimbasinePercussive mallet tone
electricGuitarsquareOverdriven guitar emulation

Track Configuration

synth.updateTrack(trackIndex, settings)

Updates one or more properties of a track. Changes apply in real-time to currently playing notes.

synth.updateTrack(0, {
  type: 'sawtooth',
  volume: 0.4,
  unisonVoices: 4,
  unisonDetune: 20
});

Track Properties

PropertyTypeDefaultDescription
typestring'square'波形: 'square', 'triangle', 'sawtooth', 'sine', 'noise'
volumenumber0.3Track volume (0-1)
dutyCyclenumber0.5Pulse width for square waves (0-1)
detunenumber0Fine tuning in cents (1200 = 1 octave)
octaveOffsetnumber0八度 shift (±)
semitoneOffsetnumber0半音tone shift (±)
pitchEnvnumber0音调 envelope depth in semitones
glidenumber0Portamento time in seconds

You can also directly set properties on the track objects:

synth.tracks[0].type = 'sawtooth';
synth.tracks[0].volume = 0.4;
synth.updateLiveNotes(0); // Apply to active notes

Envelopes (ADSR)

synth.updateEnvelope(trackIndex, settings)

Sets the amplitude envelope for a track. Controls how notes fade in, sustain, and fade out.

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
});
PropertyTypeRangeDescription
attacknumber0-5sTime to reach full volume
decaynumber0-5sTime to fall from peak to sustain level
sustainnumber0-1音量 level while note is held (0 = off after decay)
releasenumber0-10sFade-out time after note stops

Default Envelopes

Track起音衰减延音释放
0 - Lead0.010.100.70.20
1 - 贝斯0.010.200.80.15
2 - Drums0.0010.100.00.05
3 - FX0.0050.300.00.20

颤音

synth.update颤音(trackIndex, settings)

Configures pitch modulation (vibrato) for a track.

synth.updateVibrato(0, {
  rate:  5,   // Speed in Hz
  depth: 12   // Amount in cents
});
PropertyTypeDefaultDescription
ratenumber0LFO speed in Hz (0 = off)
depthnumber0音调 deviation in cents (0 = off)

滤波器

Each track has an optional filter for shaping the frequency content of the sound.

synth.tracks[0].filterEnabled = true;
synth.tracks[0].filterType = 'lowpass';
synth.tracks[0].filterCutoff = 2000;
synth.tracks[0].filterQ = 5;
synth.updateLiveNotes(0);
PropertyTypeDefaultDescription
filter启用dbooleanfalse启用/disable filter
filterTypestring'lowpass''lowpass', 'highpass', 'bandpass', 'notch'
filter截止频率number20000截止频率 frequency in Hz
filterQnumber0.1共鸣 / Q factor
filterKeyTracknumber0Key tracking 0-100 (cutoff follows pitch)
filterEnv量number0滤波器 envelope depth (semitones)
filterEnv起音number0.01滤波器 envelope attack (seconds)
filterEnv释放number0.2滤波器 envelope release (seconds)

齐奏 & 失谐

Stack multiple detuned oscillators for a thick, wide sound. Essential for pads and leads.

synth.tracks[0].unisonVoices = 8;
synth.tracks[0].unisonDetune = 25;  // cents between voices
synth.tracks[0].unisonSpread = 80;  // stereo spread %
PropertyTypeDefaultDescription
unison声部number1Number of oscillators (1-16)
unison失谐number0失谐 spread in cents
unison展宽number0Stereo panning spread (0-100%)

LFOs (震音 & 滤波器 调制ulation)

震音 (Amplitude LFO)

synth.tracks[0].tremoloRate = 6;    // Hz
synth.tracks[0].tremoloDepth = 50;   // 0-100

滤波器 LFO

synth.tracks[0].filterEnabled = true;
synth.tracks[0].filterCutoff = 1000;
synth.tracks[0].lfoFilterRate = 3;     // Hz
synth.tracks[0].lfoFilterDepth = 2000;  // Hz range
PropertyTypeDescription
tremolo速率number震音 speed in Hz (0 = off)
tremolo深度number震音 amount (0-100)
lfo滤波器速率number滤波器 LFO speed in Hz (0 = off)
lfo滤波器深度number滤波器 LFO range in Hz
ChiptuneSynth has 3 independent LFOs per track: 颤音 (pitch), 震音 (volume), and 滤波器 modulation.

MIDI Support

synth.enableMIDI(options) async→ inputNames[]

启用s MIDI input from connected controllers. Returns an array of detected MIDI input device names.

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 */ }
});

Options

PropertyTypeDefaultDescription
tracknumber0Target track for MIDI notes
channelnumber0MIDI channel filter (1-16, 0 = all)
onConnectfunctionCalled when a MIDI device connects
onDisconnectfunctionCalled when a MIDI device disconnects
on音符OnfunctionCalled on note on (note, velocity, channel)
on音符OfffunctionCalled on note off (note, channel)
onCCfunctionCalled on control change (cc, value, channel)

Supported MIDI CC

CCNameEffect
1调制 WheelControls vibrato depth
7音量Controls track volume
64延音 Pedal延音s held notes
120All Sound OffStops all notes
123All 音符s OffStops all notes

synth.disableMIDI()

Disables MIDI input and stops all held MIDI notes.

synth.setMIDITrack(trackIndex)

Changes which track receives MIDI input.

synth.setMIDIChannel(ch)

Sets the MIDI channel filter (0 = all channels).

synth.isMIDI启用d() → boolean

Returns whether MIDI is currently active.

Visualizer Data

synth.get波形Data() → Uint8Array

Returns time-domain waveform data for drawing oscilloscope-style visualizations. Values range from 0-255 (128 = center).

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);
}

synth.getFrequencyData() → Uint8Array

Returns frequency-domain (FFT) data for spectrum visualizations. Values range from 0-255.

synth.set主音量音量(value)

Sets the master output volume (0-1).

synth.get主音量音量() → number

Returns the current master volume.

synth.resetToDefaults()

Resets all tracks, envelopes, and vibrato to their default values.

Static Methods

ChiptuneSynth.noteToFrequency(note, octave) static→ number

Converts a note name and octave to frequency in Hz.

ChiptuneSynth.noteToFrequency('A', 4);  // → 440
ChiptuneSynth.noteToFrequency('C', 4);  // → 261.63

ChiptuneSynth.midiToFrequency(midi) static→ number

Converts a MIDI note number (0-127) to frequency in Hz.

ChiptuneSynth.frequencyToMidi(freq) static→ number

Converts a frequency to the nearest MIDI note number.

ChiptuneSynth.getPresetNames() static→ string[]

Returns an array of all available SFX preset names.

ChiptuneSynth.getPresetNames();
// → ['laser','coin','jump','explosion','powerup','hit','blip','bass','shoot','1up']

ChiptuneSynth.getInstrumentNames() static→ string[]

Returns an array of all available instrument preset names.

ChiptuneSynth.get乐器() static→ object

Returns an object keyed by instrument name, each value containing the full definition (track settings, envelope, vibrato, filter, etc.).

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'

Creating Custom 乐器

You can craft your own instruments by combining track settings, envelopes, vibrato, and filters. Here's how to build sounds from scratch.

基础 Custom Sound

Configure a track manually, then play notes on it:

// 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 SFX (Preset-Style)

Replicate the preset pattern — configure a track, play a note, and let the envelope handle the rest:

// 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!

Rich Instrument with Effects

Combine multiple features for expressive instruments:

// 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);

Multi-Track Layered Sound

Layer multiple tracks for complex sounds:

// 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);
}

Reusable Instrument Object Pattern

Organize your custom instruments as config objects:

// 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);
The Reusable Instrument Object pattern is the recommended approach for managing custom instruments in your game or app. It keeps your sound design clean and easy to tweak.
探索 8BitForge — a creative app built with ChiptuneSynth featuring a visual instrument editor, 8 tracks, full mixer with EQ/compressor, 3 LFOs per track, and 50+ built-in instruments. 学习 more

Default Values

Track Defaults

TrackIndex波形音量
Lead0square0.30
贝斯1triangle0.40
Drums2noise0.50
FX3sawtooth0.25

Architecture 音符

Per-note gainNode handles only the ADSR envelope (normalized 0→1→sustain). Track volume is controlled by a separate _trackGains[] node. This architecture allows real-time parameter changes without interrupting the ADSR schedule of playing notes.