diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 717a8353..6a7e6b4b 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -802,8 +802,29 @@ const generic_params = [ * */ ['clip'], -]; + // ZZFX + //['volume'], + ['randomness'], + // ['frequency'], => freq + /* ['attack'], + ['decay'], + ['sustain'], + ['release'], */ + // ['shape'], // duplicate + ['shapeCurve'], + // ['slide'], // superdirt duplicate + ['deltaSlide'], + ['pitchJump'], + ['pitchJumpTime'], + ['repeatTime'], + ['noise'], + ['modulation'], + ['bitCrush'], // like crush.. + //['delay'], // duplicate + // ['sustainVolume'], // not needed? + ['tremolo'], +]; // TODO: slice / splice https://www.youtube.com/watch?v=hKhPdO0RKDQ&list=PL2lW1zNIIwj3bDkh-Y3LUGDuRcoUigoDs&index=13 controls.createParam = function (names) { diff --git a/packages/superdough/helpers.mjs b/packages/superdough/helpers.mjs index 622d3a38..ddd94fca 100644 --- a/packages/superdough/helpers.mjs +++ b/packages/superdough/helpers.mjs @@ -1,5 +1,5 @@ import { getAudioContext } from './superdough.mjs'; -import * as zzfx from 'zzfx'; +import { ZZFX } from 'zzfx'; export function gainNode(value) { const node = getAudioContext().createGain(); @@ -7,27 +7,97 @@ export function gainNode(value) { return node; } -export const getZZFX = ({ wave, freq, t, params}) => { - params.frequency = freq; - params.shape = { - 'zsine': 0, - 'ztri': 1, - 'zsaw': 2, - 'ztan': 3, - 'znoise': 4, - }[wave]; - const samples = zzfx.buildSamples(...params); +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( - samples.length, - samples[0].length, - context.sampleRate - ); - const source = context.createBufferSource(); + 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, - stop: (time) => source.stop(time), buffer} -} + node: source, + }; +}; export const getOscillator = ({ s, freq, t }) => { // make oscillator diff --git a/packages/superdough/synth.mjs b/packages/superdough/synth.mjs index 9d3b2b0b..02cf4c8a 100644 --- a/packages/superdough/synth.mjs +++ b/packages/superdough/synth.mjs @@ -22,45 +22,18 @@ const fm = (osc, harmonicityRatio, modulationIndex, wave = 'sine') => { export function registerSynthSounds() { ['zsine', 'zsaw', 'ztri', 'ztan', 'znoise'].forEach((wave) => { - registerSound( - wave, - (t, value, onended) => { - const { - attack = 0.001, - decay = 0.05, - sustain = 0.6, - release = 0.01, - } = value; - let { n, note, freq } = value; - n = note || n || 36; - if (typeof n === 'string') { - n = noteToMidi(n); // e.g. c3 => 48 - } - // get frequency - if (!freq && typeof n === 'number') { - freq = midiToFreq(n); // + 48); - } - const params = {}; - const { node: o, stop } = getZZFX({ wave, freq, t, params }); - const g = gainNode(0.3); - // envelope - const { node: envelope, stop: releaseEnvelope } = getEnvelope(attack, decay, sustain, release, 1, t); - o.onended = () => { - o.disconnect(); - g.disconnect(); - onended(); - }; - console.log(o) - return { - node: o.connect(g).connect(envelope), - stop: (releaseTime) => { - releaseEnvelope(releaseTime); - let end = releaseTime + release; - stop(end); - }, - }; - } - ) + 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: () => {}, + }; + }); }); ['sine', 'square', 'triangle', 'sawtooth'].forEach((wave) => {