working
This commit is contained in:
parent
0d900c0134
commit
3159f66560
2 changed files with 82 additions and 73 deletions
|
|
@ -261,7 +261,6 @@ export function resetGlobalEffects() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const superdough = async (value, t, hapDuration, cps, cycle) => {
|
export const superdough = async (value, t, hapDuration, cps, cycle) => {
|
||||||
console.log({ cps, cycle });
|
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
if (typeof value !== 'object') {
|
if (typeof value !== 'object') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
@ -282,6 +281,8 @@ export const superdough = async (value, t, hapDuration, cps, cycle) => {
|
||||||
}
|
}
|
||||||
// destructure
|
// destructure
|
||||||
let {
|
let {
|
||||||
|
amdepth = 1,
|
||||||
|
amshape = 'tri',
|
||||||
s = 'triangle',
|
s = 'triangle',
|
||||||
bank,
|
bank,
|
||||||
source,
|
source,
|
||||||
|
|
@ -326,6 +327,7 @@ export const superdough = async (value, t, hapDuration, cps, cycle) => {
|
||||||
gainmod,
|
gainmod,
|
||||||
crush,
|
crush,
|
||||||
shape,
|
shape,
|
||||||
|
|
||||||
shapevol = 1,
|
shapevol = 1,
|
||||||
distort,
|
distort,
|
||||||
distortvol = 1,
|
distortvol = 1,
|
||||||
|
|
@ -472,7 +474,16 @@ export const superdough = async (value, t, hapDuration, cps, cycle) => {
|
||||||
crush !== undefined && chain.push(getWorklet(ac, 'crush-processor', { crush }));
|
crush !== undefined && chain.push(getWorklet(ac, 'crush-processor', { crush }));
|
||||||
shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape, postgain: shapevol }));
|
shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape, postgain: shapevol }));
|
||||||
distort !== undefined && chain.push(getWorklet(ac, 'distort-processor', { distort, postgain: distortvol }));
|
distort !== undefined && chain.push(getWorklet(ac, 'distort-processor', { distort, postgain: distortvol }));
|
||||||
gainmod !== undefined && chain.push(getWorklet(ac, 'gainmod-processor', { speed: gainmod, cps, cycle }));
|
gainmod !== undefined &&
|
||||||
|
chain.push(
|
||||||
|
getWorklet(ac, 'gainmod-processor', {
|
||||||
|
speed: gainmod,
|
||||||
|
// depth: amdepth, shape: amshape,
|
||||||
|
|
||||||
|
cps,
|
||||||
|
cycle,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
compressorThreshold !== undefined &&
|
compressorThreshold !== undefined &&
|
||||||
chain.push(
|
chain.push(
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,70 @@
|
||||||
// coarse, crush, and shape processors adapted from dktr0's webdirt: https://github.com/dktr0/WebDirt/blob/5ce3d698362c54d6e1b68acc47eb2955ac62c793/dist/AudioWorklets.js
|
// coarse, crush, and shape processors adapted from dktr0's webdirt: https://github.com/dktr0/WebDirt/blob/5ce3d698362c54d6e1b68acc47eb2955ac62c793/dist/AudioWorklets.js
|
||||||
// LICENSE GNU General Public License v3.0 see https://github.com/dktr0/WebDirt/blob/main/LICENSE
|
// LICENSE GNU General Public License v3.0 see https://github.com/dktr0/WebDirt/blob/main/LICENSE
|
||||||
|
|
||||||
const linearEnvelope = (startVal, EndVal, startTime, endTime, currentTime, hold = 0) => {
|
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||||
let min = 0.001;
|
// adjust waveshape to remove frequencies above nyquist to prevent aliasing
|
||||||
currentTime = currentTime - hold;
|
// referenced from https://www.kvraudio.com/forum/viewtopic.php?t=375517
|
||||||
if (startTime > currentTime) {
|
function polyBlep(phase, dt) {
|
||||||
return 1;
|
// 0 <= phase < 1
|
||||||
|
if (phase < dt) {
|
||||||
|
phase /= dt;
|
||||||
|
// 2 * (phase - phase^2/2 - 0.5)
|
||||||
|
return phase + phase - phase * phase - 1;
|
||||||
}
|
}
|
||||||
if (currentTime > endTime) {
|
|
||||||
return min;
|
// -1 < phase < 0
|
||||||
|
else if (phase > 1 - dt) {
|
||||||
|
phase = (phase - 1) / dt;
|
||||||
|
// 2 * (phase^2/2 + phase + 0.5)
|
||||||
|
return phase * phase + phase + phase + 1;
|
||||||
}
|
}
|
||||||
// change relative start time to 0 to prevent numeric overflow
|
|
||||||
currentTime = currentTime - startTime;
|
|
||||||
endTime = endTime - startTime;
|
|
||||||
startTime = 0;
|
|
||||||
|
|
||||||
let x1 = startTime;
|
// 0 otherwise
|
||||||
let y1 = startVal;
|
else {
|
||||||
let x2 = endTime;
|
return 0;
|
||||||
let y2 = EndVal;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the growth or decay rate (b)
|
const waveshapes = {
|
||||||
let b = y1 / y2 / (x1 - x2);
|
sine(phase) {
|
||||||
|
return Math.sin(Math.PI * 2 * phase);
|
||||||
|
},
|
||||||
|
custom(phase, values = [0, 1]) {
|
||||||
|
const numParts = values.length - 1;
|
||||||
|
const currPart = Math.floor(phase * numParts);
|
||||||
|
|
||||||
// Calculate the initial value (a)
|
const partLength = 1 / numParts;
|
||||||
let a = y1 / (b * x1);
|
const startVal = clamp(values[currPart], 0, 1);
|
||||||
|
const endVal = clamp(values[currPart + 1], 0, 1);
|
||||||
let x = currentTime;
|
const y2 = endVal;
|
||||||
// calculate y for any x
|
const y1 = startVal;
|
||||||
return a * (b * x);
|
const x1 = 0;
|
||||||
|
const x2 = partLength;
|
||||||
|
const slope = (y2 - y1) / (x2 - x1);
|
||||||
|
return slope * (phase - partLength * currPart) + startVal;
|
||||||
|
},
|
||||||
|
sawblep(phase, dt) {
|
||||||
|
const v = 2 * phase - 1;
|
||||||
|
return v - polyBlep(phase, dt);
|
||||||
|
},
|
||||||
|
ramp(phase) {
|
||||||
|
return phase;
|
||||||
|
},
|
||||||
|
saw(phase) {
|
||||||
|
return 1 - phase;
|
||||||
|
},
|
||||||
|
tri(phase, skew = 0.5) {
|
||||||
|
if (phase >= skew) {
|
||||||
|
return 1 - ((phase / (1 - skew)) % 1);
|
||||||
|
}
|
||||||
|
return (phase / skew) % 1;
|
||||||
|
},
|
||||||
|
square(phase, skew = 0.5) {
|
||||||
|
if (phase >= skew) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
class CoarseProcessor extends AudioWorkletProcessor {
|
class CoarseProcessor extends AudioWorkletProcessor {
|
||||||
|
|
@ -91,14 +127,6 @@ class CrushProcessor extends AudioWorkletProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registerProcessor('crush-processor', CrushProcessor);
|
registerProcessor('crush-processor', CrushProcessor);
|
||||||
const sine = (phase, dt) => {
|
|
||||||
return Math.sin(Math.PI * 2 * phase);
|
|
||||||
|
|
||||||
// return Math.sin(phase);
|
|
||||||
};
|
|
||||||
const getModulator = (frequency, values, ct) => {
|
|
||||||
Math.sin();
|
|
||||||
};
|
|
||||||
|
|
||||||
class GainModProcessor extends AudioWorkletProcessor {
|
class GainModProcessor extends AudioWorkletProcessor {
|
||||||
static get parameterDescriptors() {
|
static get parameterDescriptors() {
|
||||||
|
|
@ -106,13 +134,14 @@ class GainModProcessor extends AudioWorkletProcessor {
|
||||||
{ name: 'cps', defaultValue: 0.5 },
|
{ name: 'cps', defaultValue: 0.5 },
|
||||||
{ name: 'speed', defaultValue: 0.5 },
|
{ name: 'speed', defaultValue: 0.5 },
|
||||||
{ name: 'cycle', defaultValue: 0 },
|
{ name: 'cycle', defaultValue: 0 },
|
||||||
|
// { name: 'shape', defaultValue: 'tri' },
|
||||||
|
// { name: 'depth', defaultValue: 1 },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.phase;
|
this.phase;
|
||||||
this.inc = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
incrementPhase(dt) {
|
incrementPhase(dt) {
|
||||||
|
|
@ -126,30 +155,27 @@ class GainModProcessor extends AudioWorkletProcessor {
|
||||||
const speed = parameters['speed'][0];
|
const speed = parameters['speed'][0];
|
||||||
const cps = parameters['cps'][0];
|
const cps = parameters['cps'][0];
|
||||||
const cycle = parameters['cycle'][0];
|
const cycle = parameters['cycle'][0];
|
||||||
|
|
||||||
|
const blockSize = 128;
|
||||||
const frequency = speed * cps;
|
const frequency = speed * cps;
|
||||||
if (this.phase == null) {
|
if (this.phase == null) {
|
||||||
this.phase = (cycle * cps * frequency) % 1;
|
const secondsPassed = cycle / cps;
|
||||||
|
this.phase = Math.max(0, (secondsPassed * frequency) % 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const input = inputs[0];
|
const input = inputs[0];
|
||||||
const output = outputs[0];
|
const output = outputs[0];
|
||||||
const blockSize = 128;
|
|
||||||
// let crush = parameters.crush[0] ?? 8;
|
|
||||||
// crush = Math.max(1, crush);
|
|
||||||
// if (input[0] == null || output[0] == null) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
const dt = frequency / sampleRate;
|
const dt = frequency / sampleRate;
|
||||||
for (let n = 0; n < blockSize; n++) {
|
for (let n = 0; n < blockSize; n++) {
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
const modval = sine(this.phase, dt);
|
const modval = waveshapes.tri(this.phase, 0.99);
|
||||||
|
|
||||||
output[i][n] = input[i][n] * modval;
|
output[i][n] = input[i][n] * modval;
|
||||||
}
|
}
|
||||||
this.incrementPhase(dt);
|
this.incrementPhase(dt);
|
||||||
this.inc += 1;
|
|
||||||
}
|
}
|
||||||
// return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registerProcessor('gainmod-processor', GainModProcessor);
|
registerProcessor('gainmod-processor', GainModProcessor);
|
||||||
|
|
@ -222,34 +248,6 @@ class DistortProcessor extends AudioWorkletProcessor {
|
||||||
}
|
}
|
||||||
registerProcessor('distort-processor', DistortProcessor);
|
registerProcessor('distort-processor', DistortProcessor);
|
||||||
|
|
||||||
// adjust waveshape to remove frequencies above nyquist to prevent aliasing
|
|
||||||
// referenced from https://www.kvraudio.com/forum/viewtopic.php?t=375517
|
|
||||||
const polyBlep = (phase, dt) => {
|
|
||||||
// 0 <= phase < 1
|
|
||||||
if (phase < dt) {
|
|
||||||
phase /= dt;
|
|
||||||
// 2 * (phase - phase^2/2 - 0.5)
|
|
||||||
return phase + phase - phase * phase - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -1 < phase < 0
|
|
||||||
else if (phase > 1 - dt) {
|
|
||||||
phase = (phase - 1) / dt;
|
|
||||||
// 2 * (phase^2/2 + phase + 0.5)
|
|
||||||
return phase * phase + phase + phase + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0 otherwise
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const saw = (phase, dt) => {
|
|
||||||
const v = 2 * phase - 1;
|
|
||||||
return v - polyBlep(phase, dt);
|
|
||||||
};
|
|
||||||
|
|
||||||
function lerp(a, b, n) {
|
function lerp(a, b, n) {
|
||||||
return n * (b - a) + a;
|
return n * (b - a) + a;
|
||||||
}
|
}
|
||||||
|
|
@ -349,7 +347,7 @@ class SuperSawOscillatorProcessor extends AudioWorkletProcessor {
|
||||||
|
|
||||||
for (let i = 0; i < output[0].length; i++) {
|
for (let i = 0; i < output[0].length; i++) {
|
||||||
this.phase[n] = this.phase[n] ?? Math.random();
|
this.phase[n] = this.phase[n] ?? Math.random();
|
||||||
const v = saw(this.phase[n], dt);
|
const v = waveshapes.sawblep(this.phase[n], dt);
|
||||||
|
|
||||||
output[0][i] = output[0][i] + v * gainL;
|
output[0][i] = output[0][i] + v * gainL;
|
||||||
output[1][i] = output[1][i] + v * gainR;
|
output[1][i] = output[1][i] + v * gainR;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue