jevstrudel.git / examples / buildless / minimal-repl.html
minimal-repl.html90 lines · 2.9 KB · raw
1<!doctype html>
2<html lang="en">
3  <head>
4    <meta charset="UTF-8" />
5    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6    <title>Buildless Vanilla Strudel REPL</title>
7  </head>
8  <body style="margin: 0; background: #222">
9    <div style="display: grid; height: 100vh; grid-template-rows: 32px auto">
10      <button id="start" style="width: 100vw; height: 32px">evaluate</button>
11      <textarea
12        id="text"
13        style="font-size: 2em; border: 0; color: white; background: transparent; outline: none; padding: 20px"
14        spellcheck="false"
15      ></textarea>
16    </div>
17    <div id="output"></div>
18    <script type="module">
19      // TODO: refactor to use newer version without controls import
20      import { controls, repl, evalScope } from 'https://cdn.skypack.dev/@strudel/core@0.11.0';
21      import { mini } from 'https://cdn.skypack.dev/@strudel/mini@0.11.0';
22      import { transpiler } from 'https://cdn.skypack.dev/@strudel/transpiler@0.11.0';
23      import {
24        getAudioContext,
25        webaudioOutput,
26        initAudioOnFirstClick,
27        registerSynthSounds,
28      } from 'https://cdn.skypack.dev/@strudel/webaudio@0.11.0';
29
30      const ctx = getAudioContext();
31      const input = document.getElementById('text');
32      input.innerHTML = getTune();
33
34      const loadModules = evalScope(
35        controls,
36        import('https://cdn.skypack.dev/@strudel/core@0.11.0'),
37        import('https://cdn.skypack.dev/@strudel/mini@0.11.0'),
38        import('https://cdn.skypack.dev/@strudel/tonal@0.11.0'),
39        import('https://cdn.skypack.dev/@strudel/webaudio@0.11.0'),
40      );
41
42      const initAudio = Promise.all([initAudioOnFirstClick(), registerSynthSounds()]);
43
44      const { evaluate } = repl({
45        defaultOutput: webaudioOutput,
46        getTime: () => ctx.currentTime,
47        transpiler,
48      });
49      document.getElementById('start').addEventListener('click', async () => {
50        await loadModules;
51        await initAudio;
52        evaluate(input.value);
53      });
54
55      function getTune() {
56        return `samples('github:tidalcycles/dirt-samples')
57setcps(1);
58stack(
59  // amen
60  n("0 1 2 3 4 5 6 7")
61  .sometimes(x=>x.ply(2))
62  .rarely(x=>x.speed("2 | -2"))
63  .sometimesBy(.4, x=>x.delay(".5"))
64  .s("amencutup")
65  .slow(2)
66  .room(.5)
67  ,
68  // bass
69  sine.add(saw.slow(4)).range(0,7).segment(8)
70  .superimpose(x=>x.add(.1))
71  .scale('G0 minor').note()
72  .s("sawtooth").decay(.1).sustain(0)
73  .gain(.4).cutoff(perlin.range(300,3000).slow(8)).resonance(10)
74  .degradeBy("0 0.1 .5 .1")
75  .rarely(add(note("12")))
76  ,
77  // chord
78  note("Bb3,D4".superimpose(x=>x.add(.2)))
79  .s('sawtooth').cutoff(1000).struct("<~@3 [~ x]>")
80  .decay(.05).sustain(.0).delay(.8).delaytime(.125).room(.8)
81  ,
82  // alien
83  s("breath").room(1).shape(.6).chop(16).rev().mask("<x ~@7>")
84  ,
85  n("0 1").s("east").delay(.5).degradeBy(.8).speed(rand.range(.5,1.5))
86).reset("<x@7 x(5,8)>")`;
87      }
88    </script>
89  </body>
90</html>