wip: use sample as an impulse response for the reverb

This commit is contained in:
Vasilii Milovidov 2023-10-01 05:15:47 +04:00
parent 8a741952df
commit fd18508266
3 changed files with 1232 additions and 1192 deletions

File diff suppressed because it is too large Load diff

View file

@ -7,14 +7,22 @@ if (typeof AudioContext !== 'undefined') {
return impulse; return impulse;
}; };
AudioContext.prototype.createReverb = function (duration) { AudioContext.prototype.createReverb = function (duration, buffer) {
const convolver = this.createConvolver(); const convolver = this.createConvolver();
convolver.setDuration = (d) => { convolver.setDuration = (d, i) => {
convolver.buffer = this.impulseResponse(d); convolver.buffer = i !== undefined ? buffer : this.impulseResponse(d);
convolver.duration = duration; convolver.duration = d;
return convolver; return convolver;
}; };
convolver.setDuration(duration); convolver.setIR = (i) => {
convolver.buffer = i;
return convolver;
};
if (buffer !== undefined) {
convolver.setIR(buffer);
} else {
convolver.setDuration(duration);
}
return convolver; return convolver;
}; };
} }

View file

@ -12,14 +12,18 @@ import workletsUrl from './worklets.mjs?url';
import { createFilter, gainNode } from './helpers.mjs'; import { createFilter, gainNode } from './helpers.mjs';
import { map } from 'nanostores'; import { map } from 'nanostores';
import { logger } from './logger.mjs'; import { logger } from './logger.mjs';
import { loadBuffer } from './sampler.mjs';
export const soundMap = map(); export const soundMap = map();
export function registerSound(key, onTrigger, data = {}) { export function registerSound(key, onTrigger, data = {}) {
soundMap.setKey(key, { onTrigger, data }); soundMap.setKey(key, { onTrigger, data });
} }
export function getSound(s) { export function getSound(s) {
return soundMap.get()[s]; return soundMap.get()[s];
} }
export const resetLoadedSounds = () => soundMap.set({}); export const resetLoadedSounds = () => soundMap.set({});
let audioContext; let audioContext;
@ -46,6 +50,7 @@ export const panic = () => {
}; };
let workletsLoading; let workletsLoading;
function loadWorklets() { function loadWorklets() {
if (workletsLoading) { if (workletsLoading) {
return workletsLoading; return workletsLoading;
@ -89,6 +94,7 @@ export async function initAudioOnFirstClick(options) {
let delays = {}; let delays = {};
const maxfeedback = 0.98; const maxfeedback = 0.98;
function getDelay(orbit, delaytime, delayfeedback, t) { function getDelay(orbit, delaytime, delayfeedback, t) {
if (delayfeedback > maxfeedback) { if (delayfeedback > maxfeedback) {
//logger(`delayfeedback was clamped to ${maxfeedback} to save your ears`); //logger(`delayfeedback was clamped to ${maxfeedback} to save your ears`);
@ -107,10 +113,11 @@ function getDelay(orbit, delaytime, delayfeedback, t) {
} }
let reverbs = {}; let reverbs = {};
function getReverb(orbit, duration = 2) {
function getReverb(orbit, duration = 2, ir) {
if (!reverbs[orbit]) { if (!reverbs[orbit]) {
const ac = getAudioContext(); const ac = getAudioContext();
const reverb = ac.createReverb(duration); const reverb = ac.createReverb(duration, ir);
reverb.connect(getDestination()); reverb.connect(getDestination());
reverbs[orbit] = reverb; reverbs[orbit] = reverb;
} }
@ -118,10 +125,15 @@ function getReverb(orbit, duration = 2) {
reverbs[orbit] = reverbs[orbit].setDuration(duration); reverbs[orbit] = reverbs[orbit].setDuration(duration);
reverbs[orbit].duration = duration; reverbs[orbit].duration = duration;
} }
if (reverbs[orbit].ir !== ir) {
reverbs[orbit] = reverbs[orbit].setIR(ir);
reverbs[orbit].ir = ir;
}
return reverbs[orbit]; return reverbs[orbit];
} }
export let analyser, analyserData /* s = {} */; export let analyser, analyserData /* s = {} */;
export function getAnalyser(/* orbit, */ fftSize = 2048) { export function getAnalyser(/* orbit, */ fftSize = 2048) {
if (!analyser /*s [orbit] */) { if (!analyser /*s [orbit] */) {
const analyserNode = getAudioContext().createAnalyser(); const analyserNode = getAudioContext().createAnalyser();
@ -151,7 +163,7 @@ export function getAnalyzerData(type = 'time') {
return analyserData; return analyserData;
} }
function effectSend(input, effect, wet) { function effectSend(input, effect, wet, size) {
const send = gainNode(wet); const send = gainNode(wet);
input.connect(send); input.connect(send);
send.connect(effect); send.connect(effect);
@ -219,6 +231,8 @@ export const superdough = async (value, deadline, hapDuration) => {
velocity = 1, velocity = 1,
analyze, // analyser wet analyze, // analyser wet
fft = 8, // fftSize 0 - 10 fft = 8, // fftSize 0 - 10
ir,
i = 0,
} = value; } = value;
gain *= velocity; // legacy fix for velocity gain *= velocity; // legacy fix for velocity
let toDisconnect = []; // audio nodes that will be disconnected when the source has ended let toDisconnect = []; // audio nodes that will be disconnected when the source has ended
@ -247,6 +261,7 @@ export const superdough = async (value, deadline, hapDuration) => {
// this can be used for things like speed(0) in the sampler // this can be used for things like speed(0) in the sampler
return; return;
} }
if (ac.currentTime > t) { if (ac.currentTime > t) {
logger('[webaudio] skip hap: still loading', ac.currentTime - t); logger('[webaudio] skip hap: still loading', ac.currentTime - t);
return; return;
@ -352,10 +367,16 @@ export const superdough = async (value, deadline, hapDuration) => {
delaySend = effectSend(post, delyNode, delay); delaySend = effectSend(post, delyNode, delay);
} }
// reverb // reverb
let buffer;
if (ir !== undefined) {
let sample = getSound(ir);
let url = sample.data.samples[i % sample.data.samples.length];
buffer = await loadBuffer(url, ac, ir, 0);
}
let reverbSend; let reverbSend;
if (room > 0 && size > 0) { if (room > 0 && size > 0) {
const reverbNode = getReverb(orbit, size); const reverbNode = getReverb(orbit, size, buffer);
reverbSend = effectSend(post, reverbNode, room); reverbSend = effectSend(post, reverbNode, room, size);
} }
// analyser // analyser