1// this file contains a runtime scope for testing all the tunes 2// it mocks all the functions that won't work in node (who are not important for testing values / structure) 3// it might require mocking more stuff when tunes added that use other functions 4 5// 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'; 10// import gist from '@strudel/core/gist.js'; 11import { mini, m } from '@strudel/mini/mini.mjs'; 12// import * as voicingHelpers from '@strudel/tonal/voicings.mjs'; 13// import euclid from '@strudel/core/euclid.mjs'; 14//import '@strudel/midi/midi.mjs'; 15import * as tonalHelpers from '@strudel/tonal'; 16import * as edoHelpers from '@strudel/edo'; 17import '@strudel/xen/xen.mjs'; 18// import '@strudel/xen/tune.mjs'; 19// import '@strudel/core/euclid.mjs'; 20// import '@strudel/core/speak.mjs'; // window is not defined 21// import '@strudel/osc/osc.mjs'; 22// import '@strudel/webaudio/webaudio.mjs'; 23// import '@strudel/serial/serial.mjs'; 24import '../website/src/repl/piano'; 25//import * as motionHelpers from '../packages/motion/index.mjs'; 26//import * as geolocationHelpers from '../packages/geolocation/index.mjs'; 27import * as gamepadHelpers from '../packages/gamepad/index.mjs'; 28 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]) => {}; 142 143// 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); 182 183// 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}; 189 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}; 230 231// fixed: https://strudel.cc/?DBp75NUfSxIn (missing .note()) 232// bug: https://strudel.cc/?xHaKTd1kTpCn + https://strudel.cc/?o5LLePbx8kiQ