add getPlayableNoteValue helper

This commit is contained in:
Felix Roos 2022-02-28 23:32:22 +01:00
parent 1242b1738a
commit ffe258a9fb
3 changed files with 20 additions and 14 deletions

View File

@ -16,9 +16,10 @@ import {
NoiseSynth, NoiseSynth,
PluckSynth, PluckSynth,
Sampler, Sampler,
getDestination getDestination,
} from 'tone'; } from 'tone';
import { Piano } from '@tonejs/piano'; import { Piano } from '@tonejs/piano';
import { getPlayableNoteValue } from '../../util.mjs';
// what about // what about
// https://www.charlie-roberts.com/gibberish/playground/ // https://www.charlie-roberts.com/gibberish/playground/
@ -30,13 +31,15 @@ Pattern.prototype.tone = function (instrument) {
// instrument.toDestination(); // instrument.toDestination();
return this._withEvent((event) => { return this._withEvent((event) => {
const onTrigger = (time, event) => { const onTrigger = (time, event) => {
const note = getPlayableNoteValue(event);
// TODO: test if all tonejs instruments can handle freqs
if (instrument.constructor.name === 'PluckSynth') { if (instrument.constructor.name === 'PluckSynth') {
instrument.triggerAttack(event.value, time); instrument.triggerAttack(note, 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 if (instrument.constructor.name === 'Piano') { } else if (instrument.constructor.name === 'Piano') {
instrument.keyDown({ note: event.value, time, velocity: 0.5 }); instrument.keyDown({ note, time, velocity: 0.5 });
instrument.keyUp({ note: event.value, time: time + event.duration }); instrument.keyUp({ note, time: time + event.duration });
} else { } else {
instrument.triggerAttackRelease(event.value, event.duration, time); instrument.triggerAttackRelease(event.value, event.duration, time);
} }

View File

@ -1,6 +1,5 @@
import { useCallback, useState, useMemo } from 'react'; import { useCallback, useState, useMemo } from 'react';
import { isNote } from 'tone'; import { getPlayableNoteValue } from '../../util.mjs';
import { fromMidi } from '../../util.mjs';
import { evaluate } from './evaluate'; import { evaluate } from './evaluate';
import type { Pattern } from './types'; import type { Pattern } from './types';
import useCycle from './useCycle'; import useCycle from './useCycle';
@ -64,15 +63,8 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw }: any)
onEvent?.(event); onEvent?.(event);
const { onTrigger } = event.context; const { onTrigger } = event.context;
if (!onTrigger) { if (!onTrigger) {
let note = event.value;
// if value is number => interpret as midi number...
// TODO: what if value is meant as frequency? => check context
if (typeof event.value === 'number') {
note = fromMidi(event.value);
} else if (!isNote(note)) {
throw new Error('not a note: ' + note);
}
if (defaultSynth) { if (defaultSynth) {
const note = getPlayableNoteValue(event);
defaultSynth.triggerAttackRelease(note, event.duration, time); defaultSynth.triggerAttackRelease(note, event.duration, time);
} else { } else {
throw new Error('no defaultSynth passed to useRepl.'); throw new Error('no defaultSynth passed to useRepl.');

View File

@ -28,3 +28,14 @@ export const fromMidi = (n) => {
// modulo that works with negative numbers e.g. mod(-1, 3) = 2 // modulo that works with negative numbers e.g. mod(-1, 3) = 2
// const mod = (n: number, m: number): number => (n < 0 ? mod(n + m, m) : n % m); // const mod = (n: number, m: number): number => (n < 0 ? mod(n + m, m) : n % m);
export const mod = (n, m) => (n < 0 ? mod(n + m, m) : n % m); export const mod = (n, m) => (n < 0 ? mod(n + m, m) : n % m);
export const getPlayableNoteValue = (event) => {
let { value: note, context } = event;
// if value is number => interpret as midi number as long as its not marked as frequency
if (typeof note === 'number' && context.type !== 'frequency') {
note = fromMidi(event.value);
} else if (typeof note === 'string' && !isNote(note)) {
throw new Error('not a note: ' + note);
}
return note;
};