1--- 2title: Sounds 3layout: ../../layouts/MainLayout.astro 4--- 5 6import { MiniRepl } from '../../docs/MiniRepl'; 7 8# Sounds 9 10Let's take a closer look about how sounds are implemented in the webaudio output. 11 12## Registering a sound 13 14All sounds are registered in the sound map, using the the `registerSound` function: 15 16```js 17function registerSound( 18 name: string, // The name of the sound that should be given to `s`, e.g. `mysaw` 19 // The function called by the scheduler to trigger the sound: 20 ( 21 time: number, // The audio context time the sound should start 22 value: object, // The value of the `Hap` 23 onended: () => void // A callback that should be fired when the sound has ended 24 ) => { 25 node: AudioNode, // node to connect to rest of the effects chain 26 stop: (time:number) => void // a function that will stop the sound 27 }, 28 data: object // meta data, only for ui logic in sounds tab 29); 30``` 31 32When `registerSound` is called, it registers `{ onTrigger, data }` under the given `name` in a [nanostore map](https://github.com/nanostores/nanostores#maps). 33 34### Example 35 36This might be a bit abstract, so here is a minimal example: 37 38<MiniRepl 39 client:idle 40 tune={` 41 registerSound( 42 'mysaw', 43 (time, value, onended) => { 44 let { freq } = value; // destructure control params 45 const ctx = getAudioContext(); 46 // create oscillator 47 const o = new OscillatorNode(ctx, { type: 'sawtooth', frequency: Number(freq) }); 48 o.start(time); 49 // add gain node to level down osc 50 const g = new GainNode(ctx, { gain: 0.3 }); 51 // connect osc to gain 52 const node = o.connect(g); 53 // this function can be called from outside to stop the sound 54 const stop = (time) => o.stop(time); 55 // ended will be fired when stop has been fired 56 o.addEventListener('ended', () => { 57 o.disconnect(); 58 g.disconnect(); 59 onended(); 60 }); 61 return { node, stop }; 62 }, 63 { type: 'synth' }, 64 ); 65 // use the sound 66 freq("220 440 330").s('mysaw');`} 67/> 68 69You can actually use this code in the [REPL](https://strudel.cc/) and it'll work. 70After evaluating the code, you should see `mysaw` in listed in the sounds tab. 71 72## Playing sounds 73 74Now here is what happens when a sound is played: 75When the webaudio output plays a `Hap`, it will lookup and call the `onTrigger` function for the given `s`. 76The returned `node` can then be connected to the rest of the standard effects chain 77Having the stop function separate allows playing sounds via midi too, where you don't know how long the noteon will last