migrate to encapsulated out
This commit is contained in:
parent
5c99b72e2f
commit
d092068bd2
1 changed files with 197 additions and 172 deletions
|
|
@ -23,6 +23,21 @@ export const getAudioContext = () => {
|
|||
return audioContext;
|
||||
};
|
||||
|
||||
let destination;
|
||||
export const getDestination = () => {
|
||||
const ctx = getAudioContext();
|
||||
if (!destination) {
|
||||
destination = ctx.createGain();
|
||||
destination.connect(ctx.destination);
|
||||
}
|
||||
return destination;
|
||||
};
|
||||
|
||||
export const panic = () => {
|
||||
getDestination().gain.linearRampToValueAtTime(0, getAudioContext().currentTime + 0.01);
|
||||
destination = null;
|
||||
};
|
||||
|
||||
const getFilter = (type, frequency, Q) => {
|
||||
const filter = getAudioContext().createBiquadFilter();
|
||||
filter.type = type;
|
||||
|
|
@ -99,7 +114,7 @@ const getSampleBufferSource = async (s, n, note) => {
|
|||
}
|
||||
const bank = samples?.[s];
|
||||
if (!bank) {
|
||||
throw new Error('sample not found:', s, 'try one of ' + Object.keys(samples));
|
||||
throw new Error(`sample not found: "${s}", try one of ${Object.keys(samples).join(', ')}`);
|
||||
}
|
||||
if (typeof bank !== 'object') {
|
||||
throw new Error('wrong format for sample bank:', s);
|
||||
|
|
@ -172,13 +187,17 @@ function gainNode(value) {
|
|||
}
|
||||
const cutGroups = [];
|
||||
|
||||
Pattern.prototype.out = function () {
|
||||
return this.onTrigger(async (t, hap, ct, cps) => {
|
||||
const hapDuration = hap.duration / cps;
|
||||
// export const webaudioOutput = async (t, hap, ct, cps) => {
|
||||
export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
||||
try {
|
||||
const ac = getAudioContext();
|
||||
if (typeof hap.value !== 'object') {
|
||||
throw new Error(
|
||||
`hap.value ${hap.value} is not supported by webaudio output. Hint: append .note() or .s() to the end`,
|
||||
);
|
||||
}
|
||||
// calculate correct time (tone.js workaround)
|
||||
t = ac.currentTime + t - ct;
|
||||
let t = ac.currentTime + deadline;
|
||||
// destructure value
|
||||
let {
|
||||
freq,
|
||||
|
|
@ -306,8 +325,10 @@ Pattern.prototype.out = function () {
|
|||
const adsr = getADSR(attack, decay, sustain, release, 1, t, t + duration);
|
||||
chain.push(adsr);
|
||||
}
|
||||
// level down before effects
|
||||
chain.push(gainNode(gain));
|
||||
// master out
|
||||
const master = ac.createGain();
|
||||
master.gain.value = gain;
|
||||
chain.push(master);
|
||||
|
||||
// filters
|
||||
cutoff !== undefined && chain.push(getFilter('lowpass', cutoff, resonance));
|
||||
|
|
@ -324,18 +345,18 @@ Pattern.prototype.out = function () {
|
|||
panner.pan.value = 2 * pan - 1;
|
||||
chain.push(panner);
|
||||
}
|
||||
|
||||
// last gain
|
||||
const post = gainNode(1);
|
||||
chain.push(post);
|
||||
post.connect(ac.destination);
|
||||
|
||||
post.connect(getDestination());
|
||||
if (delay > 0 && delaytime > 0 && delayfeedback > 0) {
|
||||
const dly = ac.createFeedbackDelay(delay, delaytime, delayfeedback);
|
||||
dly.start(t);
|
||||
post.connect(dly);
|
||||
dly.connect(ac.destination);
|
||||
dly.connect(getDestination());
|
||||
}
|
||||
|
||||
// connect chain elements together
|
||||
chain.slice(1).reduce((last, current) => last.connect(current), chain[0]);
|
||||
// disconnect all nodes when source node has ended:
|
||||
|
|
@ -343,5 +364,9 @@ Pattern.prototype.out = function () {
|
|||
} catch (e) {
|
||||
console.warn('.out error:', e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Pattern.prototype.out = function () {
|
||||
// TODO: refactor (t, hap, ct, cps) to (hap, deadline, duration) ?
|
||||
return this.onTrigger((t, hap, ct, cps) => webaudioOutput(hap, t - ct, hap.duration / cps));
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue