use context for tone

This commit is contained in:
Felix Roos 2022-02-25 20:43:38 +01:00
parent a3971f793c
commit 08ab06c9cc
2 changed files with 25 additions and 28 deletions

View File

@ -26,18 +26,17 @@ const Pattern = _Pattern as any;
// with this function, you can play the pattern with any tone synth // with this function, you can play the pattern with any tone synth
Pattern.prototype.tone = function (instrument) { Pattern.prototype.tone = function (instrument) {
// instrument.toDestination(); // instrument.toDestination();
return this.fmap((value: any) => { return this._withEvent((event) => {
value = typeof value !== 'object' && !Array.isArray(value) ? { value } : value;
const onTrigger = (time, event) => { const onTrigger = (time, event) => {
if (instrument.constructor.name === 'PluckSynth') { if (instrument.constructor.name === 'PluckSynth') {
instrument.triggerAttack(value.value, time); instrument.triggerAttack(event.value, time);
} else if (instrument.constructor.name === 'NoiseSynth') { } else if (instrument.constructor.name === 'NoiseSynth') {
instrument.triggerAttackRelease(event.duration, time); // noise has no value instrument.triggerAttackRelease(event.duration, time); // noise has no value
} else { } else {
instrument.triggerAttackRelease(value.value, event.duration, time); instrument.triggerAttackRelease(event.value, event.duration, time);
} }
}; };
return { ...value, instrument, onTrigger }; return event.setContext({ ...event.context, instrument, onTrigger });
}); });
}; };
@ -105,13 +104,12 @@ Pattern.prototype._poly = function (type: any = 'triangle') {
// this.instrument = new PolySynth(Synth, instrumentConfig).toDestination(); // this.instrument = new PolySynth(Synth, instrumentConfig).toDestination();
this.instrument = poly(type); this.instrument = poly(type);
} }
return this.fmap((value: any) => { return this._withEvent((event: any) => {
value = typeof value !== 'object' && !Array.isArray(value) ? { value } : value;
const onTrigger = (time, event) => { const onTrigger = (time, event) => {
this.instrument.set(instrumentConfig); this.instrument.set(instrumentConfig);
this.instrument.triggerAttackRelease(value.value, event.duration, time); this.instrument.triggerAttackRelease(event.value, event.duration, time);
}; };
return { ...value, instrumentConfig, onTrigger }; return event.setContext({ ...event.context, instrumentConfig, onTrigger });
}); });
}; };
@ -138,8 +136,7 @@ const getTrigger = (getChain: any, value: any) => (time: number, event: any) =>
}; };
Pattern.prototype._synth = function (type: any = 'triangle') { Pattern.prototype._synth = function (type: any = 'triangle') {
return this.fmap((value: any) => { return this._withEvent((event: any) => {
value = typeof value !== 'object' && !Array.isArray(value) ? { value } : value;
const instrumentConfig: any = { const instrumentConfig: any = {
oscillator: { type }, oscillator: { type },
envelope: { attack: 0.01, decay: 0.01, sustain: 0.6, release: 0.01 }, envelope: { attack: 0.01, decay: 0.01, sustain: 0.6, release: 0.01 },
@ -149,39 +146,39 @@ Pattern.prototype._synth = function (type: any = 'triangle') {
instrument.set(instrumentConfig); instrument.set(instrumentConfig);
return instrument; return instrument;
}; };
const onTrigger = getTrigger(() => getInstrument().toDestination(), value.value); const onTrigger = getTrigger(() => getInstrument().toDestination(), event.value);
return { ...value, getInstrument, instrumentConfig, onTrigger }; return event.setContext({ ...event.context, getInstrument, instrumentConfig, onTrigger });
}); });
}; };
Pattern.prototype.adsr = function (attack = 0.01, decay = 0.01, sustain = 0.6, release = 0.01) { Pattern.prototype.adsr = function (attack = 0.01, decay = 0.01, sustain = 0.6, release = 0.01) {
return this.fmap((value: any) => { return this._withEvent((event: any) => {
if (!value?.getInstrument) { if (!event.context.getInstrument) {
throw new Error('cannot chain adsr: need instrument first (like synth)'); throw new Error('cannot chain adsr: need instrument first (like synth)');
} }
const instrumentConfig = { ...value.instrumentConfig, envelope: { attack, decay, sustain, release } }; const instrumentConfig = { ...event.context.instrumentConfig, envelope: { attack, decay, sustain, release } };
const getInstrument = () => { const getInstrument = () => {
const instrument = value.getInstrument(); const instrument = event.context.getInstrument();
instrument.set(instrumentConfig); instrument.set(instrumentConfig);
return instrument; return instrument;
}; };
const onTrigger = getTrigger(() => getInstrument().toDestination(), value.value); const onTrigger = getTrigger(() => getInstrument().toDestination(), event.value);
return { ...value, getInstrument, instrumentConfig, onTrigger }; return event.setContext({ ...event.context, getInstrument, instrumentConfig, onTrigger });
}); });
}; };
Pattern.prototype.chain = function (...effectGetters: any) { Pattern.prototype.chain = function (...effectGetters: any) {
return this.fmap((value: any) => { return this._withEvent((event: any) => {
if (!value?.getInstrument) { if (!event.context?.getInstrument) {
throw new Error('cannot chain: need instrument first (like synth)'); throw new Error('cannot chain: need instrument first (like synth)');
} }
const chain = (value.chain || []).concat(effectGetters); const chain = (event.context.chain || []).concat(effectGetters);
const getChain = () => { const getChain = () => {
const effects = chain.map((getEffect: any) => getEffect()); const effects = chain.map((getEffect: any) => getEffect());
return value.getInstrument().chain(...effects, Destination); return event.context.getInstrument().chain(...effects, Destination);
}; };
const onTrigger = getTrigger(getChain, value.value); const onTrigger = getTrigger(getChain, event.value);
return { ...value, getChain, onTrigger, chain }; return event.setContext({ ...event.context, getChain, onTrigger, chain });
}); });
}; };

View File

@ -56,8 +56,9 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent }: any) {
(time, event) => { (time, event) => {
try { try {
onEvent?.(event); onEvent?.(event);
if (!event.value?.onTrigger) { const { onTrigger } = event.context;
const note = event.value?.value || event.value; if (!onTrigger) {
const note = event.value;
if (!isNote(note)) { if (!isNote(note)) {
throw new Error('not a note: ' + note); throw new Error('not a note: ' + note);
} }
@ -69,7 +70,6 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent }: any) {
/* console.warn('no instrument chosen', event); /* console.warn('no instrument chosen', event);
throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */ throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */
} else { } else {
const { onTrigger } = event.value;
onTrigger(time, event); onTrigger(time, event);
} }
} catch (err: any) { } catch (err: any) {