mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 13:48:40 +00:00
91 lines
2.9 KiB
HTML
91 lines
2.9 KiB
HTML
<div style="position: absolute; bottom: 0; right: 0; padding: 4px; width: 100vw; display: flex">
|
|
<button id="start" style="font-size: 2em">start</button>
|
|
<button id="stop" style="font-size: 2em">stop</button>
|
|
<button id="slower" style="font-size: 2em">slower</button>
|
|
<button id="faster" style="font-size: 2em">faster</button>
|
|
</div>
|
|
<textarea
|
|
style="font-size: 2em; background: #052b49; color: #fff; height: 100%; width: 100%; outline: none; border: 0"
|
|
id="text"
|
|
spellcheck="false"
|
|
>
|
|
Loading...</textarea
|
|
>
|
|
<script type="module">
|
|
document.body.style = 'margin: 0';
|
|
import * as strudel from '@strudel.cycles/core';
|
|
|
|
const { cat, State, TimeSpan, Scheduler, getPlayableNoteValue, getFreq } = strudel;
|
|
Object.assign(window, strudel); // add strudel to eval scope
|
|
|
|
const ctx = new AudioContext();
|
|
const scheduler = new Scheduler({
|
|
// audioContext: getAudioContext(),
|
|
interval: 0.1,
|
|
onTrigger: (hap, time, duration) => {
|
|
const freq = getFrequency(hap);
|
|
const osc = ctx.createOscillator();
|
|
const gain = 0.2;
|
|
osc.frequency.value = freq;
|
|
osc.type = 'triangle';
|
|
const onset = ctx.currentTime + time;
|
|
const offset = onset + duration;
|
|
const attack = 0.05;
|
|
const release = 0.05;
|
|
osc.start(onset);
|
|
osc.stop(offset + release);
|
|
|
|
const g = ctx.createGain();
|
|
g.gain.setValueAtTime(gain, onset);
|
|
g.gain.linearRampToValueAtTime(gain, onset + attack);
|
|
g.gain.setValueAtTime(gain, offset - release);
|
|
g.gain.linearRampToValueAtTime(0, offset);
|
|
osc.connect(g);
|
|
g.connect(ctx.destination);
|
|
},
|
|
});
|
|
|
|
let initialCode = `stack('c4','e4',cat('g4','a4','b4','a4'))
|
|
.add(cat(0,1,2,3,4,3,2,1).slow(8))
|
|
.fast(2)
|
|
.cps(tri.range(1,8).slow(32))`;
|
|
|
|
try {
|
|
const base64 = decodeURIComponent(window.location.href.split('#')[1]);
|
|
initialCode = atob(base64);
|
|
} catch (err) {
|
|
console.warn('failed to decode', err);
|
|
}
|
|
const input = document.getElementById('text');
|
|
input.value = initialCode;
|
|
const evaluate = () => {
|
|
try {
|
|
const pattern = eval(input.value);
|
|
scheduler.setPattern(pattern);
|
|
window.location.hash = '#' + encodeURIComponent(btoa(input.value)); // update url hash
|
|
} catch (err) {
|
|
console.warn(err);
|
|
}
|
|
};
|
|
evaluate();
|
|
input.addEventListener('input', () => evaluate());
|
|
document.getElementById('start').addEventListener('click', async () => {
|
|
await ctx.resume();
|
|
scheduler.start();
|
|
});
|
|
document.getElementById('stop').addEventListener('click', () => scheduler.stop());
|
|
document.getElementById('slower').addEventListener('click', () => scheduler.setCps(scheduler.cps - 0.1));
|
|
document.getElementById('faster').addEventListener('click', () => scheduler.setCps(scheduler.cps + 0.1));
|
|
</script>
|
|
<!--
|
|
sequence(1,2).mul(55/2) // frequencies
|
|
.mul(slowcat(1,2))
|
|
.mul(slowcat(1,3/2,4/3,5/3).slow(8))
|
|
.fast(3)
|
|
.freq()
|
|
.velocity(.5)
|
|
.s('sawtooth')
|
|
.cutoff(800)
|
|
.out()
|
|
-->
|