Merge branch 'main' into patterns-tab
This commit is contained in:
commit
80601451b6
51 changed files with 2824 additions and 1253 deletions
|
|
@ -67,6 +67,10 @@ superdough({ s: 'bd', delay: 0.5 }, 0, 1);
|
|||
- `crush`: amplitude bit crusher using given number of bits
|
||||
- `shape`: distortion effect from 0 (none) to 1 (full). might get loud!
|
||||
- `pan`: stereo panning from 0 (left) to 1 (right)
|
||||
- `phaser`: sets the speed of the modulation
|
||||
- `phaserdepth`: the amount the signal is affected by the phaser effect.
|
||||
- `phasersweep`: the frequency sweep range of the lfo for the phaser effect.
|
||||
- `phasercenter`: the amount the signal is affected by the phaser effect.
|
||||
- `vowel`: vowel filter. possible values: "a", "e", "i", "o", "u"
|
||||
- `delay`: delay mix
|
||||
- `delayfeedback`: delay feedback
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "superdough",
|
||||
"version": "0.9.10",
|
||||
"version": "0.9.11",
|
||||
"description": "simple web audio synth and sampler intended for live coding. inspired by superdirt and webdirt.",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resol
|
|||
const bufferSource = ac.createBufferSource();
|
||||
bufferSource.buffer = buffer;
|
||||
const playbackRate = 1.0 * Math.pow(2, transpose / 12);
|
||||
// bufferSource.playbackRate.value = Math.pow(2, transpose / 12);
|
||||
bufferSource.playbackRate.value = playbackRate;
|
||||
return bufferSource;
|
||||
};
|
||||
|
|
@ -163,9 +162,17 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '', option
|
|||
if (handler) {
|
||||
return handler(sampleMap);
|
||||
}
|
||||
if (sampleMap.startsWith('bubo:')) {
|
||||
const [_, repo] = sampleMap.split(':');
|
||||
sampleMap = `github:Bubobubobubobubo/dough-${repo}`;
|
||||
}
|
||||
if (sampleMap.startsWith('github:')) {
|
||||
let [_, path] = sampleMap.split('github:');
|
||||
path = path.endsWith('/') ? path.slice(0, -1) : path;
|
||||
if (path.split('/').length === 2) {
|
||||
// assume main as default branch if none set
|
||||
path += '/main';
|
||||
}
|
||||
sampleMap = `https://raw.githubusercontent.com/${path}/strudel.json`;
|
||||
}
|
||||
if (sampleMap.startsWith('shabda:')) {
|
||||
|
|
@ -233,6 +240,8 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
|||
begin = 0,
|
||||
loopEnd = 1,
|
||||
end = 1,
|
||||
vib,
|
||||
vibmod = 0.5,
|
||||
} = value;
|
||||
// load sample
|
||||
if (speed === 0) {
|
||||
|
|
@ -248,6 +257,19 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
|||
|
||||
const bufferSource = await getSampleBufferSource(s, n, note, speed, freq, bank, resolveUrl);
|
||||
|
||||
// vibrato
|
||||
let vibratoOscillator;
|
||||
if (vib > 0) {
|
||||
vibratoOscillator = getAudioContext().createOscillator();
|
||||
vibratoOscillator.frequency.value = vib;
|
||||
const gain = getAudioContext().createGain();
|
||||
// Vibmod is the amount of vibrato, in semitones
|
||||
gain.gain.value = vibmod * 100;
|
||||
vibratoOscillator.connect(gain);
|
||||
gain.connect(bufferSource.detune);
|
||||
vibratoOscillator.start(0);
|
||||
}
|
||||
|
||||
// asny stuff above took too long?
|
||||
if (ac.currentTime > t) {
|
||||
logger(`[sampler] still loading sound "${s}:${n}"`, 'highlight');
|
||||
|
|
@ -279,6 +301,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
|||
envelope.connect(out);
|
||||
bufferSource.onended = function () {
|
||||
bufferSource.disconnect();
|
||||
vibratoOscillator?.stop();
|
||||
envelope.disconnect();
|
||||
out.disconnect();
|
||||
onended();
|
||||
|
|
|
|||
|
|
@ -112,6 +112,48 @@ function getDelay(orbit, delaytime, delayfeedback, t) {
|
|||
return delays[orbit];
|
||||
}
|
||||
|
||||
// each orbit will have its own lfo
|
||||
const phaserLFOs = {};
|
||||
function getPhaser(orbit, t, speed = 1, depth = 0.5, centerFrequency = 1000, sweep = 2000) {
|
||||
//gain
|
||||
const ac = getAudioContext();
|
||||
const lfoGain = ac.createGain();
|
||||
lfoGain.gain.value = sweep;
|
||||
|
||||
//LFO
|
||||
if (phaserLFOs[orbit] == null) {
|
||||
phaserLFOs[orbit] = ac.createOscillator();
|
||||
phaserLFOs[orbit].frequency.value = speed;
|
||||
phaserLFOs[orbit].type = 'sine';
|
||||
phaserLFOs[orbit].start();
|
||||
}
|
||||
|
||||
phaserLFOs[orbit].connect(lfoGain);
|
||||
if (phaserLFOs[orbit].frequency.value != speed) {
|
||||
phaserLFOs[orbit].frequency.setValueAtTime(speed, t);
|
||||
}
|
||||
|
||||
//filters
|
||||
const numStages = 2; //num of filters in series
|
||||
let fOffset = 0;
|
||||
const filterChain = [];
|
||||
for (let i = 0; i < numStages; i++) {
|
||||
const filter = ac.createBiquadFilter();
|
||||
filter.type = 'notch';
|
||||
filter.gain.value = 1;
|
||||
filter.frequency.value = centerFrequency + fOffset;
|
||||
filter.Q.value = 2 - Math.min(Math.max(depth * 2, 0), 1.9);
|
||||
|
||||
lfoGain.connect(filter.detune);
|
||||
fOffset += 282;
|
||||
if (i > 0) {
|
||||
filterChain[i - 1].connect(filter);
|
||||
}
|
||||
filterChain.push(filter);
|
||||
}
|
||||
return filterChain[filterChain.length - 1];
|
||||
}
|
||||
|
||||
let reverbs = {};
|
||||
|
||||
let hasChanged = (now, before) => now !== undefined && now !== before;
|
||||
|
|
@ -226,6 +268,12 @@ export const superdough = async (value, deadline, hapDuration) => {
|
|||
bpsustain = 1,
|
||||
bprelease = 0.01,
|
||||
bandq = 1,
|
||||
|
||||
//phaser
|
||||
phaser,
|
||||
phaserdepth = 0.75,
|
||||
phasersweep,
|
||||
phasercenter,
|
||||
//
|
||||
coarse,
|
||||
crush,
|
||||
|
|
@ -261,6 +309,7 @@ export const superdough = async (value, deadline, hapDuration) => {
|
|||
if (bank && s) {
|
||||
s = `${bank}_${s}`;
|
||||
}
|
||||
|
||||
// get source AudioNode
|
||||
let sourceNode;
|
||||
if (source) {
|
||||
|
|
@ -378,6 +427,11 @@ export const superdough = async (value, deadline, hapDuration) => {
|
|||
panner.pan.value = 2 * pan - 1;
|
||||
chain.push(panner);
|
||||
}
|
||||
// phaser
|
||||
if (phaser !== undefined && phaserdepth > 0) {
|
||||
const phaserFX = getPhaser(orbit, t, phaser, phaserdepth, phasercenter, phasersweep);
|
||||
chain.push(phaserFX);
|
||||
}
|
||||
|
||||
// last gain
|
||||
const post = gainNode(postgain);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue