Merge branch 'main' into glossing/wavetable-synth

This commit is contained in:
Aria 2025-09-04 20:31:01 -05:00
commit 1205573bc6
10 changed files with 151 additions and 29 deletions

View file

@ -3,8 +3,6 @@
Live coding patterns on the web Live coding patterns on the web
https://strudel.cc/ https://strudel.cc/
Development is moving to https://codeberg.org/uzu/strudel
- Try it here: <https://strudel.cc> - Try it here: <https://strudel.cc>
- Docs: <https://strudel.cc/learn> - Docs: <https://strudel.cc/learn>
- Technical Blog Post: <https://loophole-letters.vercel.app/strudel> - Technical Blog Post: <https://loophole-letters.vercel.app/strudel>
@ -47,3 +45,5 @@ There is a #strudel channel on the TidalCycles discord: <https://discord.com/inv
You can also ask questions and find related discussions on the tidal club forum: <https://club.tidalcycles.org/> You can also ask questions and find related discussions on the tidal club forum: <https://club.tidalcycles.org/>
The discord and forum is shared with the haskell (tidal) and python (vortex) siblings of this project. The discord and forum is shared with the haskell (tidal) and python (vortex) siblings of this project.
We also have a mastodon account: <a rel="me" href="https://social.toplap.org/@strudel">social.toplap.org/@strudel</a>

View file

@ -56,11 +56,13 @@ const buildExamples = (examples) =>
export const Autocomplete = ({ doc, label }) => export const Autocomplete = ({ doc, label }) =>
h` h`
<div class="autocomplete-info-tooltip"> <div class="autocomplete-info-container">
<h3 class="autocomplete-info-function-name">${label || getDocLabel(doc)}</h3> <div class="autocomplete-info-tooltip">
${doc.description ? `<p class="autocomplete-info-function-description">${doc.description}</p>` : ''} <h3 class="autocomplete-info-function-name">${label || getDocLabel(doc)}</h3>
${buildParamsList(doc.params)} ${doc.description ? `<div class="autocomplete-info-function-description">${doc.description}</div>` : ''}
${buildExamples(doc.examples)} ${buildParamsList(doc.params)}
${buildExamples(doc.examples)}
</div>
</div> </div>
`[0]; `[0];
@ -98,4 +100,4 @@ export const strudelAutocomplete = (context) => {
}; };
export const isAutoCompletionEnabled = (enabled) => export const isAutoCompletionEnabled = (enabled) =>
enabled ? [autocompletion({ override: [strudelAutocomplete] })] : []; enabled ? [autocompletion({ override: [strudelAutocomplete], closeOnBlur: false })] : [];

View file

@ -1549,6 +1549,29 @@ export const { roomfade, rfade } = registerControl('roomfade', 'rfade');
* *
*/ */
export const { ir, iresponse } = registerControl(['ir', 'i'], 'iresponse'); export const { ir, iresponse } = registerControl(['ir', 'i'], 'iresponse');
/**
* Sets speed of the sample for the impulse response.
* @name irspeed
* @param {string | Pattern} speed
* @example
* samples('github:switchangel/pad')
* $: s("brk/2").fit().scrub(irand(16).div(16).seg(8)).ir("swpad:4").room(.2).irspeed("<2 1 .5>/2").irbegin(.5).roomsize(.5)
*
*/
export const { irspeed } = registerControl('irspeed');
/**
* Sets the beginning of the IR response sample
* @name irbegin
* @param {string | Pattern} begin between 0 and 1
* @synonyms ir
* @example
* samples('github:switchangel/pad')
* $: s("brk/2").fit().scrub(irand(16).div(16).seg(8)).ir("swpad:4").room(.65).irspeed("-2").irbegin("<0 .5 .75>/2").roomsize(.6)
*
*/
export const { irbegin } = registerControl('irbegin');
/** /**
* Sets the room size of the reverb, see `room`. * Sets the room size of the reverb, see `room`.
* When this property is changed, the reverb will be recaculated, so only change this sparsely.. * When this property is changed, the reverb will be recaculated, so only change this sparsely..

View file

@ -6,7 +6,7 @@ let debounce = 1000,
export function errorLogger(e, origin = 'cyclist') { export function errorLogger(e, origin = 'cyclist') {
//TODO: add some kind of debug flag that enables this while in dev mode //TODO: add some kind of debug flag that enables this while in dev mode
// console.error(e); console.error(e);
logger(`[${origin}] error: ${e.message}`); logger(`[${origin}] error: ${e.message}`);
} }

View file

@ -3277,7 +3277,7 @@ export const slice = register(
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @example
* s("bd!8").onTriggerTime((hap) => {console.info(hap)}) * s("bd!8").onTriggerTime((hap) => {console.log(hap)})
*/ */
Pattern.prototype.onTriggerTime = function (func) { Pattern.prototype.onTriggerTime = function (func) {
return this.onTrigger((hap, currentTime, _cps, targetTime) => { return this.onTrigger((hap, currentTime, _cps, targetTime) => {

View file

@ -1,7 +1,9 @@
import reverbGen from './reverbGen.mjs'; import reverbGen from './reverbGen.mjs';
import { clamp } from './util.mjs';
if (typeof AudioContext !== 'undefined') { if (typeof AudioContext !== 'undefined') {
AudioContext.prototype.adjustLength = function (duration, buffer) { AudioContext.prototype.adjustLength = function (duration, buffer, speed = 1, offsetAmount = 0) {
const sampleOffset = Math.floor(clamp(offsetAmount, 0, 1) * buffer.length);
const newLength = buffer.sampleRate * duration; const newLength = buffer.sampleRate * duration;
const newBuffer = this.createBuffer(buffer.numberOfChannels, buffer.length, buffer.sampleRate); const newBuffer = this.createBuffer(buffer.numberOfChannels, buffer.length, buffer.sampleRate);
for (let channel = 0; channel < buffer.numberOfChannels; channel++) { for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
@ -9,22 +11,30 @@ if (typeof AudioContext !== 'undefined') {
let newData = newBuffer.getChannelData(channel); let newData = newBuffer.getChannelData(channel);
for (let i = 0; i < newLength; i++) { for (let i = 0; i < newLength; i++) {
newData[i] = oldData[i] || 0; // loop the buffer around to prevent
let position = (sampleOffset + i * Math.abs(speed)) % oldData.length;
if (speed < 1) {
position = position * -1;
}
newData[i] = oldData.at(position) || 0;
} }
} }
return newBuffer; return newBuffer;
}; };
AudioContext.prototype.createReverb = function (duration, fade, lp, dim, ir) { AudioContext.prototype.createReverb = function (duration, fade, lp, dim, ir, irspeed, irbegin) {
const convolver = this.createConvolver(); const convolver = this.createConvolver();
convolver.generate = (d = 2, fade = 0.1, lp = 15000, dim = 1000, ir) => { convolver.generate = (d = 2, fade = 0.1, lp = 15000, dim = 1000, ir, irspeed, irbegin) => {
convolver.duration = d; convolver.duration = d;
convolver.fade = fade; convolver.fade = fade;
convolver.lp = lp; convolver.lp = lp;
convolver.dim = dim; convolver.dim = dim;
convolver.ir = ir; convolver.ir = ir;
convolver.irspeed = irspeed;
convolver.irbegin = irbegin;
if (ir) { if (ir) {
convolver.buffer = this.adjustLength(d, ir); convolver.buffer = this.adjustLength(d, ir, irspeed, irbegin);
} else { } else {
reverbGen.generateReverb( reverbGen.generateReverb(
{ {
@ -41,7 +51,7 @@ if (typeof AudioContext !== 'undefined') {
); );
} }
}; };
convolver.generate(duration, fade, lp, dim, ir); convolver.generate(duration, fade, lp, dim, ir, irspeed, irbegin);
return convolver; return convolver;
}; };
} }

View file

@ -282,7 +282,6 @@ export async function initAudioOnFirstClick(options) {
return audioReady; return audioReady;
} }
let delays = {};
const maxfeedback = 0.98; const maxfeedback = 0.98;
let channelMerger, destinationGain; let channelMerger, destinationGain;
@ -326,7 +325,7 @@ export const panic = () => {
channelMerger == null; channelMerger == null;
}; };
function getDelay(orbit, delaytime, delayfeedback, t, channels) { function getDelay(orbit, delaytime, delayfeedback, t) {
if (delayfeedback > maxfeedback) { if (delayfeedback > maxfeedback) {
//logger(`delayfeedback was clamped to ${maxfeedback} to save your ears`); //logger(`delayfeedback was clamped to ${maxfeedback} to save your ears`);
} }
@ -442,19 +441,22 @@ function duckOrbit(audioContext, targetOrbit, t, attacktime = 0.1, duckdepth = 1
} }
let hasChanged = (now, before) => now !== undefined && now !== before; let hasChanged = (now, before) => now !== undefined && now !== before;
function getReverb(orbit, duration, fade, lp, dim, ir) { function getReverb(orbit, duration, fade, lp, dim, ir, irspeed, irbegin) {
// If no reverb has been created for a given orbit, create one // If no reverb has been created for a given orbit, create one
if (!orbits[orbit].reverbNode) { if (!orbits[orbit].reverbNode) {
const ac = getAudioContext(); const ac = getAudioContext();
const reverb = ac.createReverb(duration, fade, lp, dim, ir); const reverb = ac.createReverb(duration, fade, lp, dim, ir, irspeed, irbegin);
connectToOrbit(reverb, orbit); connectToOrbit(reverb, orbit);
orbits[orbit].reverbNode = reverb; orbits[orbit].reverbNode = reverb;
} }
if ( if (
hasChanged(duration, orbits[orbit].reverbNode.duration) || hasChanged(duration, orbits[orbit].reverbNode.duration) ||
hasChanged(fade, orbits[orbit].reverbNode.fade) || hasChanged(fade, orbits[orbit].reverbNode.fade) ||
hasChanged(lp, orbits[orbit].reverbNode.lp) || hasChanged(lp, orbits[orbit].reverbNode.lp) ||
hasChanged(dim, orbits[orbit].reverbNode.dim) || hasChanged(dim, orbits[orbit].reverbNode.dim) ||
hasChanged(irspeed, orbits[orbit].reverbNode.irspeed) ||
hasChanged(irbegin, orbits[orbit].reverbNode.irbegin) ||
orbits[orbit].reverbNode.ir !== ir orbits[orbit].reverbNode.ir !== ir
) { ) {
// only regenerate when something has changed // only regenerate when something has changed
@ -462,7 +464,7 @@ function getReverb(orbit, duration, fade, lp, dim, ir) {
// stack(s("a"), s("b").rsize(8)).room(.5) // stack(s("a"), s("b").rsize(8)).room(.5)
// this only works when args may stay undefined until here // this only works when args may stay undefined until here
// setting default values breaks this // setting default values breaks this
orbits[orbit].reverbNode.generate(duration, fade, lp, dim, ir); orbits[orbit].reverbNode.generate(duration, fade, lp, dim, ir, irspeed, irbegin);
} }
return orbits[orbit].reverbNode; return orbits[orbit].reverbNode;
} }
@ -620,6 +622,8 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
roomdim, roomdim,
roomsize, roomsize,
ir, ir,
irspeed,
irbegin,
i = getDefaultValue('i'), i = getDefaultValue('i'),
velocity = getDefaultValue('velocity'), velocity = getDefaultValue('velocity'),
analyze, // analyser wet analyze, // analyser wet
@ -836,7 +840,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
// delay // delay
let delaySend; let delaySend;
if (delay > 0 && delaytime > 0 && delayfeedback > 0) { if (delay > 0 && delaytime > 0 && delayfeedback > 0) {
const delayNode = getDelay(orbit, delaytime, delayfeedback, t, orbitChannels); const delayNode = getDelay(orbit, delaytime, delayfeedback, t);
delaySend = effectSend(post, delayNode, delay); delaySend = effectSend(post, delayNode, delay);
audioNodes.push(delaySend); audioNodes.push(delaySend);
} }
@ -854,7 +858,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
} }
roomIR = await loadBuffer(url, ac, ir, 0); roomIR = await loadBuffer(url, ac, ir, 0);
} }
const reverbNode = getReverb(orbit, roomsize, roomfade, roomlp, roomdim, roomIR, orbitChannels); const reverbNode = getReverb(orbit, roomsize, roomfade, roomlp, roomdim, roomIR, irspeed, irbegin);
reverbSend = effectSend(post, reverbNode, room); reverbSend = effectSend(post, reverbNode, room);
audioNodes.push(reverbSend); audioNodes.push(reverbSend);
} }

View file

@ -4875,6 +4875,43 @@ exports[`runs examples > example "irand" example index 0 1`] = `
] ]
`; `;
exports[`runs examples > example "irbegin" example index 0 1`] = `
[
"[ 0/1 → 1/8 | s:brk speed:0.5 unit:c begin:0 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 1/8 → 1/4 | s:brk speed:0.5 unit:c begin:0.625 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 1/4 → 3/8 | s:brk speed:0.5 unit:c begin:0.3125 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 3/8 → 1/2 | s:brk speed:0.5 unit:c begin:0.375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 1/2 → 5/8 | s:brk speed:0.5 unit:c begin:0.25 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 5/8 → 3/4 | s:brk speed:0.5 unit:c begin:0.125 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 3/4 → 7/8 | s:brk speed:0.5 unit:c begin:0.1875 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 7/8 → 1/1 | s:brk speed:0.5 unit:c begin:0.375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 1/1 → 9/8 | s:brk speed:0.5 unit:c begin:0.5 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 9/8 → 5/4 | s:brk speed:0.5 unit:c begin:0.625 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 5/4 → 11/8 | s:brk speed:0.5 unit:c begin:0.6875 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 11/8 → 3/2 | s:brk speed:0.5 unit:c begin:0.125 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 3/2 → 13/8 | s:brk speed:0.5 unit:c begin:0.5625 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 13/8 → 7/4 | s:brk speed:0.5 unit:c begin:0.4375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 7/4 → 15/8 | s:brk speed:0.5 unit:c begin:0.1875 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 15/8 → 2/1 | s:brk speed:0.5 unit:c begin:0.5625 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0 roomsize:0.6 ]",
"[ 2/1 → 17/8 | s:brk speed:0.5 unit:c begin:0.9375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 17/8 → 9/4 | s:brk speed:0.5 unit:c begin:0.875 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 9/4 → 19/8 | s:brk speed:0.5 unit:c begin:0.3125 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 19/8 → 5/2 | s:brk speed:0.5 unit:c begin:0.8125 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 5/2 → 21/8 | s:brk speed:0.5 unit:c begin:0.4375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 21/8 → 11/4 | s:brk speed:0.5 unit:c begin:0.125 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 11/4 → 23/8 | s:brk speed:0.5 unit:c begin:0.625 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 23/8 → 3/1 | s:brk speed:0.5 unit:c begin:0 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 3/1 → 25/8 | s:brk speed:0.5 unit:c begin:0.1875 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 25/8 → 13/4 | s:brk speed:0.5 unit:c begin:0.3125 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 13/4 → 27/8 | s:brk speed:0.5 unit:c begin:0.9375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 27/8 → 7/2 | s:brk speed:0.5 unit:c begin:0.375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 7/2 → 29/8 | s:brk speed:0.5 unit:c begin:0.375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 29/8 → 15/4 | s:brk speed:0.5 unit:c begin:0.9375 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 15/4 → 31/8 | s:brk speed:0.5 unit:c begin:0.75 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
"[ 31/8 → 4/1 | s:brk speed:0.5 unit:c begin:0.6875 clip:1 ir:swpad i:4 room:0.65 irspeed:-2 irbegin:0.5 roomsize:0.6 ]",
]
`;
exports[`runs examples > example "iresponse" example index 0 1`] = ` exports[`runs examples > example "iresponse" example index 0 1`] = `
[ [
"[ 0/1 → 1/4 | s:bd room:0.8 ir:shaker_large i:0 ]", "[ 0/1 → 1/4 | s:bd room:0.8 ir:shaker_large i:0 ]",
@ -4896,6 +4933,43 @@ exports[`runs examples > example "iresponse" example index 0 1`] = `
] ]
`; `;
exports[`runs examples > example "irspeed" example index 0 1`] = `
[
"[ 0/1 → 1/8 | s:brk speed:0.5 unit:c begin:0 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 1/8 → 1/4 | s:brk speed:0.5 unit:c begin:0.625 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 1/4 → 3/8 | s:brk speed:0.5 unit:c begin:0.3125 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 3/8 → 1/2 | s:brk speed:0.5 unit:c begin:0.375 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 1/2 → 5/8 | s:brk speed:0.5 unit:c begin:0.25 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 5/8 → 3/4 | s:brk speed:0.5 unit:c begin:0.125 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 3/4 → 7/8 | s:brk speed:0.5 unit:c begin:0.1875 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 7/8 → 1/1 | s:brk speed:0.5 unit:c begin:0.375 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 1/1 → 9/8 | s:brk speed:0.5 unit:c begin:0.5 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 9/8 → 5/4 | s:brk speed:0.5 unit:c begin:0.625 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 5/4 → 11/8 | s:brk speed:0.5 unit:c begin:0.6875 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 11/8 → 3/2 | s:brk speed:0.5 unit:c begin:0.125 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 3/2 → 13/8 | s:brk speed:0.5 unit:c begin:0.5625 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 13/8 → 7/4 | s:brk speed:0.5 unit:c begin:0.4375 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 7/4 → 15/8 | s:brk speed:0.5 unit:c begin:0.1875 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 15/8 → 2/1 | s:brk speed:0.5 unit:c begin:0.5625 clip:1 ir:swpad i:4 room:0.2 irspeed:2 irbegin:0.5 roomsize:0.5 ]",
"[ 2/1 → 17/8 | s:brk speed:0.5 unit:c begin:0.9375 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 17/8 → 9/4 | s:brk speed:0.5 unit:c begin:0.875 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 9/4 → 19/8 | s:brk speed:0.5 unit:c begin:0.3125 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 19/8 → 5/2 | s:brk speed:0.5 unit:c begin:0.8125 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 5/2 → 21/8 | s:brk speed:0.5 unit:c begin:0.4375 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 21/8 → 11/4 | s:brk speed:0.5 unit:c begin:0.125 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 11/4 → 23/8 | s:brk speed:0.5 unit:c begin:0.625 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 23/8 → 3/1 | s:brk speed:0.5 unit:c begin:0 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 3/1 → 25/8 | s:brk speed:0.5 unit:c begin:0.1875 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 25/8 → 13/4 | s:brk speed:0.5 unit:c begin:0.3125 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 13/4 → 27/8 | s:brk speed:0.5 unit:c begin:0.9375 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 27/8 → 7/2 | s:brk speed:0.5 unit:c begin:0.375 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 7/2 → 29/8 | s:brk speed:0.5 unit:c begin:0.375 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 29/8 → 15/4 | s:brk speed:0.5 unit:c begin:0.9375 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 15/4 → 31/8 | s:brk speed:0.5 unit:c begin:0.75 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
"[ 31/8 → 4/1 | s:brk speed:0.5 unit:c begin:0.6875 clip:1 ir:swpad i:4 room:0.2 irspeed:1 irbegin:0.5 roomsize:0.5 ]",
]
`;
exports[`runs examples > example "isaw" example index 0 1`] = ` exports[`runs examples > example "isaw" example index 0 1`] = `
[ [
"[ 0/1 → 1/8 | note:c3 clip:1 ]", "[ 0/1 → 1/8 | note:c3 clip:1 ]",

View file

@ -72,21 +72,19 @@
/* Override default styles from the codemirror inline css for autocomplete info tooltip*/ /* Override default styles from the codemirror inline css for autocomplete info tooltip*/
.cm-tooltip.cm-completionInfo { .cm-tooltip.cm-completionInfo {
padding: 12px !important; padding: 0 !important;
padding-bottom: 12px !important;
border: 1px solid var(--foreground) !important; border: 1px solid var(--foreground) !important;
border-radius: 4px !important; border-radius: 4px !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
max-width: 500px !important; max-width: 500px !important;
min-width: 300px !important; min-width: 300px !important;
max-height: 400px !important; max-height: 400px !important;
white-space: normal !important;
overflow: auto !important;
background-color: var(--lineHighlight) !important; background-color: var(--lineHighlight) !important;
} }
/* Main tooltip container */ /* Main tooltip container */
.autocomplete-info-tooltip { .autocomplete-info-container {
padding: 12px !important;
border-radius: 4px !important; border-radius: 4px !important;
color: var(--foreground); color: var(--foreground);
font-family: var(--font-family, 'SF Mono', 'Monaco', monospace); font-family: var(--font-family, 'SF Mono', 'Monaco', monospace);
@ -95,6 +93,16 @@
max-width: 600px; max-width: 600px;
max-height: 400px; max-height: 400px;
min-width: 400px; min-width: 400px;
white-space: normal !important;
overflow-y: auto !important;
}
.autocomplete-info-tooltip {
overflow-y: auto !important;
}
.autocomplete-info-function-description {
white-space: pre-wrap !important;
} }
.autocomplete-info-function-name { .autocomplete-info-function-name {

View file

@ -311,7 +311,8 @@ export function SettingsTab({ started }) {
onClick={() => { onClick={() => {
confirmDialog('Sure?').then((r) => { confirmDialog('Sure?').then((r) => {
if (r) { if (r) {
settingsMap.set(defaultSettings); const { userPatterns } = settingsMap.get(); // keep current patterns
settingsMap.set({...defaultSettings, userPatterns});
} }
}); });
}} }}