jevstrudel.git / test / runtime.mjs

this file contains a runtime scope for testing all the tunes it mocks all the functions that won't work in node (who are not important for testing values / structure) it might require mocking more stuff when tunes added that use other functions

import * as tunes from './tunes.mjs';

6import { evaluate } from '@strudel/transpiler';
7import { evalScope } from '@strudel/core';
8import * as strudel from '@strudel/core';
9import * as webaudio from '@strudel/webaudio';

import gist from '@strudel/core/gist.js';

11import { mini, m } from '@strudel/mini/mini.mjs';

import * as voicingHelpers from '@strudel/tonal/voicings.mjs'; import euclid from '@strudel/core/euclid.mjs'; import '@strudel/midi/midi.mjs';

15import * as tonalHelpers from '@strudel/tonal';
16import * as edoHelpers from '@strudel/edo';
17import '@strudel/xen/xen.mjs';

import '@strudel/xen/tune.mjs'; import '@strudel/core/euclid.mjs'; import '@strudel/core/speak.mjs'; // window is not defined import '@strudel/osc/osc.mjs'; import '@strudel/webaudio/webaudio.mjs'; import '@strudel/serial/serial.mjs';

24import '../website/src/repl/piano';

import * as motionHelpers from '../packages/motion/index.mjs'; import * as geolocationHelpers from '../packages/geolocation/index.mjs';

27import * as gamepadHelpers from '../packages/gamepad/index.mjs';
29class MockedNode {
30  chain() {
31    return this;
32  }
33  connect() {
34    return this;
35  }
36  toDestination() {
37    return this;
38  }
39  set() {
40    return this;
41  }
42  start() {
43    return this;
44  }
45}
46
47const mockNode = () => new MockedNode();
48
49const id = (x) => x;
50
51const toneHelpersMocked = {
52  FeedbackDelay: MockedNode,
53  MembraneSynth: MockedNode,
54  NoiseSynth: MockedNode,
55  MetalSynth: MockedNode,
56  Synth: MockedNode,
57  PolySynth: MockedNode,
58  Chorus: MockedNode,
59  Freeverb: MockedNode,
60  Gain: MockedNode,
61  Reverb: MockedNode,
62  vol: mockNode,
63  out: id,
64  osc: id,
65  samples: id,
66  adsr: id,
67  getDestination: id,
68  players: mockNode,
69  sampler: mockNode,
70  synth: mockNode,
71  piano: mockNode,
72  polysynth: mockNode,
73  fmsynth: mockNode,
74  membrane: mockNode,
75  noise: mockNode,
76  metal: mockNode,
77  lowpass: mockNode,
78  highpass: mockNode,
79};
80
81[
82  'osc',
83  'csound',
84  'tone',
85  'webdirt',
86  'pianoroll',
87  'speak',
88  'wave',
89  'filter',
90  'adsr',
91  'webaudio',
92  'soundfont',
93  'tune',
94  'midi',
95  '_scope',
96  '_spiral',
97  '_pitchwheel',
98  '_pianoroll',
99  '_spectrum',
100  'markcss',
101  'p',
102  'dough',
103].forEach((mock) => {
104  strudel.Pattern.prototype[mock] = function () {
105    return this;
106  };
107});
108
109const uiHelpersMocked = {
110  backgroundImage: id,
111};
112
113const canvasCtx = {
114  clearRect: () => {},
115  fillText: () => {},
116  fillRect: () => {},
117  canvas: {
118    width: 100,
119    height: 100,
120  },
121};
122const audioCtx = {
123  currentTime: 1,
124};
125const getDrawContext = () => canvasCtx;
126const getAudioContext = () => audioCtx;
127const loadSoundfont = () => {};
128const loadCsound = () => {};
129const loadCSound = () => {};
130const loadcsound = () => {};
131const getDuration = () => {};
132
133const midin = () => {
134  return (ccNum) => strudel.ref(() => 0); // returns ref with default value 0
135};
136
137const midikeys = async () => {
138  return () => strudel.silence;
139};
140
141const sysex = ([id, data]) => {};

TODO: refactor to evalScope

144evalScope(
145  // Tone,
146  strudel,
147  toneHelpersMocked,
148  uiHelpersMocked,
149  webaudio,
150  edoHelpers,
151  tonalHelpers,
152  gamepadHelpers,
153  /*
154  toneHelpers,
155  voicingHelpers,
156  drawHelpers,
157  uiHelpers,
158  */
159  {
160    midin,
161    midikeys,
162    sysex,
163    // gist,
164    // euclid,
165    csound: id,
166    loadOrc: id,
167    mini,
168    m,
169    getDrawContext,
170    getAudioContext,
171    loadSoundfont,
172    loadCSound,
173    loadCsound,
174    loadcsound,
175    getDuration,
176    setcps: id,
177    setcpm: id,
178    initDough: id,
179    Clock: {}, // whatever
180  },
181);

TBD: use transpiler to support labeled statements

184export const queryCode = async (code, cycles = 1) => {
185  const { pattern } = await evaluate(code);
186  const haps = pattern.sortHapsByPart().queryArc(0, cycles);
187  return haps.map((h) => h.show(true));
188};
190export const testCycles = {
191  timeCatMini: 16,
192  timeCat: 8,
193  shapeShifted: 16,
194  tetrisMini: 16,
195  whirlyStrudel: 16,
196  swimming: 51,
197  giantSteps: 20,
198  giantStepsReggae: 25,
199  transposedChordsHacked: 8,
200  scaleTranspose: 16,
201  struct: 4,
202  magicSofa: 8,
203  confusedPhone: 8,
204  zeldasRescue: 48,
205  technoDrums: 4,
206  caverave: 60,
207  callcenterhero: 22,
208  primalEnemy: 4,
209  synthDrums: 4,
210  sampleDrums: 4,
211  xylophoneCalling: 60,
212  sowhatelse: 60,
213  barryHarris: 64,
214  wavyKalimba: 64,
215  jemblung: 12,
216  risingEnemy: 12,
217  festivalOfFingers: 16,
218  festivalOfFingers2: 22,
219  undergroundPlumber: 20,
220  bridgeIsOver: 8,
221  goodTimes: 16,
222  echoPiano: 8,
223  sml1: 48,
224  speakerman: 48,
225  randomBells: 24,
226  waa: 16,
227  waar: 16,
228  festivalOfFingers3: 16,
229};

fixed: https://strudel.cc/?DBp75NUfSxIn (missing .note()) bug: https://strudel.cc/?xHaKTd1kTpCn + https://strudel.cc/?o5LLePbx8kiQ