Compare commits

..

6 Commits

Author SHA1 Message Date
froos 7179066a68 Merge branch 'main' into daslyfe/jade/rescurve 2025-10-20 20:39:35 +02:00
Jade (Rose) Rowland fe5cebc435 add res curve setter 2025-07-08 22:39:31 -04:00
Felix Roos 2ea0053edf Merge branch 'main' into daslyfe/jade/rescurve 2025-07-06 21:43:35 +02:00
Jade (Rose) Rowland 3f76da7ad8 Merge branch 'main' into daslyfe/jade/rescurve 2025-06-27 15:58:43 -04:00
Jade (Rose) Rowland 4e6ca54ef3 lint 2025-05-02 22:51:44 -04:00
Jade (Rose) Rowland 525f5d87d1 adj resonance 2025-05-02 22:50:00 -04:00
4 changed files with 23 additions and 68 deletions
-17
View File
@@ -2320,23 +2320,6 @@ export const { miditouch } = registerControl('miditouch');
// TODO: what is this?
export const { polyTouch } = registerControl('polyTouch');
/**
* Checks if a control name exists in the controlAlias map.
* @name hasControlName
* @param {string} alias The control name to check
* @returns {boolean} True if the control name exists, false otherwise
*/
export const hasControlName = (alias) => {
// Check if the name exists as a key (alias) or value (main control name)
return controlAlias.has(alias) || Array.from(controlAlias.values()).includes(alias);
};
/**
* Gets the control name from the controlAlias map.
* @name getControlName
* @param {string} alias The control name to get
* @returns {string} The control name
*/
export const getControlName = (alias) => {
if (controlAlias.has(alias)) {
return controlAlias.get(alias);
-8
View File
@@ -8,14 +8,6 @@ This package adds midi functionality to strudel Patterns.
npm i @strudel/midi --save
```
## Enabling MIDI for Local Development in Chrome
1. Open Chrome and navigate to `chrome://flags`
2. Search for "Insecure origins treated as secure"
3. In the text field that appears, add your development origin (e.g., http://localhost:3000)
4. Enable the flag
5. Restart Chrome
## Available Controls
The following MIDI controls are available:
+7 -40
View File
@@ -6,7 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th
import * as _WebMidi from 'webmidi';
import { Pattern, getEventOffsetMs, isPattern, logger, ref } from '@strudel/core';
import { noteToMidi, hasControlName, getControlName, registerControl } from '@strudel/core';
import { noteToMidi, getControlName } from '@strudel/core';
import { Note } from 'webmidi';
// if you use WebMidi from outside of this package, make sure to import that instance:
@@ -100,34 +100,10 @@ export const midicontrolMap = new Map();
function unifyMapping(mapping) {
return Object.fromEntries(
Object.entries(mapping).map(([key, mapping]) => {
// Convert number to object with ccn property
if (typeof mapping === 'number') {
mapping = { ccn: mapping };
}
// Get the non-aliased control name from the key
const controlName = getControlName(key);
// Check if the key or controlName already exists in the controlAlias map
if (hasControlName(key) || hasControlName(controlName)) {
// Show warning and carry on.
logger(`[midimap] '[${key}, ${controlName}]' overwrites a Strudel API.`);
// Throw error to stop the music
//throw new Error(`[midimap] '${key}' overwrites a Strudel API.`);
}
// Register the control in the midicontrolMap if it doesn't exist
if (!midicontrolMap.has(controlName)) {
try {
registerControl(controlName);
} catch (err) {
throw new Error(`[midimap] Failed to register midimap control '${controlName}': ${err.message}`);
}
} else {
logger(`[midimap] '${controlName}' already registered as a midimap control. Skipping registration.`);
}
return [controlName, mapping];
return [getControlName(key), mapping];
}),
);
}
@@ -186,14 +162,7 @@ export async function midimaps(map) {
map = await loadCache[map];
}
if (typeof map === 'object') {
Object.entries(map).forEach(([name, mapping]) => {
try {
midicontrolMap.set(name, unifyMapping(mapping));
} catch (err) {
logger(`[midi] Error setting midimap '${name}': ${err.message}`);
throw err;
}
});
Object.entries(map).forEach(([name, mapping]) => midicontrolMap.set(name, unifyMapping(mapping)));
}
}
@@ -355,18 +324,18 @@ Pattern.prototype.midi = function (midiport, options = {}) {
const device = getDevice(midiConfig.midiport, outputs);
const otherOutputs = outputs.filter((o) => o.name !== device.name);
logger(
`[midi] Midi enabled! Using "${device.name}". ${
`Midi enabled! Using "${device.name}". ${
otherOutputs?.length ? `Also available: ${getMidiDeviceNamesString(otherOutputs)}` : ''
}`,
);
},
onDisconnected: ({ outputs }) =>
logger(`[midi] Midi device disconnected! Available: ${getMidiDeviceNamesString(outputs)}`),
logger(`Midi device disconnected! Available: ${getMidiDeviceNamesString(outputs)}`),
});
return this.onTrigger((hap, currentTime, cps, targetTime) => {
if (!WebMidi.enabled) {
logger('[midi] Midi not enabled');
logger('Midi not enabled');
return;
}
hap.ensureObjectValue();
@@ -414,9 +383,7 @@ Pattern.prototype.midi = function (midiport, options = {}) {
ccs.forEach(({ ccn, ccv }) => sendCC(ccn, ccv, device, midichan, timeOffsetString));
} else if (midimap !== 'default') {
// Add warning when a non-existent midimap is specified
throw new Error(
`[midimap] midimap "${midimap}" not found! Available maps: ${[...midicontrolMap.keys()].join(', ')}`,
);
logger(`[midi] midimap "${midimap}" not found! Available maps: ${[...midicontrolMap.keys()].join(', ')}`);
}
// Handle note
+16 -3
View File
@@ -148,9 +148,9 @@ let defaultDefaultValues = {
density: '.03',
ftype: '12db',
fanchor: 0,
resonance: 1,
hresonance: 1,
bandq: 1,
resonance: 0.183,
hresonance: 0.183,
bandq: 0.183,
channels: [1, 2],
phaserdepth: 0.75,
shapevol: 1,
@@ -207,6 +207,16 @@ export function registerWorklet(url) {
externalWorklets.push(url);
}
let resCurveFunc = (res) => Math.min(30.03, Math.pow(res * 5.48, 2));
export function setResCurve(newFunc) {
resCurveFunc = newFunc;
}
function applyResonanceCurve(res) {
return resCurveFunc(res);
}
let workletsLoading;
function loadWorklets() {
if (!workletsLoading) {
@@ -483,6 +493,9 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
compressorRelease,
} = value;
resonance = applyResonanceCurve(resonance);
hresonance = applyResonanceCurve(hresonance);
bandq = applyResonanceCurve(bandq);
delaytime = delaytime ?? cycleToSeconds(delaysync, cps);
const orbitChannels = mapChannelNumbers(