<!-- SS · part 100 -->
n; }
    var hp = k(new Tone.Filter(7000, 'highpass').connect(out));
    var cf = k(new Tone.Filter(1300, 'bandpass').connect(out)); cf.Q.value = 0.8;
    d.perc = k(new Tone.NoiseSynth({ noise: { type: 'white' }, envelope: { attack: 0.002, decay: 0.12, sustain: 0 }, volume: -4 }).connect(cf));
    if (kit === 'Lo-fi') {
      var lp = k(new Tone.Filter(3200, 'lowpass').connect(out));
      d.kick = k(new Tone.MembraneSynth({ pitchDecay: 0.03, octaves: 6, envelope: { attack: 0.001, decay: 0.35, sustain: 0, release: 0.1 } }).connect(lp));
      d.snare = k(new Tone.NoiseSynth({ noise: { type: 'pink' }, envelope: { attack: 0.001, decay: 0.18, sustain: 0 } }).connect(lp));
      d.hat = k(new Tone.NoiseSynth({ noise: { type: 'white' }, envelope: { attack: 0.001, decay: 0.04, sustain: 0 }, volume: -10 }).connect(hp));
      d.kickNote = 'C1';
    } else if (kit === 'Chip') {
      d.kick = k(new Tone.MembraneSynth({ oscillator: { type: 'square' }, pitchDecay: 0.02, octaves: 4, envelope: { attack: 0.001, decay: 0.18, sustain: 0 }, volume: -8 }).connect(out));
      d.snare = k(new Tone.NoiseSynth({ noise: { type: 'brown' }, envelope: { attack: 0.001, decay: 0.09, sustain: 0 }, volume: 2 }).connect(out));
      d.hat = k(new Tone.NoiseSynth({ noise: { type: 'white' }, envelope: { attack: 0.001, decay: 0.02, sustain: 0 }, volume: -6 }).connect(hp));
      d.kickNote = 'C2';
    } else {
      d.kick = k(new Tone.MembraneSynth({ pitchDecay: 0.06, octaves: 8, envelope: { attack: 0.001, decay: 0.6, sustain: 0.01, release: 0.4 } }).connect(out));
      var sf = k(new Tone.Filter(1800, 'bandpass').connect(out));
      d.snare = k(new Tone.NoiseSynth({ noise: { type: 'white' }, envelope: { attack: 0.001, decay: 0.2, sustain: 0 }, volume: 6 }).connect(sf));
      d.hat = k(new Tone.NoiseSynth({ noise: { type: 'white' }, envelope: { attack: 0.001, decay: 0.05, sustain: 0 }, volume: -4 }).connect(hp));
      d.kickNote = 'A0';
    }
    d.play = function (row, time, vel) { if (row === 'kick') d.kick.triggerAttackRelease(d.kickNote, '8n', time, vel); else d[row].triggerAttackRelease(row === 'hat' ? '32n' : '16n', time, vel); };
    d.dispose = function () { nodes.forEach(function (n) { try { n.dispose(); } catch (e) {} }); };
    return d;
  }
  function makeSynth(track, kind, out) {
    var s;
    if (track === 'bass') {
      if (kind === 'Saw') s = new Tone.MonoSynth({ oscillator: { type: 'sawtooth' }, filter: { Q: 2, type: 'lowpass' }, envelope: { attack: 0.005, decay: 0.2, sustain: 0.5, release: 0.2 }, filterEnvelope: { attack: 0.001, decay: 0.15, sustain: 0.2, baseFrequency: 120, octaves: 3 } });
      else if (kind === 'FM') s = new Tone.FMSynth({ harmonicity: 1, modulationIndex: 6, envelope: { attack: 0.005, decay: 0.3, sustain: 0.4, release: 0.2 } });
      else s = new Tone.Synth({ oscillator: { type: 'sine' }, envelope: { attack: 0.005, decay: 0.4, sustain: 0.6, release: 0.3 }, volume: 4 });
    } else if (track === 'chords') {
      if (kind === 'Keys') s = new Tone.PolySynth(Tone.FMSynth, { harmonicity: 3, modulationIndex: 2, envelope: { attack: 0.005, decay: 0.8, sustain: 0.2, release: 0.8 } });
      else if (kind === 'Pluck') s = new Tone.PolySynth(Tone.Synth, { oscillator: { type: 'triangle' }, envelope: { attack: 0.002, decay: 0.25, sustain: 0, release: 0.2 } });
      else s = new Tone.PolySynth(Tone.Synth, { oscillator: { type: 'fatsawtooth', count: 3, spread: 20 }, envelope: { attack: 0.3, decay: 0.4, sustain: 0.7, release: 1.2 }, volume: -6 });
      s.maxPolyphony = 16;
    } else {
      if (kind === 'Square') s = new Tone.Synth({ oscillator: { type: 'square' }, envelope: { attack: 0.005, decay: 0.15, sustain: 0.3, release: 0.15 }, volume: -6 });
      else if (kind === 'Bell') s = new Tone.FMSynth({ harmonicity: 3.01, modulationIndex: 12, envelope: { attack: 0.001, decay: 1.2, sustain: 0, release: 1 }, modulationEnvelope: { attack: 0.001, decay: 0.6, sustain: 0, release: 0.5 } });
      else s = new Tone.MonoSynth({ oscillator: { type: 'sawtooth' }, filter: { Q: 1, type: 'lowpass' }, envelope: { attack: 0.01, decay: 0.2, sustain: 0.4, release: 0.25 }, filterEnvelope: { attack: 0.01, decay: 0.2, sustain: 0.4, baseFrequency: 600, octaves: 2.5 }, volume: -4 });
    }
    return s.connect(out);
  }
  // One complete signal graph in the CURRENT Tone context (realtime, or inside Tone.Offline).
  function makeGraph(withMeters) {
    var G = { ch: {}, inst: {}, nodes: [] };
    function k(n) { G.nodes.push(n); return n; }
    G.out = k(new Tone.Gain(1));
    G.eq = k(new Tone.EQ3(0, 0, 0)); G.drive = k(new Tone.Distortion({ distortion: 0, wet: 0 }));
    G.comp = k(new Tone.Compressor({ threshold: -12, ratio: 1.5, attack: 0.01, release: 0.2 }));
    G.width = k(new Tone.StereoWidener(0.5)); G.limiter = k(new Tone.Limiter(-1)); G.mvol = k(new Tone.Gain(0.9));
    // insert points (EQ plugin rewires in->out): master and one per lane
    G.mIn = k(new Tone.Gain(1)); G.mOut = k(new Tone