can now pass meta data to setSound

+ added types for synth and sample
+ list sample count for samples in sounds tab (as before)
This commit is contained in:
Felix Roos 2023-03-07 21:43:01 +01:00
parent b08a0b8102
commit 35ef26c013
4 changed files with 39 additions and 34 deletions

View File

@ -149,7 +149,7 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '') => {
}), }),
); );
} }
setSound(key, (options) => onTriggerSample(options, value)); setSound(key, (options) => onTriggerSample(options, value), { type: 'sample', samples: value });
}); });
}; };

View File

@ -4,31 +4,35 @@ import { getOscillator, gainNode, getADSR } from './helpers.mjs';
export function registerSynthSounds() { export function registerSynthSounds() {
['sine', 'square', 'triangle', 'sawtooth'].forEach((wave) => { ['sine', 'square', 'triangle', 'sawtooth'].forEach((wave) => {
setSound(wave, ({ hap, duration, t }) => { setSound(
// destructure adsr here, because the default should be different for synths and samples wave,
const { attack = 0.001, decay = 0.05, sustain = 0.6, release = 0.01 } = hap.value; ({ hap, duration, t }) => {
let { n, note, freq } = hap.value; // destructure adsr here, because the default should be different for synths and samples
// with synths, n and note are the same thing const { attack = 0.001, decay = 0.05, sustain = 0.6, release = 0.01 } = hap.value;
n = note || n || 36; let { n, note, freq } = hap.value;
if (typeof n === 'string') { // with synths, n and note are the same thing
n = toMidi(n); // e.g. c3 => 48 n = note || n || 36;
} if (typeof n === 'string') {
// get frequency n = toMidi(n); // e.g. c3 => 48
if (!freq && typeof n === 'number') { }
freq = fromMidi(n); // + 48); // get frequency
} if (!freq && typeof n === 'number') {
// maybe pull out the above frequency resolution?? (there is also getFrequency but it has no default) freq = fromMidi(n); // + 48);
// make oscillator }
const o = getOscillator({ t, s: wave, freq, duration, release }); // maybe pull out the above frequency resolution?? (there is also getFrequency but it has no default)
// chain.push(o); // make oscillator
// level down oscillators as they are really loud compared to samples i've tested const o = getOscillator({ t, s: wave, freq, duration, release });
//chain.push(gainNode(0.3)); // chain.push(o);
const g = gainNode(0.3); // level down oscillators as they are really loud compared to samples i've tested
// TODO: make adsr work with samples without pops //chain.push(gainNode(0.3));
// envelope const g = gainNode(0.3);
const adsr = getADSR(attack, decay, sustain, release, 1, t, t + duration); // TODO: make adsr work with samples without pops
//chain.push(adsr); // envelope
return o.connect(g).connect(adsr); const adsr = getADSR(attack, decay, sustain, release, 1, t, t + duration);
}); //chain.push(adsr);
return o.connect(g).connect(adsr);
},
{ type: 'synth' },
);
}); });
} }

View File

@ -15,8 +15,8 @@ import { map } from 'nanostores';
export const soundMap = map(); export const soundMap = map();
// onTrigger = ({ hap: Hap, t: number, deadline: number, duration: number, cps: number }) => AudioNode // onTrigger = ({ hap: Hap, t: number, deadline: number, duration: number, cps: number }) => AudioNode
export function setSound(key, onTrigger) { export function setSound(key, onTrigger, data = {}) {
soundMap.setKey(key, onTrigger); soundMap.setKey(key, { onTrigger, data });
} }
export const resetLoadedSounds = () => soundMap.set({}); export const resetLoadedSounds = () => soundMap.set({});
@ -166,7 +166,8 @@ export const webaudioOutput = async (hap, deadline, hapDuration, cps) => {
if (source) { if (source) {
node = source(options); node = source(options);
} else if (soundMap.get()[s]) { } else if (soundMap.get()[s]) {
node = await soundMap.get()[s](options); const { onTrigger } = soundMap.get()[s];
node = await onTrigger(options);
} else { } else {
throw new Error(`sound ${s} not found! Is it loaded?`); throw new Error(`sound ${s} not found! Is it loaded?`);
} }

View File

@ -196,15 +196,15 @@ function ConsoleTab({ log }) {
function SoundsTab() { function SoundsTab() {
const sounds = useStore(soundMap); const sounds = useStore(soundMap);
const getSamples = (samples) =>
Array.isArray(samples) ? samples.length : typeof samples === 'object' ? Object.values(samples).length : 1;
return ( return (
<div id="sounds-tab" className="break-normal w-full px-4 dark:text-white text-stone-900"> <div id="sounds-tab" className="break-normal w-full px-4 dark:text-white text-stone-900">
{/* <span>{loadedSamples.length} banks loaded:</span> */} {/* <span>{loadedSamples.length} banks loaded:</span> */}
{Object.entries(sounds).map(([name, samples]) => ( {Object.entries(sounds).map(([name, { data }]) => (
<span key={name} className="cursor-pointer hover:opacity-50" onClick={() => {}}> <span key={name} className="cursor-pointer hover:opacity-50" onClick={() => {}}>
{' '} {' '}
{name} {name} {data?.type === 'sample' ? `(${getSamples(data.samples)})` : ''}
{/* (
{Array.isArray(samples) ? samples.length : typeof samples === 'object' ? Object.values(samples).length : 1}) */}
</span> </span>
))} ))}
</div> </div>