Compare commits

..

1 Commits

Author SHA1 Message Date
Jade (Rose) Rowland 40930d8515 better defaults 2025-11-26 12:04:10 -05:00
7 changed files with 28 additions and 69 deletions
+2 -2
View File
@@ -25,7 +25,7 @@ import {
stringifyValues,
} from './util.mjs';
import drawLine from './drawLine.mjs';
import { errorLogger, logger } from './logger.mjs';
import { logger } from './logger.mjs';
let stringParser;
@@ -414,7 +414,7 @@ export class Pattern {
try {
return this.query(new State(new TimeSpan(begin, end), controls));
} catch (err) {
errorLogger(err, 'query');
logger(`[query]: ${err.message}`, 'error');
return [];
}
}
-1
View File
@@ -35,7 +35,6 @@ export async function initHydra(options = {}) {
hydra.synth.s0.init({ src: canvas });
}
}
return hydra;
}
export function clearHydra() {
+2 -2
View File
@@ -263,8 +263,8 @@ let audioReady;
export async function initAudioOnFirstClick(options) {
if (!audioReady) {
audioReady = new Promise((resolve) => {
document.addEventListener('mousedown', async function listener() {
document.removeEventListener('mousedown', listener);
document.addEventListener('click', async function listener() {
document.removeEventListener('click', listener);
await initAudio(options);
resolve();
});
+2 -2
View File
@@ -85,7 +85,7 @@ export class Orbit {
return effectSend(node, this.delayNode, amount);
}
duck(t, onsettime = 0, attacktime = 0.1, depth = 1) {
duck(t, onsettime = 0, attacktime = 0.16, depth = 0.8) {
const onset = onsettime;
const attack = Math.max(attacktime, 0.002);
const gainParam = this.output.gain;
@@ -178,7 +178,7 @@ export class SuperdoughAudioController {
this.output.reset();
}
duck(targetOrbits, t, onsettime = 0, attacktime = 0.1, depth = 1) {
duck(targetOrbits, t, onsettime = 0, attacktime = 0.16, depth = 0.8) {
const targetArr = [targetOrbits].flat();
const onsetArr = [onsettime].flat();
const attackArr = [attacktime].flat();
+5 -17
View File
@@ -45,8 +45,7 @@ if (typeof GainNode !== 'undefined') {
throw new Error('vowel: unknown vowel ' + letter);
}
const { gains, qs, freqs } = vowelFormant[letter];
this.makeupGain = ac.createGain();
this.audioNodes = [];
const makeupGain = ac.createGain();
for (let i = 0; i < 5; i++) {
const gain = ac.createGain();
gain.gain.value = gains[i];
@@ -54,25 +53,14 @@ if (typeof GainNode !== 'undefined') {
filter.type = 'bandpass';
filter.Q.value = qs[i];
filter.frequency.value = freqs[i];
super.connect(filter);
this.connect(filter);
filter.connect(gain);
this.audioNodes.push(filter);
gain.connect(this.makeupGain);
this.audioNodes.push(gain);
gain.connect(makeupGain);
}
this.makeupGain.gain.value = 8; // how much makeup gain to add?
makeupGain.gain.value = 8; // how much makeup gain to add?
this.connect = (target) => makeupGain.connect(target);
return this;
}
connect(target) {
this.makeupGain.connect(target);
}
disconnect() {
this.makeupGain.disconnect();
this.audioNodes.forEach((n) => n.disconnect());
super.disconnect();
this.makeupGain = null;
this.audioNodes = null;
}
}
AudioContext.prototype.createVowelFilter = function (letter) {
+2 -11
View File
@@ -5,16 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import { Note, Interval, Scale } from '@tonaljs/tonal';
import {
_mod,
errorLogger,
getAccidentalsOffset,
isNote,
logger,
noteToMidi,
register,
removeUndefineds,
} from '@strudel/core';
import { register, _mod, logger, isNote, noteToMidi, removeUndefineds, getAccidentalsOffset } from '@strudel/core';
import { stepInNamedScale, nearestNumberIndex } from './tonleiter.mjs';
const octavesInterval = (octaves) => (octaves <= 0 ? -1 : 1) + octaves * 7 + 'P';
@@ -303,7 +294,7 @@ export const scale = register(
}
if (offset != 0) scaleNote = Note.transpose(scaleNote, Interval.fromSemitones(offset));
} catch (err) {
errorLogger(err, 'tonal');
logger(`[tonal] ${err.message}`, 'error');
return; // will be removed
}
}
+15 -34
View File
@@ -14,10 +14,6 @@ import { prebake } from '@src/repl/prebake.mjs';
const getSamples = (samples) =>
Array.isArray(samples) ? samples.length : typeof samples === 'object' ? Object.values(samples).length : 1;
function wait(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export function SoundsTab() {
const sounds = useStore(soundMap);
@@ -60,7 +56,9 @@ export function SoundsTab() {
// holds mutable ref to current triggered sound
const trigRef = useRef();
const numRef = useRef(0);
// Used to cycle through sound previews on banks with multiple sounds
let soundPreviewIdx = 0;
// stop current sound on mouseup
useEvent('mouseup', () => {
@@ -68,14 +66,6 @@ export function SoundsTab() {
trigRef.current = undefined;
ref?.stop?.(getAudioContext().currentTime + 0.01);
});
useEvent('keydown', (e) => {
if (!isNaN(Number(e.key))) {
numRef.current = Number(e.key);
}
});
useEvent('keyup', (e) => {
numRef.current = 0;
});
return (
<div id="sounds-tab" className="px-4 flex gap-2 flex-col w-full h-full text-foreground">
<Textbox placeholder="Search" value={search} onChange={(v) => setSearch(v)} />
@@ -125,34 +115,25 @@ export function SoundsTab() {
const params = {
note: ['synth', 'soundfont'].includes(data.type) ? 'a3' : undefined,
s: name,
n: numRef.current,
n: soundPreviewIdx,
clip: 1,
release: 0.5,
sustain: 1,
duration: 0.5,
};
soundPreviewIdx++;
const onended = () => trigRef.current?.node?.disconnect();
// Attempt to play the sample and retry every 200ms until 10 attempts have been reached
let errMsg;
for (let attempt = 0; attempt < 10; attempt++) {
try {
// Pre-load the sample by calling onTrigger with a future time
// This triggers the loading but schedules playback for later
const time = ctx.currentTime + 0.05; // Give 50ms for loading
const ref = await onTrigger(time, params, onended);
trigRef.current = ref;
if (ref?.node) {
connectToDestination(ref.node);
break;
}
} catch (err) {
errMsg = err;
}
if (attempt == 9) {
console.warn('Failed to trigger sound after 10 attempts' + (errMsg ? `: ${errMsg}` : ''));
} else {
await wait(200);
try {
// Pre-load the sample by calling onTrigger with a future time
// This triggers the loading but schedules playback for later
const time = ctx.currentTime + 0.05;
const ref = await onTrigger(time, params, onended);
trigRef.current = ref;
if (ref?.node) {
connectToDestination(ref.node);
}
} catch (err) {
console.warn('Failed to trigger sound:', err);
}
}}
>