strudel/packages/superdough
2026-03-03 18:42:33 +01:00
..
audioContext.mjs wip 2026-01-10 01:07:09 -05:00
dspworklet.mjs Move things around to allow selection by name and avoid circular imports; fixed chebyshev 2025-09-04 11:47:01 -05:00
feedbackdelay.mjs Working version 2025-12-31 14:58:31 -06:00
fft.js fixed offset time 2024-06-12 01:11:58 -04:00
helpers.mjs sp 2026-01-17 19:11:08 -08:00
index.mjs Refactor modulators 2025-12-29 10:41:20 -06:00
logger.mjs rm comment 2025-09-16 01:48:37 -04:00
modulators.mjs Add retrig option for LFOs 2026-01-19 09:52:49 -08:00
nodePools.mjs Switch to tracking grace period in node pool; add negative begin and ends 2026-01-12 17:59:33 -06:00
noise.mjs Improve getOscillator/noiseMix release 2025-12-08 17:31:34 +00:00
ola-processor.js Document remaining functions 2025-10-12 16:07:11 +02:00
package.json fix: move kabelsalat web to superdough 2026-01-18 22:04:49 +01:00
README.md README: update superdough documentation 2025-11-15 15:06:44 +01:00
reverb.mjs WIP non-realtime exporting 2025-10-19 14:38:50 +03:00
reverbGen.mjs Merge branch 'main' of ssh://codeberg.org/vvolhejn/strudel into radical-new-docs 2026-01-10 06:58:39 -08:00
sampler.mjs moved to sampler 2026-02-19 13:59:30 -05:00
superdough.mjs moved to sampler 2026-02-19 13:59:30 -05:00
superdoughdata.mjs Fix lfos for vowels, phasers; fix ir index; more informative error message 2026-01-01 12:02:54 -06:00
superdoughoutput.mjs wip 2026-01-10 01:07:09 -05:00
synth.mjs Fix typo in phase computation 2026-02-12 18:30:50 -06:00
util.mjs Tag the remaining functions 2026-01-18 12:16:50 +01:00
vite.config.js add vite-plugin-bundle-audioworklet and use it both from website and superdough 2025-05-01 23:26:04 +02:00
vowel.mjs Fix lfos for vowels, phasers; fix ir index; more informative error message 2026-01-01 12:02:54 -06:00
wavetable.mjs tagging a lot of superdough functions 2026-01-23 23:40:51 +01:00
worklets.mjs coarse: handle non-integer parameters more smoothly 2026-02-07 16:53:06 +02:00
zzfx.mjs Fixes for zzfx and soundfonts 2025-12-29 13:28:26 -06:00
zzfx_fork.mjs Move things around to allow selection by name and avoid circular imports; fixed chebyshev 2025-09-04 11:47:01 -05:00

superdough

superdough is a simple web audio sampler and synth, intended for live coding. It is the default output of strudel. This package has no ties to strudel and can be used to quickly bake your own music system on the web.

Install

via npm:

npm i superdough --save

Use

import { superdough, samples, initAudioOnFirstClick, registerSynthSounds } from 'superdough';

const init = Promise.all([
  initAudioOnFirstClick(),
  samples('github:tidalcycles/dirt-samples'),
  registerSynthSounds(),
]);

const loop = (t = 0) => {
  // superdough(value, time, duration)
  superdough({ s: 'bd', delay: 0.5 }, t);
  superdough({ note: 'g1', s: 'sawtooth', cutoff: 600, resonance: 8 }, t, 0.125);
  superdough({ note: 'g2', s: 'sawtooth', cutoff: 600, resonance: 8 }, t + 0.25, 0.125);
  superdough({ s: 'hh' }, t + 0.25);
  superdough({ s: 'sd', room: 0.5 }, t + 0.5);
  superdough({ s: 'hh' }, t + 0.75);
};

document.getElementById('play').addEventListener('click', async () => {
  await init;
  let t = 0.1;
  while (t < 16) {
    loop(t++);
  }
});

Open this in Codesandbox

API

superdough(value, deadline, duration)

superdough({ s: 'bd', delay: 0.5 }, 0, 1);
  • value: the sound properties:
    • s: the name of the sound as loaded via samples or registerSound
    • n: selects sample with given index
    • bank: prefix_ that is attached to the sound, e.g. { s: 'bd', bank: 'RolandTR909' } = { s: 'RolandTR909_bd' }
    • gain: gain from 0 to 1 (higher values also work but might clip)
    • velocity: additional gain multiplier
    • cutoff: low pass filter cutoff
    • resonance: low pass filter resonance
    • hcutoff: high pass filter cutoff
    • hresonance: high pass filter resonance
    • bandf: band pass filter cutoff
    • bandq: band pass filter resonance
    • crush: amplitude bit crusher using given number of bits
    • distort: distortion effect. might get loud!
    • pan: stereo panning from 0 (left) to 1 (right)
    • phaser: sets the speed of the modulation
    • phaserdepth: the amount the signal is affected by the phaser effect.
    • phasersweep: the frequency sweep range of the lfo for the phaser effect.
    • phasercenter: the amount the signal is affected by the phaser effect.
    • vowel: vowel filter. possible values: "a", "e", "i", "o", "u"
    • delay: delay mix
    • delayfeedback: delay feedback
    • delaytime: delay time
    • room: reverb mix
    • size: reverb room size
    • orbit: bus name for global effects delay and room. same orbits will get the same effects
    • freq: repitches sound to given frequency in Hz
    • note: repitches sound to given note or midi number
    • cut: sets cut group. Sounds of same group will cut each other off
    • clip: multiplies duration with given number
    • speed: repitches sound by given factor
    • begin: moves beginning of sample to given factor (between 0 and 1)
    • end: moves end of sample to given factor (between 0 and 1)
    • attack: seconds of attack phase
    • decay: seconds of decay phase
    • sustain: gain of sustain phase
    • release: seconds of release phase
  • deadline: seconds from audio context initialization before playing the sound (getAudioContextCurrentTime() = immediate)
  • duration: seconds the sound should last. optional for one shot samples, required for synth sounds

registerSynthSounds()

Loads the default waveforms sawtooth, square, triangle and sine. Use them like this:

superdough({ s:'sawtooth' }, 0, 1)

The duration needs to be set for these sounds!

samples(sampleMap)

allows you to load samples from URLs. There are 3 ways to load samples

  1. sample map object
  2. url of sample map json file
  3. github repo

sample map object

You can pass a sample map like this:

samples({
  '_base': 'https://raw.githubusercontent.com/felixroos/samples/main/',
  'bd': 'president/president_bd.mp3',
  'sd': ['president/president_sd.mp3', 'president/president_sd2.mp3'],
  'hh': ['president/president_hh.mp3'],
})

The _base property defines the root url while the others declare one or more sample paths for each sound.

For example the full URL for bd would then be https://raw.githubusercontent.com/felixroos/samples/main/president/president_bd.mp3

A loaded sound can then be played with superdough({ s: 'bd' }, 0).

If you declare multiple sounds, you can select them with n: superdough({ s: 'sd', n: 1 }, 0)

The duration property is not needed for samples.

loading samples from a json file

Instead of passing an object as a sample map, you can also pass a URL to a json that contains a sample map:

samples('https://raw.githubusercontent.com/felixroos/samples/main/strudel.json')

The json file is expected to have the same format as described above.

loading samples from a github repo

Because it is common to use github for samples, there is a short way to load a sample map from github:

samples('github:tidalcycles/dirt-samples')

The format is github:<user>/<repo>/<branch>.

If <repo> and <branch> are not specified, they will default to samples and main respectively. It expects a strudel.json file to be present at the root of the given repository, which declares the sample paths in the repo.

The format is also expected to be the same as explained above.

initAudioOnFirstClick()

Initializes audio and makes sure it is playable after the first click in the document. A click is needed because of the Autoplay Policy. You can call this function when the document loads. Then just make sure your first call of superdough happens after a click of something.

Credits