diff --git a/packages/react/examples/nano-repl/src/App.jsx b/packages/react/examples/nano-repl/src/App.jsx index 086923ac..f84356c7 100644 --- a/packages/react/examples/nano-repl/src/App.jsx +++ b/packages/react/examples/nano-repl/src/App.jsx @@ -6,6 +6,7 @@ import { panic, webaudioOutput, registerSynthSounds, + registerZZFXSounds, } from '@strudel.cycles/webaudio'; import { registerSoundfonts } from '@strudel.cycles/soundfonts'; import { useCallback, useState } from 'react'; @@ -26,7 +27,7 @@ async function init() { import('@strudel.cycles/osc'), ); - await Promise.all([loadModules, registerSynthSounds(), registerSoundfonts()]); + await Promise.all([loadModules, registerSynthSounds(), registerZZFXSounds(), registerSoundfonts()]); } init(); diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs index ddd94fca..7cc54c8d 100644 --- a/packages/superdough/helpers.mjs +++ b/packages/superdough/helpers.mjs @@ -1,5 +1,4 @@ import { getAudioContext } from './superdough.mjs'; -import { ZZFX } from 'zzfx'; export function gainNode(value) { const node = getAudioContext().createGain(); @@ -7,98 +6,6 @@ export function gainNode(value) { return node; } -export const getZZFX = (value, t, duration) => { - let { - s, - note = 36, - freq, - // - randomness = 0, - attack = 0, - decay = 0, - sustain = 0.8, - release = 0.1, - shapeCurve = 1, - slide = 0, - deltaSlide = 0, - pitchJump = 0, - pitchJumpTime = 0, - repeatTime = 0, - noise = 0, - modulation = 0, - bitCrush = 0, - delay = 0, - tremolo = 0, - } = value; - if (typeof note === 'string') { - note = noteToMidi(note); // e.g. c3 => 48 - } - // get frequency - if (!freq && typeof n === 'number') { - freq = midiToFreq(n); - } - const shape = ['zsine', 'ztri', 'zsaw', 'ztan', 'znoise'].indexOf(s) || 0; - - const params = [ - 1, // volume - randomness, // randomness - freq, - attack, - duration, // sustain time - release, - shape, - shapeCurve, - slide, - deltaSlide, - pitchJump, - pitchJumpTime, - repeatTime, - noise, - modulation, - bitCrush, - delay, - sustain, // sustain volume! - decay, - tremolo, - ]; - const paramOrder = [ - 'volume', - 'randomness', - 'frequency', - 'attack', - 'sustain', - 'release', - 'shape', - 'shapeCurve', - 'slide', - 'deltaSlide', - 'pitchJump', - 'pitchJumpTime', - 'repeatTime', - 'noise', - 'modulation', - 'bitCrush', - 'delay', - 'sustainVolume', - 'decay', - 'tremolo', - ]; - - const readableParams = Object.fromEntries(paramOrder.map((param, i) => [param, params[i]])); - console.log(readableParams); - - const samples = ZZFX.buildSamples(...params); - const context = getAudioContext(); - const buffer = context.createBuffer(1, samples.length, context.sampleRate); - buffer.getChannelData(0).set(samples); - const source = getAudioContext().createBufferSource(); - source.buffer = buffer; - source.start(t); - return { - node: source, - }; -}; - export const getOscillator = ({ s, freq, t }) => { // make oscillator const o = getAudioContext().createOscillator(); diff --git a/packages/superdough/index.mjs b/packages/superdough/index.mjs index b795539a..e5d4498b 100644 --- a/packages/superdough/index.mjs +++ b/packages/superdough/index.mjs @@ -8,4 +8,5 @@ export * from './superdough.mjs'; export * from './sampler.mjs'; export * from './helpers.mjs'; export * from './synth.mjs'; +export * from './zzfx.mjs'; export * from './logger.mjs'; diff --git a/packages/superdough/zzfx.mjs b/packages/superdough/zzfx.mjs new file mode 100644 index 00000000..a8ddf30b --- /dev/null +++ b/packages/superdough/zzfx.mjs @@ -0,0 +1,110 @@ +import { ZZFX } from 'zzfx'; + +export const getZZFX = (value, t, duration) => { + let { + s, + note = 36, + freq, + // + randomness = 0, + attack = 0, + decay = 0, + sustain = 0.8, + release = 0.1, + shapeCurve = 1, + slide = 0, + deltaSlide = 0, + pitchJump = 0, + pitchJumpTime = 0, + repeatTime = 0, + noise = 0, + modulation = 0, + bitCrush = 0, + delay = 0, + tremolo = 0, + } = value; + if (typeof note === 'string') { + note = noteToMidi(note); // e.g. c3 => 48 + } + // get frequency + if (!freq && typeof n === 'number') { + freq = midiToFreq(n); + } + const shape = ['zsine', 'ztri', 'zsaw', 'ztan', 'znoise'].indexOf(s) || 0; + + const params = [ + 1, // volume + randomness, // randomness + freq, + attack, + duration, // sustain time + release, + shape, + shapeCurve, + slide, + deltaSlide, + pitchJump, + pitchJumpTime, + repeatTime, + noise, + modulation, + bitCrush, + delay, + sustain, // sustain volume! + decay, + tremolo, + ]; + const paramOrder = [ + 'volume', + 'randomness', + 'frequency', + 'attack', + 'sustain', + 'release', + 'shape', + 'shapeCurve', + 'slide', + 'deltaSlide', + 'pitchJump', + 'pitchJumpTime', + 'repeatTime', + 'noise', + 'modulation', + 'bitCrush', + 'delay', + 'sustainVolume', + 'decay', + 'tremolo', + ]; + + const readableParams = Object.fromEntries(paramOrder.map((param, i) => [param, params[i]])); + console.log(readableParams); + + const samples = ZZFX.buildSamples(...params); + const context = getAudioContext(); + const buffer = context.createBuffer(1, samples.length, context.sampleRate); + buffer.getChannelData(0).set(samples); + const source = getAudioContext().createBufferSource(); + source.buffer = buffer; + source.start(t); + return { + node: source, + }; +}; + +export function registerZZFXSounds() { + ['zsine', 'zsaw', 'ztri', 'ztan', 'znoise'].forEach((wave) => { + registerSound(wave, (t, value, onended) => { + const duration = 0.2; + const { node: o } = getZZFX({ s: wave, ...value }, t, duration); + o.onended = () => { + o.disconnect(); + onended(); + }; + return { + node: o, + stop: () => {}, + }; + }); + }); +}