tidalcycles / strudel

Web-based environment for live coding algorithmic patterns, incorporating a faithful port of TidalCycles to JavaScript
https://strudel.cc/
GNU Affero General Public License v3.0
587 stars 105 forks source link

add sf2 soundfonts to sound registry #182

Open felixroos opened 1 year ago

felixroos commented 1 year ago

instead of (or in addition to) .soundfont, soundfont presets should be usable via .s, integrating with .out. When loadSoundfont is called, all presets in the loaded soundfont are added to the available sounds of s. Some type of sound registry has to be implemented to be able to add sounds from outside (webaudio package should not depend on soundfont package). Also remove the old non sf2 file based soundfonts

felixroos commented 1 year ago

idea: add a new function that takes in a callback for creating the source web audio node:

note("c a f e").sourceNode((hap, deadline, duration, cps) => {
  /* webaudio code that uses above params to create a webaudio node * /
  return node;
}).lpf(1000)

the function is similar to onTrigger, but instead of being just a general purpose callback, the function is expected to return a web audio node, which is used by the webaudio output to apply the standard chain. Advantages:

the same approach could potentially also work for custom effects, e.g. effectNode

felixroos commented 1 year ago

this works really well! it opens up some interesting possibilities:

const lfo = (freq, type = 'sine', range = 1) => {
  const ctx = getAudioContext();
  const osc = ctx.createOscillator();
  osc.type = type;
  osc.frequency.value = freq;
  osc.start();
  const g = new GainNode(ctx, { gain: range/2 });
  osc.connect(g); // -range, range
  return g;
}
const pitchLFO = lfo(.1, 'sine', 20);

note("c eb a*4 c4".add("12,12.05")).legato(.5 )
  .source((t, value, duration) => {
    const { release = 0.01 } = value;
    const ctx = getAudioContext();
    const o = ctx.createOscillator();
    o.type = 'sawtooth';
    const freq = getFrequency({value});
    o.frequency.value = Number(freq/2);
    o.start(t);
    o.stop(t + duration + release)
    pitchLFO.connect(o.frequency)
    return o;
  })
  .room(.5).lpf(800)
  .gain(.5)

this cries for a thin web audio abstraction layer..

felixroos commented 1 year ago

PR for sound registry https://github.com/tidalcycles/strudel/pull/516

felixroos commented 1 year ago

note to avoid confusion: https://github.com/tidalcycles/strudel/pull/516 now has integrated gm soundfonts based on webaudiofontdata, but the soundfonts loaded from sf2 files are still not part of the registry, so I'll leave this open