fix(piano-roll): playhead seek + sound cracking
- Piano roll ruler click during playback now seeks and continues playing - ADSR envelope uses linearRampToValueAtTime for crack-free release - stopAll ramps gain to 0 in 20ms before stopping oscillators
This commit is contained in:
@@ -125,7 +125,7 @@
|
||||
}
|
||||
|
||||
osc.type = oscType;
|
||||
osc.frequency.value = freq;
|
||||
osc.frequency.setValueAtTime(freq, 0);
|
||||
|
||||
const startAt = startTime !== undefined ? startTime : ctx.currentTime;
|
||||
const durSec = durationMs / 1000;
|
||||
@@ -139,9 +139,8 @@
|
||||
noteGain.gain.linearRampToValueAtTime(targetGain * sustainLevel, startAt + attackTime + decayTime);
|
||||
|
||||
const releaseStart = startAt + Math.max(attackTime + decayTime, durSec);
|
||||
noteGain.gain.setValueAtTime(targetGain * sustainLevel, releaseStart);
|
||||
const rampEnd = Math.max(0.001, targetGain * sustainLevel * 0.01);
|
||||
noteGain.gain.exponentialRampToValueAtTime(rampEnd, releaseStart + releaseTime);
|
||||
noteGain.gain.linearRampToValueAtTime(targetGain * sustainLevel, releaseStart);
|
||||
noteGain.gain.linearRampToValueAtTime(0, releaseStart + releaseTime);
|
||||
|
||||
osc.connect(noteGain);
|
||||
|
||||
@@ -150,7 +149,7 @@
|
||||
|
||||
osc.start(startAt);
|
||||
|
||||
const stopAt = releaseStart + releaseTime + 0.05;
|
||||
const stopAt = releaseStart + releaseTime + 0.02;
|
||||
osc.stop(stopAt);
|
||||
|
||||
const oscId = `${note}_${Date.now()}_${Math.random()}`;
|
||||
@@ -166,17 +165,22 @@
|
||||
|
||||
stopAll: function () {
|
||||
const ctx = getCtx();
|
||||
const now = ctx.currentTime;
|
||||
Object.values(activeOscillators).forEach(entry => {
|
||||
try {
|
||||
if (entry.gain) {
|
||||
entry.gain.gain.cancelScheduledValues(ctx.currentTime);
|
||||
entry.gain.gain.setValueAtTime(entry.gain.gain.value || 1, ctx.currentTime);
|
||||
entry.gain.gain.linearRampToValueAtTime(0.001, ctx.currentTime + 0.008);
|
||||
entry.gain.gain.cancelScheduledValues(now);
|
||||
entry.gain.gain.setValueAtTime(entry.gain.gain.value || 0.8, now);
|
||||
entry.gain.gain.linearRampToValueAtTime(0, now + 0.02);
|
||||
}
|
||||
if (entry.osc) {
|
||||
try { entry.osc.stop(now + 0.025); } catch (e) { }
|
||||
}
|
||||
if (entry.osc) entry.osc.stop(ctx.currentTime + 0.01);
|
||||
} catch (e) { }
|
||||
});
|
||||
Object.keys(activeOscillators).forEach(k => delete activeOscillators[k]);
|
||||
setTimeout(() => {
|
||||
Object.keys(activeOscillators).forEach(k => delete activeOscillators[k]);
|
||||
}, 50);
|
||||
},
|
||||
|
||||
// Save user SoundFont to IndexedDB via window.SonicStorage
|
||||
|
||||
Reference in New Issue
Block a user