Merge pull request #219 from tidalcycles/webaudio-output
encapsulate webaudio output
This commit is contained in:
commit
cc54da5980
1 changed files with 191 additions and 170 deletions
|
|
@ -22,6 +22,21 @@ export const getAudioContext = () => {
|
||||||
return audioContext;
|
return audioContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let destination;
|
||||||
|
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 getFilter = (type, frequency, Q) => {
|
||||||
const filter = getAudioContext().createBiquadFilter();
|
const filter = getAudioContext().createBiquadFilter();
|
||||||
filter.type = type;
|
filter.type = type;
|
||||||
|
|
@ -87,7 +102,7 @@ const getSampleBufferSource = async (s, n, note) => {
|
||||||
}
|
}
|
||||||
const bank = samples?.[s];
|
const bank = samples?.[s];
|
||||||
if (!bank) {
|
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') {
|
if (typeof bank !== 'object') {
|
||||||
throw new Error('wrong format for sample bank:', s);
|
throw new Error('wrong format for sample bank:', s);
|
||||||
|
|
@ -147,21 +162,27 @@ function getWorklet(ac, processor, params) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
try {
|
try {
|
||||||
loadWorklets();
|
loadWorklets();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('could not load AudioWorklet effects coarse, crush and shape', err);
|
console.warn('could not load AudioWorklet effects coarse, crush and shape', err);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const cutGroups = [];
|
const cutGroups = [];
|
||||||
|
|
||||||
Pattern.prototype.out = function () {
|
// export const webaudioOutput = async (t, hap, ct, cps) => {
|
||||||
return this.onTrigger(async (t, hap, ct, cps) => {
|
export const webaudioOutput = async (hap, deadline, hapDuration) => {
|
||||||
const hapDuration = hap.duration / cps;
|
|
||||||
try {
|
try {
|
||||||
const ac = getAudioContext();
|
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)
|
// calculate correct time (tone.js workaround)
|
||||||
t = ac.currentTime + t - ct;
|
let t = ac.currentTime + deadline;
|
||||||
// destructure value
|
// destructure value
|
||||||
let {
|
let {
|
||||||
freq,
|
freq,
|
||||||
|
|
@ -308,17 +329,17 @@ Pattern.prototype.out = function () {
|
||||||
panner.pan.value = 2 * pan - 1;
|
panner.pan.value = 2 * pan - 1;
|
||||||
chain.push(panner);
|
chain.push(panner);
|
||||||
}
|
}
|
||||||
// master out
|
|
||||||
/* const master = ac.createGain();
|
|
||||||
master.gain.value = 0.8 * gain;
|
|
||||||
chain.push(master); */
|
|
||||||
chain.push(ac.destination);
|
|
||||||
// connect chain elements together
|
// connect chain elements together
|
||||||
chain.slice(1).reduce((last, current) => last.connect(current), chain[0]);
|
chain.slice(1).reduce((last, current) => last.connect(current), chain[0]);
|
||||||
|
chain[chain.length - 1].connect(getDestination());
|
||||||
// disconnect all nodes when source node has ended:
|
// disconnect all nodes when source node has ended:
|
||||||
chain[0].onended = () => chain.forEach((n) => n.disconnect());
|
chain[0].onended = () => chain.forEach((n) => n.disconnect());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('.out error:', 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