mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-28 15:46:51 -04:00
Move fns to util file; optimized clamp
This commit is contained in:
@@ -253,7 +253,12 @@ export const pairs = function (xs) {
|
||||
return result;
|
||||
};
|
||||
|
||||
export const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||
// Optimized clamp (~1.7x faster than Math.max/min approach)
|
||||
export const clamp = (num, min, max) => {
|
||||
if (num < min) return min;
|
||||
if (num > max) return max;
|
||||
return num;
|
||||
};
|
||||
|
||||
/* solmization, not used yet */
|
||||
const solfeggio = ['Do', 'Reb', 'Re', 'Mib', 'Mi', 'Fa', 'Solb', 'Sol', 'Lab', 'La', 'Sib', 'Si']; /*solffegio notes*/
|
||||
|
||||
@@ -3,6 +3,8 @@ import { logger } from './logger.mjs';
|
||||
// currently duplicate with core util.mjs to skip dependency
|
||||
// TODO: add separate util module?
|
||||
|
||||
export const LN2 = Math.LN2;
|
||||
|
||||
export const tokenizeNote = (note) => {
|
||||
if (typeof note !== 'string') {
|
||||
return [];
|
||||
@@ -32,10 +34,9 @@ export const noteToMidi = (note, defaultOctave = 3) => {
|
||||
export const midiToFreq = (n) => {
|
||||
return Math.pow(2, (n - 69) / 12) * 440;
|
||||
};
|
||||
export const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||
|
||||
export const freqToMidi = (freq) => {
|
||||
return (12 * Math.log(freq / 440)) / Math.LN2 + 69;
|
||||
return (12 * Math.log(freq / 440)) / LN2 + 69;
|
||||
};
|
||||
|
||||
export const valueToMidi = (value, fallbackValue) => {
|
||||
@@ -114,3 +115,38 @@ export function getCommonSampleInfo(hapValue, bank) {
|
||||
export const pickAndRename = (source, map) => {
|
||||
return Object.fromEntries(Object.entries(map).map(([newKey, oldKey]) => [newKey, source[oldKey]]));
|
||||
};
|
||||
|
||||
// Optimized / numerical functions (ideal for hot dsp loops)
|
||||
|
||||
// Optimized clamp (~1.7x faster than Math.max/min approach)
|
||||
export const clamp = (num, min, max) => {
|
||||
if (num < min) return min;
|
||||
if (num > max) return max;
|
||||
return num;
|
||||
};
|
||||
export const mod = (n, m) => ((n % m) + m) % m;
|
||||
export const lerp = (a, b, n) => n * (b - a) + a;
|
||||
export const frac = (x) => x - Math.floor(x);
|
||||
|
||||
// Fast integer ops for non-negative values
|
||||
export const ffloor = (x) => x | 0;
|
||||
export const fround = (x) => ffloor(x + 0.5);
|
||||
export const fceil = (x) => ffloor(x + 1);
|
||||
export const ffrac = (x) => x - ffloor(x);
|
||||
|
||||
export const fastexpm1 = (x) => x * (1 + x + 0.5 * x * x); // Taylor approximation
|
||||
|
||||
export const fastpow2 = (x) => {
|
||||
// Taylor approximation of 2 ^ x
|
||||
const a = x * LN2;
|
||||
return 1 + a * (1 + a * (0.5 + a / 6));
|
||||
};
|
||||
|
||||
export const applySemitoneDetuneToFrequency = (frequency, detune) => {
|
||||
return frequency * Math.pow(2, detune / 12);
|
||||
};
|
||||
|
||||
export const applyFastDetune = (frequency, detune) => {
|
||||
if (detune < 4) return frequency * fastpow2(detune / 12);
|
||||
return applySemitoneDetuneToFrequency(frequency, detune);
|
||||
};
|
||||
|
||||
@@ -5,6 +5,18 @@
|
||||
import OLAProcessor from './ola-processor';
|
||||
import FFT from './fft.js';
|
||||
import { getDistortionAlgorithm } from './helpers.mjs';
|
||||
import {
|
||||
applyFastDetune,
|
||||
applySemitoneDetuneToFrequency,
|
||||
clamp,
|
||||
fastexpm1,
|
||||
fceil,
|
||||
ffloor,
|
||||
ffrac,
|
||||
frac,
|
||||
fround,
|
||||
lerp,
|
||||
} from './util.mjs';
|
||||
|
||||
const blockSize = 128;
|
||||
const PI = Math.PI;
|
||||
@@ -12,23 +24,11 @@ const TWO_PI = 2 * PI;
|
||||
const INVSR = 1 / sampleRate;
|
||||
const MAX_VOICES = 64;
|
||||
|
||||
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||
const mod = (n, m) => ((n % m) + m) % m;
|
||||
const lerp = (a, b, n) => n * (b - a) + a;
|
||||
const pv = (arr, n) => arr[n] ?? arr[0];
|
||||
const frac = (x) => x - Math.floor(x);
|
||||
|
||||
// Fast integer ops for non-negative values
|
||||
const ffloor = (x) => x | 0;
|
||||
const fround = (x) => ffloor(x + 0.5);
|
||||
const fceil = (x) => ffloor(x + 1);
|
||||
const ffrac = (x) => x - ffloor(x);
|
||||
|
||||
const fast_tanh = (x) => {
|
||||
const x2 = x * x;
|
||||
return (x * (27 + x2)) / (27 + 9 * x2);
|
||||
};
|
||||
const fastexpm1 = (x) => x * (1 + x + 0.5 * x * x); // Taylor approximation
|
||||
|
||||
// Optimized per-voice detuner which precomputes constants
|
||||
const getDetuner = (unison, detune) => {
|
||||
@@ -40,21 +40,6 @@ const getDetuner = (unison, detune) => {
|
||||
return (voiceIdx) => voiceIdx * scale - center;
|
||||
};
|
||||
|
||||
function fastPow2(x) {
|
||||
// Taylor approximation of 2 ^ x
|
||||
const a = x * 0.6931471805599453; // ln(2)
|
||||
return 1 + a * (1 + a * (0.5 + a / 6));
|
||||
}
|
||||
|
||||
const applySemitoneDetuneToFrequency = (frequency, detune) => {
|
||||
return frequency * Math.pow(2, detune / 12);
|
||||
};
|
||||
|
||||
const applyFastDetune = (frequency, detune) => {
|
||||
if (detune < 4) return frequency * fastPow2(detune / 12);
|
||||
return applySemitoneDetuneToFrequency(frequency, detune);
|
||||
};
|
||||
|
||||
// Smooth waveshape near discontinuities to remove frequencies above Nyquist and prevent aliasing
|
||||
// referenced from https://www.kvraudio.com/forum/viewtopic.php?t=375517
|
||||
function polyBlep(phase, dt) {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { Dough } from './dough.mjs';
|
||||
|
||||
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||
const clamp = (num, min, max) => {
|
||||
if (num < min) return min;
|
||||
if (num > max) return max;
|
||||
return num;
|
||||
};
|
||||
|
||||
class DoughProcessor extends AudioWorkletProcessor {
|
||||
constructor() {
|
||||
|
||||
@@ -6,7 +6,11 @@ const PI_DIV_SR = Math.PI / SAMPLE_RATE;
|
||||
const ISR = 1 / SAMPLE_RATE;
|
||||
|
||||
let gainCurveFunc = (val) => Math.pow(val, 2);
|
||||
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||
const clamp = (num, min, max) => {
|
||||
if (num < min) return min;
|
||||
if (num > max) return max;
|
||||
return num;
|
||||
};
|
||||
|
||||
function applyGainCurve(val) {
|
||||
return gainCurveFunc(val);
|
||||
|
||||
Reference in New Issue
Block a user