mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 05:38:34 +00:00
document setSound api
This commit is contained in:
parent
41d82eaadf
commit
ff1e6714c6
@ -18,6 +18,9 @@ export const soundMap = map();
|
||||
export function setSound(key, onTrigger, data = {}) {
|
||||
soundMap.setKey(key, { onTrigger, data });
|
||||
}
|
||||
export function getSound(s) {
|
||||
return soundMap.get()[s];
|
||||
}
|
||||
export const resetLoadedSounds = () => soundMap.set({});
|
||||
|
||||
let audioContext;
|
||||
@ -166,8 +169,8 @@ export const webaudioOutput = async (hap, deadline, hapDuration, cps) => {
|
||||
let sourceNode;
|
||||
if (source) {
|
||||
sourceNode = source(t, hap.value);
|
||||
} else if (soundMap.get()[s]) {
|
||||
const { onTrigger } = soundMap.get()[s];
|
||||
} else if (getSound(s)) {
|
||||
const { onTrigger } = getSound(s);
|
||||
const soundHandle = await onTrigger(t, hap.value, onended);
|
||||
if (soundHandle) {
|
||||
sourceNode = soundHandle.node;
|
||||
|
||||
@ -73,6 +73,7 @@ export const SIDEBAR: Sidebar = {
|
||||
],
|
||||
Development: [
|
||||
{ text: 'REPL', link: 'technical-manual/repl' },
|
||||
{ text: 'Sounds', link: 'technical-manual/sounds' },
|
||||
{ text: 'Packages', link: 'technical-manual/packages' },
|
||||
{ text: 'Docs', link: 'technical-manual/docs' },
|
||||
{ text: 'Testing', link: 'technical-manual/testing' },
|
||||
|
||||
75
website/src/pages/technical-manual/sounds.mdx
Normal file
75
website/src/pages/technical-manual/sounds.mdx
Normal file
@ -0,0 +1,75 @@
|
||||
---
|
||||
title: Sounds
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
import { MiniRepl } from '../../docs/MiniRepl';
|
||||
|
||||
# Sounds
|
||||
|
||||
Let's take a closer look about how sounds are implemented in the webaudio output.
|
||||
|
||||
## Registering a sound via setSound
|
||||
|
||||
All sounds are registered in the sound map, using the the `setSound` function:
|
||||
|
||||
```ts
|
||||
function setSound(
|
||||
name: string, // The name of the sound that should be given to `s`, e.g. `mysaw`
|
||||
// The function called by the scheduler to trigger the sound:
|
||||
(
|
||||
time: number, // The audio context time the sound should start
|
||||
value: object, // The value of the `Hap`
|
||||
onended: () => void // A callback that should be fired when the sound has ended
|
||||
) => {
|
||||
node: AudioNode, // node to connect to rest of the effects chain
|
||||
stop: (time:number) => void // a function that will stop the sound
|
||||
},
|
||||
data: object // meta data, only for ui logic in sounds tab
|
||||
);
|
||||
```
|
||||
|
||||
When `setSound` is called, it registers `{ onTrigger, data }` under the given `name` in a [nanostore map](https://github.com/nanostores/nanostores#maps).
|
||||
|
||||
### Example
|
||||
|
||||
This might be a bit abstract, so here is a minimal example:
|
||||
|
||||
```js
|
||||
setSound(
|
||||
'mysaw',
|
||||
(time, value, onended) => {
|
||||
let { freq } = value; // destructure control params
|
||||
const ctx = getAudioContext();
|
||||
// create oscillator
|
||||
const o = new OscillatorNode(ctx, { type: 'sawtooth', frequency: Number(freq) });
|
||||
o.start(time);
|
||||
// add gain node to level down osc
|
||||
const g = new GainNode(ctx, { gain: 0.3 });
|
||||
// connect osc to gain
|
||||
const node = o.connect(g);
|
||||
// this function can be called from outside to stop the sound
|
||||
const stop = (time) => o.stop(time);
|
||||
// ended will be fired when stop has been fired
|
||||
o.addEventListener('ended', () => {
|
||||
o.disconnect();
|
||||
g.disconnect();
|
||||
onended();
|
||||
});
|
||||
return { node, stop };
|
||||
},
|
||||
{ type: 'synth' },
|
||||
);
|
||||
// use the sound
|
||||
freq(220, 440, 330).s('mysaw');
|
||||
```
|
||||
|
||||
You can actually use this code in the [REPL](https://strudel.tidalcycles.org/) and it'll work.
|
||||
After evaluating the code, you should see `mysaw` in listed in the sounds tab.
|
||||
|
||||
## Playing sounds
|
||||
|
||||
Now here is what happens when a sound is played:
|
||||
When the webaudio output plays a `Hap`, it will lookup and call the `onTrigger` function for the given `s`.
|
||||
The returned `node` can then be connected to the rest of the standard effects chain
|
||||
Having the stop function separate allows playing sounds via midi too, where you don't know how long the noteon will last
|
||||
Loading…
x
Reference in New Issue
Block a user