fix: reduce master clock to 240 Hz + eliminate note-off timeouts
- Master clock 960→240 Hz: reduces CPU/GC pressure by 4x while still providing 12x headroom for 300 BPM sixteenths - Remove Tone.getContext().setTimeout() for note-off scheduling — these accumulated over time causing periodic hiccups - Note-off now happens at step boundary: previous gate turned off at the start of each new step (cleaner, zero accumulation) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -71,18 +71,23 @@ export default function SequencerWidget({ moduleId }) {
|
||||
}
|
||||
|
||||
let lastStepIdx = -1;
|
||||
let noteOffTimeout = null;
|
||||
let lastGateOn = false;
|
||||
|
||||
subscribeTick(`seq-${moduleId}`, (time, elapsed) => {
|
||||
const currentBpm = bpmRef.current;
|
||||
const currentNumSteps = numStepsRef.current;
|
||||
const sixteenthRate = (currentBpm * 4) / 60;
|
||||
const stepDuration = 1 / sixteenthRate;
|
||||
const stepIdx = Math.floor(elapsed * sixteenthRate) % currentNumSteps;
|
||||
|
||||
if (stepIdx === lastStepIdx) return;
|
||||
lastStepIdx = stepIdx;
|
||||
|
||||
// Turn off previous note at step boundary (no setTimeout needed)
|
||||
if (lastGateOn) {
|
||||
setSequencerSignals(moduleId, 0, false);
|
||||
lastGateOn = false;
|
||||
}
|
||||
|
||||
const s = stepsRef.current[stepIdx];
|
||||
if (!s) return;
|
||||
|
||||
@@ -90,11 +95,7 @@ export default function SequencerWidget({ moduleId }) {
|
||||
|
||||
if (s.gate) {
|
||||
setSequencerSignals(moduleId, midiToFreq(s.midi), true);
|
||||
Tone.getContext().setTimeout(() => {
|
||||
setSequencerSignals(moduleId, midiToFreq(s.midi), false);
|
||||
}, stepDuration * 0.8);
|
||||
} else {
|
||||
setSequencerSignals(moduleId, midiToFreq(s.midi), false);
|
||||
lastGateOn = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ const keyboardState = { frequency: 440, gate: false };
|
||||
// ==================== Global Master Clock ====================
|
||||
// Single high-resolution clock (960 ticks/sec ≈ 1ms precision).
|
||||
// All sequencers/piano rolls derive their timing from this.
|
||||
const MASTER_TICK_RATE = 960; // Hz
|
||||
const MASTER_TICK_RATE = 240; // Hz — enough for 300 BPM sixteenths (20 Hz) with 12x headroom
|
||||
let _masterClock = null;
|
||||
let _masterTime = 0; // audio-context seconds at clock start
|
||||
const _tickListeners = new Map(); // id → callback(audioTime, elapsed)
|
||||
|
||||
Reference in New Issue
Block a user