Merge pull request #224 from tidalcycles/reverb

Reverb
This commit is contained in:
Felix Roos 2022-09-25 21:15:36 +02:00 committed by GitHub
commit b7b576e38b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 1 deletions

View File

@ -581,6 +581,11 @@ const generic_params = [
'size',
'a pattern of numbers from 0 to 1. Sets the perceptual size (reverb time) of the `room` to be used in reverb.',
],
[
'f',
'roomsize',
'a pattern of numbers from 0 to 1. Sets the perceptual size (reverb time) of the `room` to be used in reverb.',
],
// ['f', 'sagogo', ''],
// ['f', 'sclap', ''],
// ['f', 'sclaves', ''],

View File

@ -0,0 +1,20 @@
if (typeof AudioContext !== 'undefined') {
AudioContext.prototype.impulseResponse = function (duration) {
const length = this.sampleRate * duration;
const impulse = this.createBuffer(2, length, this.sampleRate);
const IR = impulse.getChannelData(0);
for (let i = 0; i < length; i++) IR[i] = (2 * Math.random() - 1) * Math.pow(1 - i / length, duration);
return impulse;
};
AudioContext.prototype.createReverb = function (duration) {
const convolver = this.createConvolver();
convolver.setDuration = (d) => {
convolver.buffer = this.impulseResponse(d);
convolver.duration = duration;
return convolver;
};
convolver.setDuration(duration);
return convolver;
};
}

View File

@ -8,6 +8,7 @@ This program is free software: you can redistribute it and/or modify it under th
import * as strudel from '@strudel.cycles/core';
import { fromMidi, toMidi } from '@strudel.cycles/core';
import './feedbackdelay.mjs';
import './reverb.mjs';
import { loadBuffer, reverseBuffer } from './sampler.mjs';
const { Pattern } = strudel;
import './vowel.mjs';
@ -207,6 +208,21 @@ function getDelay(orbit, delaytime, delayfeedback, t) {
return delays[orbit];
}
let reverbs = {};
function getReverb(orbit, duration = 2) {
if (!reverbs[orbit]) {
const ac = getAudioContext();
const reverb = ac.createReverb(duration);
reverb.connect(getDestination());
reverbs[orbit] = reverb;
}
if (reverbs[orbit].duration !== duration) {
reverbs[orbit] = reverbs[orbit].setDuration(duration);
reverbs[orbit].duration = duration;
}
return reverbs[orbit];
}
function effectSend(input, effect, wet) {
const send = gainNode(wet);
input.connect(send);
@ -260,6 +276,9 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
cut,
loop,
orbit = 1,
room,
size = 2,
roomsize = size,
} = hap.value;
const { velocity = 1 } = hap.context;
gain *= velocity; // legacy fix for velocity
@ -386,12 +405,18 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => {
const delyNode = getDelay(orbit, delaytime, delayfeedback, t);
delaySend = effectSend(post, delyNode, delay);
}
// reverb
let reverbSend;
if (room > 0 && roomsize > 0) {
const reverbNode = getReverb(orbit, roomsize);
reverbSend = effectSend(post, reverbNode, room);
}
// connect chain elements together
chain.slice(1).reduce((last, current) => last.connect(current), chain[0]);
// disconnect all nodes when source node has ended:
chain[0].onended = () => chain.concat([delaySend]).forEach((n) => n?.disconnect());
chain[0].onended = () => chain.concat([delaySend, reverbSend]).forEach((n) => n?.disconnect());
} catch (e) {
console.warn('.out error:', e);
}

View File

@ -1743,6 +1743,19 @@ exports[`renders tunes > tune: caverave 1`] = `
]
`;
exports[`renders tunes > tune: chop 1`] = `
[
"0/1 -> 1/4: {\\"s\\":\\"p\\",\\"speed\\":0.03125,\\"unit\\":\\"c\\",\\"begin\\":0,\\"end\\":0.0078125,\\"pan\\":0,\\"shape\\":0.4,\\"decay\\":0.1,\\"sustain\\":0.6}",
"1/4 -> 1/2: {\\"s\\":\\"p\\",\\"speed\\":0.03125,\\"unit\\":\\"c\\",\\"begin\\":0.0078125,\\"end\\":0.015625,\\"pan\\":0,\\"shape\\":0.4,\\"decay\\":0.1,\\"sustain\\":0.6}",
"1/2 -> 3/4: {\\"s\\":\\"p\\",\\"speed\\":0.03125,\\"unit\\":\\"c\\",\\"begin\\":0.015625,\\"end\\":0.0234375,\\"pan\\":0,\\"shape\\":0.4,\\"decay\\":0.1,\\"sustain\\":0.6}",
"3/4 -> 1/1: {\\"s\\":\\"p\\",\\"speed\\":0.03125,\\"unit\\":\\"c\\",\\"begin\\":0.0234375,\\"end\\":0.03125,\\"pan\\":0,\\"shape\\":0.4,\\"decay\\":0.1,\\"sustain\\":0.6}",
"3/4 -> 1/1: {\\"s\\":\\"p\\",\\"speed\\":0.03125,\\"unit\\":\\"c\\",\\"begin\\":0,\\"end\\":0.0078125,\\"pan\\":1,\\"shape\\":0.4,\\"decay\\":0.1,\\"sustain\\":0.6}",
"1/2 -> 3/4: {\\"s\\":\\"p\\",\\"speed\\":0.03125,\\"unit\\":\\"c\\",\\"begin\\":0.0078125,\\"end\\":0.015625,\\"pan\\":1,\\"shape\\":0.4,\\"decay\\":0.1,\\"sustain\\":0.6}",
"1/4 -> 1/2: {\\"s\\":\\"p\\",\\"speed\\":0.03125,\\"unit\\":\\"c\\",\\"begin\\":0.015625,\\"end\\":0.0234375,\\"pan\\":1,\\"shape\\":0.4,\\"decay\\":0.1,\\"sustain\\":0.6}",
"0/1 -> 1/4: {\\"s\\":\\"p\\",\\"speed\\":0.03125,\\"unit\\":\\"c\\",\\"begin\\":0.0234375,\\"end\\":0.03125,\\"pan\\":1,\\"shape\\":0.4,\\"decay\\":0.1,\\"sustain\\":0.6}",
]
`;
exports[`renders tunes > tune: customTrigger 1`] = `
[
"0/1 -> 1/8: {\\"freq\\":55.33,\\"s\\":\\"sawtooth\\"}",
@ -1771,6 +1784,13 @@ exports[`renders tunes > tune: customTrigger 1`] = `
]
`;
exports[`renders tunes > tune: delay 1`] = `
[
"0/1 -> 1/2: {\\"s\\":\\"bd\\",\\"delay\\":0,\\"delaytime\\":0.16,\\"delayfeedback\\":0.8,\\"speed\\":-1}",
"1/2 -> 1/1: {\\"s\\":\\"sd\\",\\"delay\\":0,\\"delaytime\\":0.16,\\"delayfeedback\\":0.8,\\"speed\\":-1}",
]
`;
exports[`renders tunes > tune: echoPiano 1`] = `
[
"0/1 -> 1/2: {\\"note\\":\\"D3\\",\\"clip\\":1,\\"s\\":\\"piano\\",\\"release\\":0.1,\\"pan\\":0.4814814814814815}",
@ -13380,6 +13400,15 @@ exports[`renders tunes > tune: meltingsubmarine 1`] = `
]
`;
exports[`renders tunes > tune: orbit 1`] = `
[
"0/1 -> 1/2: {\\"s\\":\\"bd\\",\\"delay\\":0.5,\\"delaytime\\":0.33,\\"delayfeedback\\":0.6,\\"speed\\":-1}",
"1/2 -> 1/1: {\\"s\\":\\"sd\\",\\"delay\\":0.5,\\"delaytime\\":0.33,\\"delayfeedback\\":0.6,\\"speed\\":-1}",
"0/1 -> 1/2: {\\"s\\":\\"hh\\",\\"delay\\":0.8,\\"delaytime\\":0.08,\\"delayfeedback\\":0.7,\\"orbit\\":2,\\"speed\\":-1}",
"1/2 -> 1/1: {\\"s\\":\\"hh\\",\\"delay\\":0.8,\\"delaytime\\":0.08,\\"delayfeedback\\":0.7,\\"orbit\\":2,\\"speed\\":-1}",
]
`;
exports[`renders tunes > tune: outroMusic 1`] = `
[
"0/1 -> 3/1: {\\"n\\":\\"B3\\",\\"s\\":\\"0040_FluidR3_GM_sf2_file\\",\\"attack\\":0.05,\\"decay\\":0.1,\\"sustain\\":0.7,\\"cutoff\\":1111.7252990603447,\\"gain\\":0.3}",

View File

@ -897,3 +897,33 @@ stack(
x? ~ ~ x ~ x@3\`),
roots.struct("x [~ x?0.2] x [~ x?] | x!4 | x@2 ~ ~ ~ x x x").transpose("0 7")
).slow(2).pianoroll().note().piano().out();`;
export const chop = `samples({ p: 'https://cdn.freesound.org/previews/648/648433_11943129-lq.mp3' })
s("p")
.loopAt(32,1)
.chop(128)
.jux(rev)
.shape(.4)
.decay(.1)
.sustain(.6)
.out()`;
export const delay = `stack(
s("bd <sd cp>")
.delay("<0 .5>")
.delaytime(".16 | .33")
.delayfeedback(".6 | .8")
).sometimes(x=>x.speed("-1")).out()`;
export const orbit = `stack(
s("bd <sd cp>")
.delay(.5)
.delaytime(.33)
.delayfeedback(.6),
s("hh*2")
.delay(.8)
.delaytime(.08)
.delayfeedback(.7)
.orbit(2)
).sometimes(x=>x.speed("-1")).out()`;