mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-26 04:58:27 +00:00
initial commit
This commit is contained in:
parent
fd6c713119
commit
b3f8df1783
@ -380,6 +380,17 @@ const generic_params = [
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
['coarse'],
|
['coarse'],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fake-resampling for lowering the sample rate. Caution: This effect seems to only work in chromium based browsers
|
||||||
|
*
|
||||||
|
* @name phaser
|
||||||
|
* @param {number | Pattern} factor 1 for original 2 for half, 3 for a third and so on.
|
||||||
|
* @example
|
||||||
|
* s("bd sd,hh*4").coarse("<1 4 8 16 32>")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
['phaser'],
|
||||||
/**
|
/**
|
||||||
* choose the channel the pattern is sent to in superdirt
|
* choose the channel the pattern is sent to in superdirt
|
||||||
*
|
*
|
||||||
|
|||||||
88
packages/superdough/phaser.mjs
Normal file
88
packages/superdough/phaser.mjs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// credits to webdirt: https://github.com/dktr0/WebDirt/blob/41342e81d6ad694a2310d491fef7b7e8b0929efe/js-src/Graph.js#L597
|
||||||
|
export var vowelFormant = {
|
||||||
|
0: { freqs: [660, 1120, 2750, 3000, 3350], gains: [1, 0.5012, 0.0708, 0.0631, 0.0126], qs: [80, 90, 120, 130, 140] },
|
||||||
|
1: { freqs: [440, 1800, 2700, 3000, 3300], gains: [1, 0.1995, 0.1259, 0.1, 0.1], qs: [70, 80, 100, 120, 120] },
|
||||||
|
2: { freqs: [270, 1850, 2900, 3350, 3590], gains: [1, 0.0631, 0.0631, 0.0158, 0.0158], qs: [40, 90, 100, 120, 120] },
|
||||||
|
3: { freqs: [430, 820, 2700, 3000, 3300], gains: [1, 0.3162, 0.0501, 0.0794, 0.01995], qs: [40, 80, 100, 120, 120] },
|
||||||
|
4: { freqs: [370, 630, 2750, 3000, 3400], gains: [1, 0.1, 0.0708, 0.0316, 0.01995], qs: [40, 60, 100, 120, 120] },
|
||||||
|
};
|
||||||
|
|
||||||
|
var createFilter = function (ctx, cutoff, Q) {
|
||||||
|
var lowpassFilter = ctx.createBiquadFilter();
|
||||||
|
lowpassFilter.type = 'notch';
|
||||||
|
lowpassFilter.gain.value = 1;
|
||||||
|
lowpassFilter.frequency.value = cutoff;
|
||||||
|
lowpassFilter.Q.value = Q;
|
||||||
|
return lowpassFilter;
|
||||||
|
};
|
||||||
|
|
||||||
|
// var createTriOscillator = function (freq) {
|
||||||
|
// var osc = ctx.createOscillator();
|
||||||
|
// osc.type = 'triangle';
|
||||||
|
// osc.frequency.value = freq * 1.0;
|
||||||
|
// osc.detune.value = 0;
|
||||||
|
// return osc;
|
||||||
|
// };
|
||||||
|
|
||||||
|
var createLFO = function (ctx, freq) {
|
||||||
|
var osc = ctx.createOscillator();
|
||||||
|
osc.frequency.value = freq;
|
||||||
|
osc.type = 'sine';
|
||||||
|
osc.start();
|
||||||
|
return osc;
|
||||||
|
};
|
||||||
|
var createLFOGain = function (ctx, gain) {
|
||||||
|
var gainNode = ctx.createGain();
|
||||||
|
gainNode.gain.value = gain;
|
||||||
|
return gainNode;
|
||||||
|
};
|
||||||
|
let lfo, lfoGain;
|
||||||
|
if (typeof GainNode !== 'undefined') {
|
||||||
|
class PhaserNode extends GainNode {
|
||||||
|
constructor(ac, speed) {
|
||||||
|
super(ac);
|
||||||
|
console.log('speed', speed);
|
||||||
|
|
||||||
|
if (!vowelFormant[speed]) {
|
||||||
|
throw new Error('phaser: unknown phaser ' + speed);
|
||||||
|
}
|
||||||
|
const { gains, qs, freqs } = vowelFormant[speed];
|
||||||
|
const makeupGain = ac.createGain();
|
||||||
|
|
||||||
|
// var sine = ac.createOscillator(),
|
||||||
|
// sineGain = ac.createGain();
|
||||||
|
|
||||||
|
// //set up our oscillator types
|
||||||
|
// sine.type = sine.SINE;
|
||||||
|
|
||||||
|
// //set the amplitude of the modulation
|
||||||
|
// sineGain.gain.value = 100;
|
||||||
|
|
||||||
|
// //connect the dots
|
||||||
|
// sine.connect(sineGain);
|
||||||
|
if (lfo == null) {
|
||||||
|
lfo = createLFO(ac, 0.25);
|
||||||
|
lfoGain = createLFOGain(ac, 4000);
|
||||||
|
|
||||||
|
lfo.connect(lfoGain);
|
||||||
|
}
|
||||||
|
// sineGain.connect(saw.frequency);
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
const gain = ac.createGain();
|
||||||
|
gain.gain.value = 0.5;
|
||||||
|
const filter = createFilter(ac, 1000 + i * 20, 1);
|
||||||
|
this.connect(filter);
|
||||||
|
lfoGain.connect(filter.detune);
|
||||||
|
filter.connect(gain);
|
||||||
|
gain.connect(makeupGain);
|
||||||
|
}
|
||||||
|
makeupGain.gain.value = 1; // how much makeup gain to add?
|
||||||
|
this.connect = (target) => makeupGain.connect(target);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioContext.prototype.createPhaser = function (speed) {
|
||||||
|
return new PhaserNode(this, speed);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
import './feedbackdelay.mjs';
|
import './feedbackdelay.mjs';
|
||||||
import './reverb.mjs';
|
import './reverb.mjs';
|
||||||
import './vowel.mjs';
|
import './vowel.mjs';
|
||||||
|
import './phaser.mjs';
|
||||||
import { clamp } from './util.mjs';
|
import { clamp } from './util.mjs';
|
||||||
import workletsUrl from './worklets.mjs?url';
|
import workletsUrl from './worklets.mjs?url';
|
||||||
import { createFilter, gainNode, getCompressor } from './helpers.mjs';
|
import { createFilter, gainNode, getCompressor } from './helpers.mjs';
|
||||||
@ -226,6 +227,9 @@ export const superdough = async (value, deadline, hapDuration) => {
|
|||||||
bpsustain = 1,
|
bpsustain = 1,
|
||||||
bprelease = 0.01,
|
bprelease = 0.01,
|
||||||
bandq = 1,
|
bandq = 1,
|
||||||
|
|
||||||
|
//phaser
|
||||||
|
phaser,
|
||||||
//
|
//
|
||||||
coarse,
|
coarse,
|
||||||
crush,
|
crush,
|
||||||
@ -361,10 +365,16 @@ export const superdough = async (value, deadline, hapDuration) => {
|
|||||||
chain.push(vowelFilter);
|
chain.push(vowelFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (phaser !== undefined) {
|
||||||
|
const phaserFX = ac.createPhaser(phaser);
|
||||||
|
chain.push(phaserFX);
|
||||||
|
}
|
||||||
|
|
||||||
// effects
|
// effects
|
||||||
coarse !== undefined && chain.push(getWorklet(ac, 'coarse-processor', { coarse }));
|
coarse !== undefined && chain.push(getWorklet(ac, 'coarse-processor', { coarse }));
|
||||||
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 }));
|
shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape }));
|
||||||
|
// phaser !== undefined && chain.push(getWorklet(ac, 'phaser-processor', { phaser }));
|
||||||
|
|
||||||
compressorThreshold !== undefined &&
|
compressorThreshold !== undefined &&
|
||||||
chain.push(
|
chain.push(
|
||||||
|
|||||||
@ -106,3 +106,36 @@ class ShapeProcessor extends AudioWorkletProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerProcessor('shape-processor', ShapeProcessor);
|
registerProcessor('shape-processor', ShapeProcessor);
|
||||||
|
|
||||||
|
// class PhaseProcessor extends AudioWorkletProcessor {
|
||||||
|
// static get parameterDescriptors() {
|
||||||
|
// return [{ name: 'phaser', defaultValue: 0 }];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// constructor() {
|
||||||
|
// super();
|
||||||
|
// this.notStarted = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// process(inputs, outputs, parameters) {
|
||||||
|
// const input = inputs[0];
|
||||||
|
// const output = outputs[0];
|
||||||
|
// const phaser0 = parameters.phaser[0];
|
||||||
|
// const phaser1 = phaser0 < 1 ? phaser0 : 1.0 - 4e-10;
|
||||||
|
// const phaser = (2.0 * phaser1) / (1.0 - phaser1);
|
||||||
|
// const blockSize = 128;
|
||||||
|
// const hasInput = !(input[0] === undefined);
|
||||||
|
// if (hasInput) {
|
||||||
|
// this.notStarted = false;
|
||||||
|
// for (let n = 0; n < blockSize; n++) {
|
||||||
|
// const value = ((1 + phaser) * input[0][n]) / (1 + phaser * Math.abs(input[0][n]));
|
||||||
|
// for (let o = 0; o < output.length; o++) {
|
||||||
|
// output[o][n] = value;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return this.notStarted || hasInput;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// registerProcessor('phaser-processor', PhaseProcessor);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user