Connor McCutcheon
/ Music
tidal.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>tidal.html</title>
  </head>
  <body style="margin: 0; padding: 0">
    <textarea id="code" style="width: 100%; height: 200px"></textarea>
    <pre id="result"></pre>
    <script src="https://unpkg.com/hs2js@0.0.8"></script>
    <script src="https://unpkg.com/@strudel/web@1.0.3"></script>
    <script>
      const { initStrudel } = strudel;
      const { run, parse, setBase, loadParser } = hs2js;
      setBase('https://unpkg.com/hs2js@0.0.4/dist/');
      const ready = loadParser();
      initStrudel({
        prebake: () => samples('github:tidalcycles/dirt-samples'),
      });
      const textarea = document.getElementById('code');
      if (window.location.hash) {
        textarea.value = atob(window.location.hash.slice(1));
      } else {
        textarea.value = 'd1 $ s "jvbass(3,8)"';
      }
      textarea.addEventListener('input', (e) => {
        window.location.hash = btoa(e.target.value);
        update();
      });
      update();
      function getInfixOperators() {
        let operators = {
          '>': 'set',
          '#': 'set',
          '+': 'add',
          '-': 'sub',
          '*': 'mul',
          '/': 'div',
        };
        let alignments = {
          in: (s) => '|' + s,
          out: (s) => s + '|',
          mix: (s) => '|' + s + '|',
        };
        let ops = {};
        Object.entries(operators).forEach(([o, name]) => {
          // operator without alignment
          ops[o] = (l, r) => reify(l)[name](reify(r));
          Object.entries(alignments).forEach(([a, getSymbol]) => {
            // get symbol with alignment
            let symbol = getSymbol(o);
            ops[symbol] = (l, r) => reify(l)[name][a](reify(r));
          });
        });
        ops['~>'] = (l, r) => reify(l).late(reify(r));
        ops['<~'] = (l, r) => reify(l).early(reify(r));
        ops['<$>'] = (l, r) => reify(r).fmap(l).outerJoin(); // is this right?
        return ops;
      }
      const ops = getInfixOperators();
      async function update() {
        let result, tree;
        await ready;
        try {
          tree = parse(textarea.value);
        } catch (err) {
          console.warn('parse error');
          console.error(err);
        }
        console.log('parsed tree');
        console.log(tree.rootNode.toString());
        try {
          let patterns = {};
          window.p = (name, pattern) => {
            patterns[name] = pattern;
          };
          window.d1 = (pat) => window.p(1, pat);
          window.d2 = (pat) => window.p(2, pat);
          window.d3 = (pat) => window.p(3, pat);
          window.rot = late;
          result = run(tree.rootNode, window, ops);
          if (Object.values(patterns).length) {
            stack(...Object.values(patterns)).play();
          }
        } catch (err) {
          console.warn('eval error');
          console.error(err);
          result = 'ERROR: ' + err.message;
        }
        document.getElementById('result').innerHTML = 'Result: ' + result;
      }
    </script>
  </body>
</html>
No comments yet.