mirror of
https://codeberg.org/uzu/strudel
synced 2026-09-05 06:57:35 -04:00
Attempt to block animation when pattern highlighting disabled
This commit is contained in:
@@ -162,6 +162,7 @@ export class StrudelMirror {
|
||||
this.onDraw = onDraw || this.draw;
|
||||
this.id = id || s4();
|
||||
this.solo = solo;
|
||||
this.hasPainters = false;
|
||||
|
||||
this.drawer = new Drawer((haps, time, _, painters) => {
|
||||
const currentFrame = haps.filter((hap) => hap.isActive(time));
|
||||
@@ -177,7 +178,7 @@ export class StrudelMirror {
|
||||
onToggle: (started) => {
|
||||
replOptions?.onToggle?.(started);
|
||||
if (started) {
|
||||
this.drawer.start(this.repl.scheduler);
|
||||
this.shouldAnimate() && this.drawer.start(this.repl.scheduler);
|
||||
if (this.solo) {
|
||||
// stop other repls when this one is started
|
||||
document.dispatchEvent(
|
||||
@@ -207,9 +208,10 @@ export class StrudelMirror {
|
||||
updateWidgets(this.editor, widgets);
|
||||
updateMiniLocations(this.editor, this.miniLocations);
|
||||
replOptions?.afterEval?.(options);
|
||||
this.hasPainters = options.pattern.getPainters().length > 0;
|
||||
// if no painters are set (.onPaint was not called), then we only need
|
||||
// the present moment (for highlighting)
|
||||
const drawTime = options.pattern.getPainters().length ? this.drawTime : [0, 0];
|
||||
const drawTime = this.hasPainters ? this.drawTime : [0, 0];
|
||||
this.drawer.setDrawTime(drawTime);
|
||||
// invalidate drawer after we've set the appropriate drawTime
|
||||
this.drawer.invalidate(this.repl.scheduler);
|
||||
@@ -327,6 +329,12 @@ export class StrudelMirror {
|
||||
}
|
||||
highlightMiniLocations(this.editor, time, haps);
|
||||
}
|
||||
shouldAnimate() {
|
||||
return (
|
||||
this.repl.scheduler.started &&
|
||||
(this.isPatternHighlightingEnabled || this.hasPainters || this.onDraw !== this.draw)
|
||||
);
|
||||
}
|
||||
setFontSize(size) {
|
||||
this.root.style.fontSize = size + 'px';
|
||||
}
|
||||
@@ -343,13 +351,15 @@ export class StrudelMirror {
|
||||
return;
|
||||
}
|
||||
value = parseBooleans(value);
|
||||
if (key === 'isPatternHighlightingEnabled') {
|
||||
this.isPatternHighlightingEnabled = value;
|
||||
}
|
||||
const newValue = extensions[key](value, this);
|
||||
this.editor.dispatch({
|
||||
effects: compartments[key].reconfigure(newValue),
|
||||
});
|
||||
if (key === 'isPatternHighlightingEnabled') {
|
||||
this.isPatternHighlightingEnabled = value;
|
||||
this.drawer.stop();
|
||||
this.shouldAnimate() && this.drawer.start(this.repl.scheduler);
|
||||
}
|
||||
if (key === 'theme') {
|
||||
activateTheme(value);
|
||||
}
|
||||
|
||||
@@ -191,22 +191,13 @@ export function registerSynthSounds() {
|
||||
getPitchEnvelope(o.parameters.get('detune'), value, begin, holdend);
|
||||
const vibratoOscillator = getVibratoOscillator(o.parameters.get('detune'), value, begin);
|
||||
const fm = applyFM(o.parameters.get('frequency'), value, begin);
|
||||
getParamADSR(
|
||||
o.parameters.get('postgain'),
|
||||
attack,
|
||||
decay,
|
||||
sustain,
|
||||
release,
|
||||
0,
|
||||
0.3 * gainAdjustment,
|
||||
begin,
|
||||
holdend,
|
||||
'linear',
|
||||
);
|
||||
const envGain = o.connect(gainNode(1));
|
||||
getParamADSR(envGain.gain, attack, decay, sustain, release, 0, 0.3 * gainAdjustment, begin, holdend, 'linear');
|
||||
const timeoutNode = webAudioTimeout(
|
||||
ac,
|
||||
() => {
|
||||
destroyAudioWorkletNode(o);
|
||||
envGain.disconnect();
|
||||
releaseVoice('supersaw', o);
|
||||
onended();
|
||||
fm?.stop();
|
||||
@@ -217,7 +208,7 @@ export function registerSynthSounds() {
|
||||
);
|
||||
|
||||
return {
|
||||
node: o,
|
||||
node: envGain,
|
||||
stop: (time) => {
|
||||
timeoutNode.stop(time);
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
applyFM,
|
||||
applyParameterModulators,
|
||||
claimVoice,
|
||||
gainNode,
|
||||
getADSRValues,
|
||||
getFrequencyFromValue,
|
||||
getParamADSR,
|
||||
@@ -320,9 +321,10 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) {
|
||||
);
|
||||
const vibratoOscillator = getVibratoOscillator(source.parameters.get('detune'), value, t);
|
||||
const fm = applyFM(source.parameters.get('frequency'), value, t);
|
||||
getParamADSR(source.parameters.get('postgain'), attack, decay, sustain, release, 0, 0.3, t, holdEnd, 'linear');
|
||||
const envGain = source.connect(gainNode(1));
|
||||
getParamADSR(envGain.gain, attack, decay, sustain, release, 0, 0.3, t, holdEnd, 'linear');
|
||||
getPitchEnvelope(source.parameters.get('detune'), value, t, holdEnd);
|
||||
const handle = { node: source };
|
||||
const handle = { node: envGain };
|
||||
const timeoutNode = webAudioTimeout(
|
||||
ac,
|
||||
() => {
|
||||
@@ -330,6 +332,7 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) {
|
||||
fm?.stop();
|
||||
wtPosModulators?.disconnect();
|
||||
wtWarpModulators?.disconnect();
|
||||
envGain.disconnect();
|
||||
destroyAudioWorkletNode(source);
|
||||
releaseVoice(voiceKey, source);
|
||||
onended();
|
||||
|
||||
@@ -43,7 +43,7 @@ const getDetuner = (unison, detune) => {
|
||||
function fastPow2(x) {
|
||||
// Taylor approximation of 2 ^ x
|
||||
const a = x * 0.6931471805599453; // ln(2)
|
||||
return 1 + a * (1 + a * (0.8333333333333333 + a));
|
||||
return 1 + a * (1 + a * (0.5 + (a / 6)));
|
||||
}
|
||||
|
||||
const applySemitoneDetuneToFrequency = (frequency, detune) => {
|
||||
@@ -517,10 +517,6 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
|
||||
defaultValue: 0,
|
||||
min: 0,
|
||||
},
|
||||
{
|
||||
name: 'postgain',
|
||||
defaultValue: 1,
|
||||
},
|
||||
];
|
||||
}
|
||||
process(_input, outputs, params) {
|
||||
@@ -548,10 +544,9 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
|
||||
gainR = Math.sqrt(0.5 + 0.5 * panspread);
|
||||
}
|
||||
for (let i = 0; i < output[0].length; i++) {
|
||||
const postgain = pv(params.postgain, i);
|
||||
const panspread = pv(params.panspread, i) * 0.5 + 0.5;
|
||||
gainL = Math.sqrt(1 - panspread) * postgain;
|
||||
gainR = Math.sqrt(panspread) * postgain;
|
||||
gainL = Math.sqrt(1 - panspread);
|
||||
gainR = Math.sqrt(panspread);
|
||||
// Main detuning (a-rate path)
|
||||
detune ??= pv(params.detune, i);
|
||||
freqspread ??= pv(params.freqspread, i);
|
||||
@@ -1154,7 +1149,6 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||
{ name: 'warp', defaultValue: 0, min: 0, max: 1 },
|
||||
{ name: 'warpMode', defaultValue: 0 },
|
||||
{ name: 'panspread', defaultValue: 0.7, min: 0, max: 1 },
|
||||
{ name: 'postgain', defaultValue: 1, min: 0 },
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1187,7 +1181,7 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||
phases[i] = Math.random() * phaseRand;
|
||||
}
|
||||
this.voices = options.voices;
|
||||
this.voicesDenom = 1 / Math.sqrt(this.voices);
|
||||
this.normalizer = 1 / Math.sqrt(this.voices);
|
||||
}
|
||||
|
||||
_mirror(x) {
|
||||
@@ -1364,8 +1358,6 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||
const interpT = idx - fIdx;
|
||||
const warpAmount = clamp(pv(params.warp, i), 0, 1);
|
||||
const warpMode = pv(params.warpMode, i);
|
||||
const postgain = pv(params.postgain, i);
|
||||
const normalizer = postgain * this.voicesDenom;
|
||||
panspread ??= this.voices > 1 ? clamp(pv(params.panspread, i), 0, 1) : 0;
|
||||
gainL ??= Math.sqrt(0.5 - 0.5 * panspread);
|
||||
gainR ??= Math.sqrt(0.5 + 0.5 * panspread);
|
||||
@@ -1384,8 +1376,8 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||
if (warpMode === WarpMode.FLIP && this.phases[n] < warpAmount) {
|
||||
s = -s;
|
||||
}
|
||||
outL[i] += s * gainL * normalizer;
|
||||
outR[i] += s * gainR * normalizer;
|
||||
outL[i] += s * gainL * this.normalizer;
|
||||
outR[i] += s * gainR * this.normalizer;
|
||||
this.phases[n] = frac(this.phases[n] + dPhase);
|
||||
// invert right and left gain
|
||||
const tmp = gainL;
|
||||
|
||||
Reference in New Issue
Block a user