mercury-engine 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mercury.js CHANGED
@@ -15195,7 +15195,7 @@ const LFO = function(_params){
15195
15195
  if (this._waveMap[w]){
15196
15196
  w = this._waveMap[w];
15197
15197
  } else {
15198
- console.log(`'${w} is not a valid waveshape`);
15198
+ Util.log(`'${w} is not a valid waveshape`);
15199
15199
  // default wave if wave does not exist
15200
15200
  w = 'sine';
15201
15201
  }
@@ -15244,7 +15244,7 @@ const Filter = function(_params){
15244
15244
  if (this._types[_params[0]]){
15245
15245
  this._fx.set({ type: this._types[_params[0]] });
15246
15246
  } else {
15247
- console.log(`'${_params[0]}' is not a valid filter type`);
15247
+ Util.log(`'${_params[0]}' is not a valid filter type`);
15248
15248
  this._fx.set({ type: 'lowpass' });
15249
15249
  }
15250
15250
  this._fx.set({ rolloff: -24 });
@@ -15318,7 +15318,7 @@ const TriggerFilter = function(_params){
15318
15318
  if (this._types[_params[0][0]]){
15319
15319
  this._fx.set({ type: this._types[_params[0][0]] });
15320
15320
  } else {
15321
- console.log(`'${_params[0][0]}' is not a valid filter type. Defaulting to lowpass`);
15321
+ Util.log(`'${_params[0][0]}' is not a valid filter type. Defaulting to lowpass`);
15322
15322
  this._fx.set({ type: 'lowpass' });
15323
15323
  }
15324
15324
 
@@ -15758,7 +15758,7 @@ class Instrument extends Sequencer {
15758
15758
  let tmpF = fxMap[f[0]](f.slice(1));
15759
15759
  this._fx.push(tmpF);
15760
15760
  } else {
15761
- log(`Effect ${f[0]} does not exist`);
15761
+ Util.log(`Effect ${f[0]} does not exist`);
15762
15762
  }
15763
15763
  });
15764
15764
  // if any fx working
@@ -15789,6 +15789,7 @@ module.exports = Instrument;
15789
15789
  },{"./Effects.js":56,"./Sequencer.js":65,"./Util.js":66,"tone":44}],58:[function(require,module,exports){
15790
15790
  const Tone = require('tone');
15791
15791
  const Instrument = require('./Instrument.js');
15792
+ const Util = require('./Util.js');
15792
15793
 
15793
15794
  class MonoInput extends Instrument {
15794
15795
  constructor(engine, d, canvas){
@@ -15799,7 +15800,7 @@ class MonoInput extends Instrument {
15799
15800
  } else if (d.match(/in(\d+)/g)){
15800
15801
  this._device = Number(d.match(/in(\d+)/)[1]);
15801
15802
  } else {
15802
- console.log(`${d} is not a valid microphone input. defaults to in0`);
15803
+ Util.log(`${d} is not a valid microphone input. defaults to in0`);
15803
15804
  this._device = 0;
15804
15805
  }
15805
15806
 
@@ -15812,9 +15813,9 @@ class MonoInput extends Instrument {
15812
15813
  createSource(){
15813
15814
  this.mic = new Tone.UserMedia().connect(this.channelStrip());
15814
15815
  this.mic.open(this._device).then(() => {
15815
- console.log(`Opened microphone: ${window.devices[this._device]}`);
15816
+ Util.log(`Opened microphone: ${window.devices[this._device]}`);
15816
15817
  }).catch((e) => {
15817
- console.log(`Unable to use microphone`);
15818
+ Util.log(`Unable to use microphone`);
15818
15819
  });
15819
15820
  this.mic.channelInterpretation = 'discrete';
15820
15821
 
@@ -15837,11 +15838,11 @@ class MonoInput extends Instrument {
15837
15838
  }
15838
15839
  }
15839
15840
  module.exports = MonoInput;
15840
- },{"./Instrument.js":57,"tone":44}],59:[function(require,module,exports){
15841
+ },{"./Instrument.js":57,"./Util.js":66,"tone":44}],59:[function(require,module,exports){
15841
15842
  const Tone = require('tone');
15842
15843
  const Util = require('./Util.js');
15843
15844
  const Sequencer = require('./Sequencer.js');
15844
- const WebMidi = require("webmidi");
15845
+ const { WebMidi } = require("webmidi");
15845
15846
 
15846
15847
  class MonoMidi extends Sequencer {
15847
15848
  constructor(engine, d='default', canvas){
@@ -15852,7 +15853,7 @@ class MonoMidi extends Sequencer {
15852
15853
  if (d === 'default'){
15853
15854
  this._device = WebMidi.outputs[0];
15854
15855
  } else if (!this._device){
15855
- console.log(`${d} is not a valid MIDI Device name, set to default`);
15856
+ Util.log(`${d} is not a valid MIDI Device name, set to default`);
15856
15857
  this._device = WebMidi.outputs[0];
15857
15858
  }
15858
15859
 
@@ -15919,8 +15920,8 @@ class MonoMidi extends Sequencer {
15919
15920
  n[x] = Util.toMidi(i[x], o);
15920
15921
  }
15921
15922
 
15922
- // play the note(s)!
15923
- this._device.playNote(n, ch, { duration: d, velocity: g, time: sync });
15923
+ // play the note(s)! updated for webmidi 3.x
15924
+ this._device.playNote(n, ch, { duration: d, attack: g, time: sync });
15924
15925
 
15925
15926
  // }
15926
15927
  }
@@ -15959,7 +15960,7 @@ class MonoMidi extends Sequencer {
15959
15960
  this._cc = [];
15960
15961
  cc.forEach((c) => {
15961
15962
  if (isNaN(c[0])){
15962
- console.log(`'${c[0]}' is not a valid CC number`);
15963
+ Util.log(`'${c[0]}' is not a valid CC number`);
15963
15964
  } else {
15964
15965
  let cc = [];
15965
15966
  cc[0] = c[0];
@@ -16084,7 +16085,7 @@ class MonoSample extends Instrument {
16084
16085
  // error if soundfile does not exist
16085
16086
  else if (!this._bufs.has(s)){
16086
16087
  // set default (or an ampty soundfile?)
16087
- console.log(`sample ${s} not found`);
16088
+ Util.log(`sample ${s} not found`);
16088
16089
  return 'kick_909';
16089
16090
  }
16090
16091
  return s;
@@ -16191,7 +16192,7 @@ class MonoSynth extends Instrument {
16191
16192
  if (this._waveMap[w]){
16192
16193
  w = this._waveMap[w];
16193
16194
  } else {
16194
- console.log(`${w} is not a valid waveshape`);
16195
+ Util.log(`${w} is not a valid waveshape`);
16195
16196
  // default wave if wave does not exist
16196
16197
  w = 'sine';
16197
16198
  }
@@ -16387,7 +16388,7 @@ class PolyInstrument extends Instrument {
16387
16388
  }
16388
16389
 
16389
16390
  voices(v){
16390
- console.log(`Changing voice amount is not yet supported. You can use voice-stealing with steal(on)`);
16391
+ Util.log(`Changing voice amount is not yet supported. You can use voice-stealing with steal(on)`);
16391
16392
  // TODO change voice amount
16392
16393
  // set the voiceamount for the polyphonic synth
16393
16394
  // this.numVoices = Math.max(1, isNaN(Number(v))? 6 : Number(v));
@@ -16402,7 +16403,7 @@ class PolyInstrument extends Instrument {
16402
16403
  } else if (s === 'off' || s == 0){
16403
16404
  this._steal = false;
16404
16405
  } else {
16405
- console.log(`${s} is not a valid argument for steal()`);
16406
+ Util.log(`${s} is not a valid argument for steal()`);
16406
16407
  }
16407
16408
  }
16408
16409
 
@@ -16543,7 +16544,7 @@ class PolySample extends PolyInstrument {
16543
16544
  // error if soundfile does not exist
16544
16545
  else if (!this._bufs.has(s)){
16545
16546
  // set default (or an ampty soundfile?)
16546
- console.log(`sample ${s} not found`);
16547
+ Util.log(`sample ${s} not found`);
16547
16548
  return 'kick_909';
16548
16549
  }
16549
16550
  return s;
@@ -16960,7 +16961,7 @@ function getOSC(a){
16960
16961
  return a;
16961
16962
  } else if (osc.match(/^\/[^`'"\s]+/g)){
16962
16963
  if (!window.oscMessages[osc]){
16963
- console.log(`No message received on address ${osc}`);
16964
+ log(`No message received on address ${osc}`);
16964
16965
  return [0];
16965
16966
  }
16966
16967
  return window.oscMessages[osc];
@@ -16993,7 +16994,7 @@ function evalExpr(a){
16993
16994
  try {
16994
16995
  result = eval(expr);
16995
16996
  } catch (e){
16996
- console.log(`Unable to evaluate expression: ${expr}`);
16997
+ log(`Unable to evaluate expression: ${expr}`);
16997
16998
  }
16998
16999
  return result;
16999
17000
  }
@@ -17018,8 +17019,7 @@ function formatRatio(d, bpm){
17018
17019
  } else if (!isNaN(Number(d))){
17019
17020
  return Number(d) * 4.0 * 60 / bpm;
17020
17021
  } else {
17021
- // print(`${d} is not a valid time value`);
17022
- console.log(`${d} is not a valid time value`);
17022
+ log(`${d} is not a valid time value`);
17023
17023
  return 60 / bpm;
17024
17024
  }
17025
17025
  }
@@ -17031,7 +17031,7 @@ function divToS(d, bpm){
17031
17031
  } else if (!isNaN(Number(d))){
17032
17032
  return Number(d) / 1000;
17033
17033
  } else {
17034
- console.log(`${d} is not a valid time value`);
17034
+ log(`${d} is not a valid time value`);
17035
17035
  return 0.1;
17036
17036
  }
17037
17037
  }
@@ -17041,7 +17041,7 @@ function noteToFreq(i, o){
17041
17041
  if (isNaN(i)){
17042
17042
  let _i = noteToMidi(i);
17043
17043
  if (!_i){
17044
- console.log(`${i} is not a valid number or name`);
17044
+ log(`${i} is not a valid number or name`);
17045
17045
  i = 0;
17046
17046
  } else {
17047
17047
  i = _i - 48;
@@ -17072,7 +17072,7 @@ function assureWave(w){
17072
17072
  if (waveMap[w]){
17073
17073
  w = waveMap[w];
17074
17074
  } else {
17075
- console.log(`${w} is not a valid waveshape`);
17075
+ log(`${w} is not a valid waveshape`);
17076
17076
  // default wave if wave does not exist
17077
17077
  w = 'sine';
17078
17078
  }
@@ -17084,7 +17084,7 @@ function toMidi(n=0, o=0){
17084
17084
  if (isNaN(n)){
17085
17085
  let _n = noteToMidi(n);
17086
17086
  if (!_n){
17087
- console.log(`${n} is not a valid number or name`);
17087
+ log(`${n} is not a valid number or name`);
17088
17088
  n = 0;
17089
17089
  } else {
17090
17090
  n = _n - 36;
@@ -17093,7 +17093,18 @@ function toMidi(n=0, o=0){
17093
17093
  return toScale(n + o * 12 + 36);
17094
17094
  }
17095
17095
 
17096
- module.exports = { clip, assureNum, lookup, randLookup, isRandom, getParam, toArray, msToS, formatRatio, divToS, toMidi, mtof, noteToMidi, noteToFreq, assureWave }
17096
+ // the log message is used to log to the console but also
17097
+ // sends a custom event that can be listened for to print the
17098
+ // content at some other place in the window, for example using a div
17099
+ function log(msg){
17100
+ console.log(msg);
17101
+ if (window){
17102
+ let print = new CustomEvent('mercuryLog', { detail: msg });
17103
+ window.dispatchEvent(print);
17104
+ }
17105
+ }
17106
+
17107
+ module.exports = { clip, assureNum, lookup, randLookup, isRandom, getParam, toArray, msToS, formatRatio, divToS, toMidi, mtof, noteToMidi, noteToFreq, assureWave, log }
17097
17108
  },{"total-serialism":47}],67:[function(require,module,exports){
17098
17109
  module.exports={
17099
17110
  "uptempo" : 10,
@@ -17120,7 +17131,7 @@ module.exports={
17120
17131
  const Tone = require('tone');
17121
17132
  const Mercury = require('mercury-lang');
17122
17133
  const TL = require('total-serialism').Translate;
17123
- // const Util = require('total-serialism').Utility;
17134
+ const { normalize, multiply } = require('total-serialism').Utility;
17124
17135
 
17125
17136
  const MonoSample = require('./core/MonoSample.js');
17126
17137
  const MonoMidi = require('./core/MonoMidi.js');
@@ -17129,11 +17140,12 @@ const MonoInput = require('./core/MonoInput.js');
17129
17140
  const PolySynth = require('./core/PolySynth.js');
17130
17141
  const PolySample = require('./core/PolySample.js');
17131
17142
  const Tempos = require('./data/genre-tempos.json');
17143
+ const Util = require('./core/Util.js');
17132
17144
 
17133
17145
  class MercuryInterpreter {
17134
- constructor(){
17146
+ constructor({ hydra, p5canvas } = {}){
17135
17147
  // cross-fade time
17136
- this.crossFade = 0.5;
17148
+ this.crossFade;
17137
17149
 
17138
17150
  // arrays with the current and previous instruments for crossfade
17139
17151
  this._sounds = [];
@@ -17146,6 +17158,10 @@ class MercuryInterpreter {
17146
17158
  this.parse;
17147
17159
  this.tree;
17148
17160
  this.errors;
17161
+
17162
+ // Hydra and P5 canvas
17163
+ this.canvas = hydra;
17164
+ this.p5canvas = p5canvas;
17149
17165
  }
17150
17166
 
17151
17167
  getSounds(){
@@ -17169,32 +17185,51 @@ class MercuryInterpreter {
17169
17185
  startSounds(s, f=0){
17170
17186
  // fade in new sounds
17171
17187
  s.map((_s) => {
17172
- _s.fadeIn(f);
17188
+ if (_s){ _s.fadeIn(f); }
17173
17189
  });
17174
17190
  }
17175
17191
 
17176
17192
  removeSounds(s, f=0) {
17177
17193
  // fade out and delete after fade
17178
17194
  s.map((_s) => {
17179
- _s.fadeOut(f);
17195
+ if (_s){ _s.fadeOut(f); }
17180
17196
  });
17181
17197
  // empty array to trigger garbage collection
17182
17198
  s.length = 0;
17183
17199
  }
17184
17200
 
17185
- code({ file='', canvas, p5canvas } = {}){
17201
+ makeLoops(s){
17202
+ // make the loops for all the instruments
17203
+ s.map((_s) => {
17204
+ if (_s){ _s.makeLoop(); }
17205
+ });
17206
+ }
17207
+
17208
+ setCrossFade(f){
17209
+ // set the crossFade in milliseconds
17210
+ this.crossFade = Number(f) / 1000;
17211
+ Util.log(`Crossfade set to: ${f}ms`);
17212
+ }
17213
+
17214
+ getCode(){
17215
+ // return the last evaluated code
17216
+ return this._code;
17217
+ }
17218
+
17219
+ code(file=''){
17186
17220
  // parse and evaluate the inputted code
17187
- // as an asyncronous function with promise
17188
17221
  let c = (!file)? this._code : file;
17189
- this._code = c;
17190
-
17222
+
17191
17223
  let t = Tone.Transport.seconds;
17224
+
17192
17225
  // is this necessary?
17226
+ // as an asyncronous function with promise
17193
17227
  // let parser = new Promise((resolve) => {
17194
17228
  // return resolve(Mercury(c));
17195
17229
  // });
17196
17230
  // this.parse = await parser;
17197
17231
  this.parse = Mercury(c);
17232
+
17198
17233
  console.log(`Evaluated code in: ${((Tone.Transport.seconds-t) * 1000).toFixed(3)}ms`);
17199
17234
 
17200
17235
  this.tree = this.parse.parseTree;
@@ -17204,31 +17239,21 @@ class MercuryInterpreter {
17204
17239
  // l.innerHTML = '';
17205
17240
  // handle .print and .errors
17206
17241
  this.errors.forEach((e) => {
17207
- console.log(e);
17208
- // log(e);
17242
+ Util.log(e);
17209
17243
  });
17210
17244
  if (this.errors.length > 0){
17211
17245
  // return if the code contains any syntax errors
17212
- console.log(`Could not run because of syntax error`);
17213
- console.log(`Please see Help for more information`);
17246
+ Util.log(`Could not run because of syntax error`);
17247
+ Util.log(`Please see Help for more information`);
17214
17248
  return;
17215
17249
  }
17250
+ // if no errors the last evaluated code is stored
17251
+ this._code = c;
17216
17252
 
17217
17253
  this.tree.print.forEach((p) => {
17218
- console.log(p);
17254
+ Util.log(p);
17219
17255
  });
17220
17256
 
17221
- // hide canvas and noLoop
17222
- // p5canvas.hide();
17223
-
17224
- // handle .display to p5
17225
- // tree.display.forEach((p) => {
17226
- // // restart canvas if view is used
17227
- // let n = Util.mul(Util.normalize(p), 255);
17228
- // p5canvas.sketch.fillCanvas(n);
17229
- // p5canvas.display();
17230
- // });
17231
-
17232
17257
  // set timer to check evaluation time
17233
17258
  t = Tone.Transport.seconds;
17234
17259
 
@@ -17236,21 +17261,19 @@ class MercuryInterpreter {
17236
17261
  const globalMap = {
17237
17262
  'crossFade' : (args) => {
17238
17263
  // set crossFade time in ms
17239
- this.crossFade = Number(args[0]) / 1000;
17240
- // log(`crossfade time is ${args[0]}ms`);
17241
- console.log(`Crossfade: ${args[0]}ms`);
17264
+ this.setCrossFade(args[0]);
17242
17265
  },
17243
17266
  'tempo' : (args) => {
17244
17267
  let t = args[0];
17245
17268
  if (isNaN(t)){
17246
17269
  t = Tempos[args[0].toLowerCase()];
17247
17270
  if (t === undefined){
17248
- console.log(`tempo ${args[0]} is not a valid genre or number`);
17271
+ Util.log(`tempo ${args[0]} is not a valid genre or number`);
17249
17272
  return;
17250
17273
  }
17251
17274
  args[0] = t;
17252
17275
  }
17253
- this.bpm(...args);
17276
+ this.setBPM(...args);
17254
17277
  // engine.setBPM(...args);
17255
17278
  // log(`set bpm to ${bpm}`);
17256
17279
  },
@@ -17275,16 +17298,15 @@ class MercuryInterpreter {
17275
17298
  if (s.indexOf(scl) > -1){
17276
17299
  TL.setScale(scl);
17277
17300
  } else {
17278
- console.log(`${scl} is not a valid scale`);
17301
+ Util.log(`${scl} is not a valid scale`);
17279
17302
  }
17280
17303
  if (rt){
17281
17304
  TL.setRoot(rt);
17282
17305
  }
17283
-
17284
- let tmpS = TL.getScale().scale;
17285
- let tmpR = TL.getScale().root;
17306
+ // let tmpS = TL.getScale().scale;
17307
+ // let tmpR = TL.getScale().root;
17286
17308
  // document.getElementById('scale').innerHTML = `scale = ${tmpR} ${tmpS}`;
17287
- // log(`set scale to ${tmpR} ${tmpS}`);
17309
+ // Util.log(`set scale to ${tmpR} ${tmpS}`);
17288
17310
  },
17289
17311
  'amp' : (args) => {
17290
17312
  this.setVolume(...args);
@@ -17303,38 +17325,42 @@ class MercuryInterpreter {
17303
17325
  // Handling all the different instrument types here
17304
17326
  const objectMap = {
17305
17327
  'sample' : (obj) => {
17306
- let inst = new MonoSample(this, obj.type, canvas);
17328
+ let inst = new MonoSample(this, obj.type, this.canvas);
17307
17329
  objectMap.applyFunctions(obj.functions, inst, obj.type);
17308
17330
  return inst;
17309
17331
  },
17310
17332
  'loop' : (obj) => {
17311
- let inst = new MonoSample(this, obj.type, canvas);
17333
+ let inst = new MonoSample(this, obj.type, this.canvas);
17312
17334
  objectMap.applyFunctions(obj.functions, inst, obj.type);
17313
17335
  return inst;
17314
17336
  },
17315
17337
  'synth' : (obj) => {
17316
17338
  console.log(obj);
17317
- let inst = new MonoSynth(this, obj.type, canvas);
17339
+ let inst = new MonoSynth(this, obj.type, this.canvas);
17318
17340
  objectMap.applyFunctions(obj.functions, inst, obj.type);
17319
17341
  return inst;
17320
17342
  },
17321
17343
  'polySynth' : (obj) => {
17322
- let inst = new PolySynth(this, obj.type, canvas);
17344
+ let inst = new PolySynth(this, obj.type, this.canvas);
17323
17345
  objectMap.applyFunctions(obj.functions, inst, obj.type);
17324
17346
  return inst;
17325
17347
  },
17326
17348
  'polySample' : (obj) => {
17327
- let inst = new PolySample(this, obj.type, canvas);
17349
+ let inst = new PolySample(this, obj.type, this.canvas);
17328
17350
  objectMap.applyFunctions(obj.functions, inst, obj.type);
17329
17351
  return inst;
17330
17352
  },
17331
17353
  'midi' : (obj) => {
17332
- let inst = new MonoMidi(this, obj.type, canvas);
17354
+ if (!this.midi.enabled){
17355
+ Util.log(`WebMIDI is not started. Please load the package and check your browser compatibility`);
17356
+ return null;
17357
+ }
17358
+ let inst = new MonoMidi(this, obj.type, this.canvas);
17333
17359
  objectMap.applyFunctions(obj.functions, inst, obj.type);
17334
17360
  return inst;
17335
17361
  },
17336
17362
  'input' : (obj) => {
17337
- let inst = new MonoInput(this, obj.type, canvas);
17363
+ let inst = new MonoInput(this, obj.type, this.canvas);
17338
17364
  objectMap.applyFunctions(obj.functions, inst, obj.type);
17339
17365
  return inst;
17340
17366
  },
@@ -17369,18 +17395,15 @@ class MercuryInterpreter {
17369
17395
  if (objectMap[type]){
17370
17396
  this.sounds.push(objectMap[type](this.tree.objects[o]));
17371
17397
  } else {
17372
- log(`Instrument named '${type}' is not supported`);
17398
+ Util.log(`Instrument named '${type}' is not supported`);
17373
17399
  }
17374
17400
  }
17375
17401
 
17376
17402
  // start new loops;
17377
- this.sounds.map((s) => {
17378
- s.makeLoop();
17379
- });
17380
-
17381
- console.log(`Instruments added in: ${((Tone.Transport.seconds - t) * 1000).toFixed(3)}ms`);
17382
-
17403
+ this.makeLoops(this.sounds);
17383
17404
  this.transferCounts(this._sounds, this.sounds);
17405
+
17406
+ console.log(`Instruments added in: ${((Tone.Transport.seconds - t) * 1000).toFixed(3)}ms`);
17384
17407
 
17385
17408
  // when all loops started fade in the new sounds and fade out old
17386
17409
  if (!this.sounds.length){
@@ -17390,22 +17413,39 @@ class MercuryInterpreter {
17390
17413
  this.removeSounds(this._sounds, this.crossFade);
17391
17414
 
17392
17415
  this.resume();
17416
+
17417
+ // if p5js canvas is included in the html page
17418
+ if (this.p5canvas){
17419
+ // hide canvas and noLoop
17420
+ this.p5canvas.hide();
17421
+
17422
+ // handle .display to p5
17423
+ tree.display.forEach((p) => {
17424
+ // restart canvas if view is used
17425
+ let n = multiply(normalize(p), 255);
17426
+ this.p5canvas.sketch.fillCanvas(n);
17427
+ this.p5canvas.display();
17428
+ });
17429
+ }
17393
17430
  }
17394
17431
  }
17395
17432
  module.exports = { MercuryInterpreter }
17396
- },{"./core/MonoInput.js":58,"./core/MonoMidi.js":59,"./core/MonoSample.js":60,"./core/MonoSynth.js":61,"./core/PolySample.js":63,"./core/PolySynth.js":64,"./data/genre-tempos.json":67,"mercury-lang":27,"tone":44,"total-serialism":47}],69:[function(require,module,exports){
17433
+ },{"./core/MonoInput.js":58,"./core/MonoMidi.js":59,"./core/MonoSample.js":60,"./core/MonoSynth.js":61,"./core/PolySample.js":63,"./core/PolySynth.js":64,"./core/Util.js":66,"./data/genre-tempos.json":67,"mercury-lang":27,"tone":44,"total-serialism":47}],69:[function(require,module,exports){
17397
17434
 
17398
17435
  console.log(`
17399
17436
  Mercury Engine by Timo Hoogland (c) 2023
17400
17437
  more info:
17401
17438
  https://www.timohoogland.com
17402
17439
  https://mercury.timohoogland.com
17403
- https://github.com/tmhglnd/mercury
17440
+ https://github.com/tmhglnd/mercury-playground
17441
+ https://github.com/tmhglnd/mercury-engine
17404
17442
 
17405
17443
  `);
17406
17444
 
17407
17445
  const Tone = require('tone');
17446
+ const Util = require('./core/Util.js');
17408
17447
  const { MercuryInterpreter } = require('./interpreter');
17448
+ const { WebMidi } = require("webmidi");
17409
17449
 
17410
17450
  // load extra AudioWorkletProcessors from file
17411
17451
  // transformed to inline with browserify brfs
@@ -17413,15 +17453,15 @@ const { MercuryInterpreter } = require('./interpreter');
17413
17453
  const fxExtensions = "\n// A white noise generator at -6dBFS to test AudioWorkletProcessor\n//\nclass NoiseProcessor extends AudioWorkletProcessor {\n\tprocess(inputs, outputs, parameters){\n\t\tconst output = outputs[0];\n\n\t\toutput.forEach((channel) => {\n\t\t\tfor (let i=0; i<channel.length; i++) {\n\t\t\t\tchannel[i] = Math.random() - 0.5;\n\t\t\t}\n\t\t});\n\t\treturn true;\n\t}\n}\nregisterProcessor('noise-processor', NoiseProcessor);\n\n// A Downsampling Chiptune effect. Downsamples the signal by a specified amount\n// Resulting in a lower samplerate, making it sound more like 8bit/chiptune\n// Programmed with a custom AudioWorkletProcessor, see effects/Processors.js\n//\nclass DownSampleProcessor extends AudioWorkletProcessor {\n\tstatic get parameterDescriptors() {\n\t\treturn [{\n\t\t\tname: 'down',\n\t\t\tdefaultValue: 8,\n\t\t\tminValue: 1,\n\t\t\tmaxValue: 2048\n\t\t}];\n\t}\n\n\tconstructor(){\n\t\tsuper();\n\t\t// the frame counter\n\t\tthis.count = 0;\n\t\t// sample and hold variable array\n\t\tthis.sah = [];\n\t}\n\n\tprocess(inputs, outputs, parameters){\n\t\tconst input = inputs[0];\n\t\tconst output = outputs[0];\n\n\t\t// if there is anything to process\n\t\tif (input.length > 0){\n\t\t\t// for the length of the sample array (generally 128)\n\t\t\tfor (let i=0; i<input[0].length; i++){\n\t\t\t\tconst d = (parameters.down.length > 1) ? parameters.down[i] : parameters.down[0];\n\t\t\t\t// for every channel\n\t\t\t\tfor (let channel=0; channel<input.length; ++channel){\n\t\t\t\t\t// if counter equals 0, sample and hold\n\t\t\t\t\tif (this.count % d === 0){\n\t\t\t\t\t\tthis.sah[channel] = input[channel][i];\n\t\t\t\t\t}\n\t\t\t\t\t// output the currently held sample\n\t\t\t\t\toutput[channel][i] = this.sah[channel];\n\t\t\t\t}\n\t\t\t\t// increment sample counter\n\t\t\t\tthis.count++;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\nregisterProcessor('downsampler-processor', DownSampleProcessor);\n\n// A distortion algorithm using the tanh (hyperbolic-tangent) as a \n// waveshaping technique. Some mapping to apply a more equal loudness \n// distortion is applied on the overdrive parameter\n//\nclass TanhDistortionProcessor extends AudioWorkletProcessor {\n\tconstructor(){\n\t\tsuper();\n\t}\n\n\tprocess(inputs, outputs, parameters){\n\t\tconst input = inputs[0];\n\t\tconst output = outputs[0];\n\n\t\tif (input.length > 0){\n\t\t\tfor (let channel=0; channel<input.length; ++channel){\n\t\t\t\tfor (let i=0; i<input[channel].length; i++){\n\t\t\t\t\t// simple waveshaping with tanh\n\t\t\t\t\toutput[channel][i] = Math.tanh(input[channel][i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\nregisterProcessor('tanh-distortion-processor', TanhDistortionProcessor);\n\n// A distortion/compression effect of an incoming signal\n// Based on an algorithm by Peter McCulloch\n// \nclass SquashProcessor extends AudioWorkletProcessor {\n\tstatic get parameterDescriptors(){\n\t\treturn [{\n\t\t\tname: 'amount',\n\t\t\tdefaultValue: 4,\n\t\t\tminValue: 1,\n\t\t\tmaxValue: 1024\n\t\t}];\n\t}\n\n\tconstructor(){\n\t\tsuper();\n\t}\n\n\tprocess(inputs, outputs, parameters){\n\t\tconst input = inputs[0];\n\t\tconst output = outputs[0];\n\t\t\n\t\tif (input.length > 0){\n\t\t\tfor (let channel=0; channel<input.length; ++channel){\n\t\t\t\tfor (let i=0; i<input[channel].length; i++){\n\t\t\t\t\t// (s * a) / ((s * a)^2 * 0.28 + 1) / √a\n\t\t\t\t\t// drive amount, minimum of 1\n\t\t\t\t\tconst a = (parameters.amount.length > 1)? parameters.amount[i] : parameters.amount[0];\n\t\t\t\t\t// set the waveshaper effect\n\t\t\t\t\tconst s = input[channel][i];\n\t\t\t\t\tconst p = (s * a) / ((s * a) * (s * a) * 0.28 + 1.0);\n\t\t\t\t\toutput[channel][i] = p;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\nregisterProcessor('squash-processor', SquashProcessor);";
17414
17454
  Tone.getContext().addAudioWorkletModule(URL.createObjectURL(new Blob([ fxExtensions ], { type: 'text/javascript' })));
17415
17455
 
17416
- // const minifyInline = require('minify-inline-json');
17417
-
17418
17456
  // Mercury main class controls Tone and loads samples
17419
17457
  // also has the interpreter evaluating the code and adding the instruments
17420
17458
  //
17421
17459
  class Mercury extends MercuryInterpreter {
17422
- constructor(callback){
17423
- // initalize the constructor of inheriting class
17424
- super();
17460
+ constructor({ onload, onmidi, hydra, p5canvas } = {}){
17461
+ // initalize the constructor of inheriting class with
17462
+ // optionally a hydra and p5 canvas
17463
+ super({ hydra, p5canvas });
17464
+
17425
17465
  // store sample files in buffers
17426
17466
  this.samples = JSON.parse("{\n \"noise_a\": \"noise/noise_a.wav\",\n \"drone_cymbal\": \"ambient/cymbal/drone_cymbal.wav\",\n \"drone_cymbal_01\": \"ambient/cymbal/drone_cymbal_01.wav\",\n \"clap_808\": \"drums/clap/clap_808.wav\",\n \"clap_808_short\": \"drums/clap/clap_808_short.wav\",\n \"clap_909\": \"drums/clap/clap_909.wav\",\n \"clap_min\": \"drums/clap/clap_min.wav\",\n \"hat_808\": \"drums/hat/hat_808.wav\",\n \"hat_808_open\": \"drums/hat/hat_808_open.wav\",\n \"hat_808_semi\": \"drums/hat/hat_808_semi.wav\",\n \"hat_909\": \"drums/hat/hat_909.wav\",\n \"hat_909_open\": \"drums/hat/hat_909_open.wav\",\n \"hat_909_open_short\": \"drums/hat/hat_909_open_short.wav\",\n \"hat_909_short\": \"drums/hat/hat_909_short.wav\",\n \"hat_click\": \"drums/hat/hat_click.wav\",\n \"hat_dub\": \"drums/hat/hat_dub.wav\",\n \"hat_min\": \"drums/hat/hat_min.wav\",\n \"hat_min_open\": \"drums/hat/hat_min_open.wav\",\n \"kick_808\": \"drums/kick/kick_808.wav\",\n \"kick_808_dist\": \"drums/kick/kick_808_dist.wav\",\n \"kick_909\": \"drums/kick/kick_909.wav\",\n \"kick_909_dist\": \"drums/kick/kick_909_dist.wav\",\n \"kick_909_dist_long\": \"drums/kick/kick_909_dist_long.wav\",\n \"kick_909_long\": \"drums/kick/kick_909_long.wav\",\n \"kick_deep\": \"drums/kick/kick_deep.wav\",\n \"kick_dub\": \"drums/kick/kick_dub.wav\",\n \"kick_house\": \"drums/kick/kick_house.wav\",\n \"kick_min\": \"drums/kick/kick_min.wav\",\n \"kick_sub\": \"drums/kick/kick_sub.wav\",\n \"kick_ua\": \"drums/kick/kick_ua.wav\",\n \"kick_vintage\": \"drums/kick/kick_vintage.wav\",\n \"block\": \"drums/perc/block.wav\",\n \"block_lo\": \"drums/perc/block_lo.wav\",\n \"bongo\": \"drums/perc/bongo.wav\",\n \"bongo_lo\": \"drums/perc/bongo_lo.wav\",\n \"clave_808\": \"drums/perc/clave_808.wav\",\n \"cowbell_808\": \"drums/perc/cowbell_808.wav\",\n \"cymbal_808\": \"drums/perc/cymbal_808.wav\",\n \"maracas_808\": \"drums/perc/maracas_808.wav\",\n \"snare_808\": \"drums/snare/snare_808.wav\",\n \"snare_909\": \"drums/snare/snare_909.wav\",\n \"snare_909_short\": \"drums/snare/snare_909_short.wav\",\n \"snare_ac\": \"drums/snare/snare_ac.wav\",\n \"snare_dnb\": \"drums/snare/snare_dnb.wav\",\n \"snare_dub\": \"drums/snare/snare_dub.wav\",\n \"snare_fat\": \"drums/snare/snare_fat.wav\",\n \"snare_hvy\": \"drums/snare/snare_hvy.wav\",\n \"snare_min\": \"drums/snare/snare_min.wav\",\n \"snare_rock\": \"drums/snare/snare_rock.wav\",\n \"snare_step\": \"drums/snare/snare_step.wav\",\n \"tabla_01\": \"drums/tabla/tabla_01.wav\",\n \"tabla_02\": \"drums/tabla/tabla_02.wav\",\n \"tabla_03\": \"drums/tabla/tabla_03.wav\",\n \"tabla_hi\": \"drums/tabla/tabla_hi.wav\",\n \"tabla_hi_long\": \"drums/tabla/tabla_hi_long.wav\",\n \"tabla_hi_short\": \"drums/tabla/tabla_hi_short.wav\",\n \"tabla_lo\": \"drums/tabla/tabla_lo.wav\",\n \"tabla_lo_long\": \"drums/tabla/tabla_lo_long.wav\",\n \"tabla_lo_short\": \"drums/tabla/tabla_lo_short.wav\",\n \"tabla_mid\": \"drums/tabla/tabla_mid.wav\",\n \"tabla_mid_long\": \"drums/tabla/tabla_mid_long.wav\",\n \"tabla_mid_short\": \"drums/tabla/tabla_mid_short.wav\",\n \"tom_808\": \"drums/tom/tom_808.wav\",\n \"tom_hi\": \"drums/tom/tom_hi.wav\",\n \"tom_lo\": \"drums/tom/tom_lo.wav\",\n \"tom_mid\": \"drums/tom/tom_mid.wav\",\n \"tongue\": \"foley/body/tongue.wav\",\n \"tongue_lo\": \"foley/body/tongue_lo.wav\",\n \"shatter\": \"foley/glass/shatter.wav\",\n \"metal\": \"foley/metal/metal.wav\",\n \"metal_lo\": \"foley/metal/metal_lo.wav\",\n \"wobble\": \"foley/plastic/wobble.wav\",\n \"wobble_02\": \"foley/plastic/wobble_02.wav\",\n \"door\": \"foley/wood/door.wav\",\n \"scrape\": \"foley/wood/scrape.wav\",\n \"scrape_01\": \"foley/wood/scrape_01.wav\",\n \"wood_hit\": \"foley/wood/wood_hit.wav\",\n \"wood_metal\": \"foley/wood/wood_metal.wav\",\n \"wood_plate\": \"foley/wood/wood_plate.wav\",\n \"bell\": \"idiophone/bell/bell.wav\",\n \"chimes\": \"idiophone/chimes/chimes.wav\",\n \"chimes_chord\": \"idiophone/chimes/chimes_chord.wav\",\n \"chimes_chord_01\": \"idiophone/chimes/chimes_chord_01.wav\",\n \"chimes_chord_02\": \"idiophone/chimes/chimes_chord_02.wav\",\n \"chimes_hi\": \"idiophone/chimes/chimes_hi.wav\",\n \"gong_hi\": \"idiophone/gong/gong_hi.wav\",\n \"gong_lo\": \"idiophone/gong/gong_lo.wav\",\n \"kalimba_a\": \"idiophone/kalimba/kalimba_a.wav\",\n \"kalimba_ab\": \"idiophone/kalimba/kalimba_ab.wav\",\n \"kalimba_cis\": \"idiophone/kalimba/kalimba_cis.wav\",\n \"kalimba_e\": \"idiophone/kalimba/kalimba_e.wav\",\n \"kalimba_g\": \"idiophone/kalimba/kalimba_g.wav\",\n \"bamboo_a\": \"idiophone/marimba-bamboo/bamboo_a.wav\",\n \"bamboo_c\": \"idiophone/marimba-bamboo/bamboo_c.wav\",\n \"bamboo_f\": \"idiophone/marimba-bamboo/bamboo_f.wav\",\n \"bamboo_g\": \"idiophone/marimba-bamboo/bamboo_g.wav\",\n \"bowl_hi\": \"idiophone/singing-bowl/bowl_hi.wav\",\n \"bowl_lo\": \"idiophone/singing-bowl/bowl_lo.wav\",\n \"bowl_mid\": \"idiophone/singing-bowl/bowl_mid.wav\",\n \"rhodes_8bit\": \"keys/pad/rhodes_8bit.wav\",\n \"piano_a\": \"keys/piano/piano_a.wav\",\n \"piano_b\": \"keys/piano/piano_b.wav\",\n \"piano_c\": \"keys/piano/piano_c.wav\",\n \"piano_d\": \"keys/piano/piano_d.wav\",\n \"piano_e\": \"keys/piano/piano_e.wav\",\n \"piano_f\": \"keys/piano/piano_f.wav\",\n \"piano_g\": \"keys/piano/piano_g.wav\",\n \"amen\": \"loops/breaks/amen.wav\",\n \"amen_alt\": \"loops/breaks/amen_alt.wav\",\n \"amen_break\": \"loops/breaks/amen_break.wav\",\n \"amen_fill\": \"loops/breaks/amen_fill.wav\",\n \"house\": \"loops/breaks/house.wav\",\n \"chimes_l\": \"loops/chimes/chimes_l.wav\",\n \"noise_c\": \"loops/noise/noise_c.wav\",\n \"noise_e\": \"loops/noise/noise_e.wav\",\n \"noise_e_01\": \"loops/noise/noise_e_01.wav\",\n \"noise_mw\": \"loops/noise/noise_mw.wav\",\n \"noise_p\": \"loops/noise/noise_p.wav\",\n \"noise_r\": \"loops/noise/noise_r.wav\",\n \"choir_01\": \"vocal/choir/choir_01.wav\",\n \"choir_02\": \"vocal/choir/choir_02.wav\",\n \"choir_03\": \"vocal/choir/choir_03.wav\",\n \"choir_o\": \"vocal/choir/choir_o.wav\",\n \"wiper\": \"loops/foley/car/wiper.wav\",\n \"wiper_out\": \"loops/foley/car/wiper_out.wav\",\n \"wood_l\": \"loops/foley/wood/wood_l.wav\",\n \"wood_l_01\": \"loops/foley/wood/wood_l_01.wav\",\n \"violin_a\": \"string/bowed/violin/violin_a.wav\",\n \"violin_b\": \"string/bowed/violin/violin_b.wav\",\n \"violin_c\": \"string/bowed/violin/violin_c.wav\",\n \"violin_d\": \"string/bowed/violin/violin_d.wav\",\n \"violin_e\": \"string/bowed/violin/violin_e.wav\",\n \"violin_f\": \"string/bowed/violin/violin_f.wav\",\n \"violin_g\": \"string/bowed/violin/violin_g.wav\",\n \"harp_down\": \"string/plucked/harp/harp_down.wav\",\n \"harp_up\": \"string/plucked/harp/harp_up.wav\",\n \"pluck_a\": \"string/plucked/violin/pluck_a.wav\",\n \"pluck_b\": \"string/plucked/violin/pluck_b.wav\",\n \"pluck_c\": \"string/plucked/violin/pluck_c.wav\",\n \"pluck_d\": \"string/plucked/violin/pluck_d.wav\",\n \"pluck_e\": \"string/plucked/violin/pluck_e.wav\",\n \"pluck_f\": \"string/plucked/violin/pluck_f.wav\",\n \"pluck_g\": \"string/plucked/violin/pluck_g.wav\"\n}\n");
17427
17467
 
@@ -17429,23 +17469,68 @@ class Mercury extends MercuryInterpreter {
17429
17469
  // add the buffers via function
17430
17470
  // this.addBuffers(['http://localhost:8080/mercury-engine/src/data/samples.json'])
17431
17471
 
17472
+ // setting parameters
17473
+ this.bpm;
17474
+ this.volume;
17475
+ this.lowPass;
17476
+ this.highPass;
17477
+
17432
17478
  // effects on main output for Tone
17433
17479
  this.gain = new Tone.Gain(1);
17434
- this.lowPass = new Tone.Filter(18000, 'lowpass');
17435
- this.highPass = new Tone.Filter(5, 'highpass');
17436
- Tone.Destination.chain(this.lowPass, this.highPass, this.gain);
17480
+ this.lowPassF = new Tone.Filter(18000, 'lowpass');
17481
+ this.highPassF = new Tone.Filter(5, 'highpass');
17482
+ Tone.Destination.chain(this.lowPassF, this.highPassF, this.gain);
17437
17483
 
17438
17484
  // a recorder for the sound
17439
17485
  this.recorder = new Tone.Recorder({ mimeType: 'audio/webm' });
17440
17486
  this.gain.connect(this.recorder);
17441
17487
 
17488
+ // default settings
17489
+ this.setBPM(100);
17490
+ this.setVolume(1);
17491
+ this.setHighPass(18000);
17492
+ this.setLowPass(5);
17493
+ this.setCrossFade(250);
17494
+
17495
+ // load the buffers from the github
17442
17496
  this.buffers = new Tone.ToneAudioBuffers({
17443
17497
  urls: this.samples,
17444
17498
  baseUrl: "https://raw.githubusercontent.com/tmhglnd/mercury-playground/main/public/assets/samples/",
17445
17499
  onload: () => {
17446
17500
  console.log('Samples loaded', this.buffers);
17447
17501
  // executes a callback from the class constructor
17448
- if (callback){ callback(); }
17502
+ // if a callback is provided
17503
+ if (onload){ onload(); }
17504
+ }
17505
+ });
17506
+
17507
+ // the midi status, inputs and outputs
17508
+ this.midi = { enabled: false, inputs: [], outputs: [] };
17509
+
17510
+ // WebMIDI Setup if supported by the browser
17511
+ // Else `midi` not supported in the Mercury code
17512
+ WebMidi.enable((error) => {
17513
+ if (error) {
17514
+ console.error(`WebMIDI not enabled: ${error}`);
17515
+ } else {
17516
+ this.midi.enabled = true;
17517
+
17518
+ console.log(`WebMIDI enabled`);
17519
+ if (WebMidi.inputs.length < 1){
17520
+ console.log(`No MIDI device detected`);
17521
+ } else {
17522
+ this.midi.inputs = WebMidi.inputs;
17523
+ this.midi.outputs = WebMidi.outputs;
17524
+
17525
+ WebMidi.inputs.forEach((device, index) => {
17526
+ console.log(`in ${index}: ${device.name}`);
17527
+ });
17528
+ WebMidi.outputs.forEach((device, index) => {
17529
+ console.log(`out ${index}: ${device.name}`);
17530
+ });
17531
+ }
17532
+ // execute a callback when midi is loaded if provided
17533
+ if (onmidi) { onmidi(); }
17449
17534
  }
17450
17535
  });
17451
17536
  }
@@ -17480,7 +17565,8 @@ class Mercury extends MercuryInterpreter {
17480
17565
  }
17481
17566
 
17482
17567
  // set the bpm and optionally ramp in milliseconds
17483
- bpm(bpm, ramp=0) {
17568
+ setBPM(bpm, ramp=0) {
17569
+ this.bpm = bpm;
17484
17570
  if (ramp > 0){
17485
17571
  Tone.Transport.bpm.rampTo(bpm, ramp / 1000);
17486
17572
  } else {
@@ -17496,12 +17582,12 @@ class Mercury extends MercuryInterpreter {
17496
17582
  // generate a random bpm between 75 and 150
17497
17583
  randomBPM(){
17498
17584
  let bpm = Math.floor(Math.random() * 75) + 75.0;
17499
- this.bpm(bpm);
17585
+ this.setBPM(bpm);
17500
17586
  }
17501
17587
 
17502
17588
  // add files to the buffer from a single File Link
17503
17589
  // an array or file paths, or a json of { name:file, ... }
17504
- async addSamples(uploads){
17590
+ async addBuffers(uploads){
17505
17591
  // for every file from uploads
17506
17592
  uploads.forEach((f) => {
17507
17593
  let n = f;
@@ -17542,7 +17628,7 @@ class Mercury extends MercuryInterpreter {
17542
17628
 
17543
17629
  // add to ToneAudioBuffers
17544
17630
  this.buffers.add(n, url, () => {
17545
- console.log(`sound added as: ${n}`);
17631
+ Util.log(`sound added as: ${n}`);
17546
17632
  URL.revokeObjectURL(url);
17547
17633
 
17548
17634
  // also add soundfiles to menu for easy selection
@@ -17551,7 +17637,7 @@ class Mercury extends MercuryInterpreter {
17551
17637
  // o.value = o.innerHTML = n;
17552
17638
  // m.appendChild(o);
17553
17639
  }, (e) => {
17554
- console.log(`error adding sound from: ${n}`);
17640
+ Util.log(`error adding sound from: ${n}`);
17555
17641
  });
17556
17642
  }
17557
17643
 
@@ -17589,24 +17675,27 @@ class Mercury extends MercuryInterpreter {
17589
17675
 
17590
17676
  // set lowpass frequency cutoff and ramptime
17591
17677
  setLowPass(f, t=0){
17678
+ this.lowPass = f;
17592
17679
  if (t > 0){
17593
- this.lowPass.frequency.rampTo(f, t/1000, Tone.now());
17680
+ this.lowPassF.frequency.rampTo(f, t/1000, Tone.now());
17594
17681
  } else {
17595
- this.lowPass.frequency.setValueAtTime(f, Tone.now());
17682
+ this.lowPassF.frequency.setValueAtTime(f, Tone.now());
17596
17683
  }
17597
17684
  }
17598
17685
 
17599
17686
  // set highpass frequency cutoff and ramptime
17600
17687
  setHighPass(f, t=0){
17688
+ this.highPass = f;
17601
17689
  if (t > 0){
17602
- this.highPass.frequency.rampTo(f, t/1000, Tone.now());
17690
+ this.highPassF.frequency.rampTo(f, t/1000, Tone.now());
17603
17691
  } else {
17604
- this.highPass.frequency.setValueAtTime(f, Tone.now());
17692
+ this.highPassF.frequency.setValueAtTime(f, Tone.now());
17605
17693
  }
17606
17694
  }
17607
17695
 
17608
17696
  // set volume in floatingpoint and ramptime
17609
17697
  setVolume(v, t=0){
17698
+ this.volume = v;
17610
17699
  if (t > 0){
17611
17700
  this.gain.gain.rampTo(v, t/1000, Tone.now());
17612
17701
  } else {
@@ -17614,6 +17703,11 @@ class Mercury extends MercuryInterpreter {
17614
17703
  }
17615
17704
  }
17616
17705
 
17706
+ // get the volume as float between 0-1
17707
+ getVolume(){
17708
+ return this.gain.gain.value;
17709
+ }
17710
+
17617
17711
  // a recording function
17618
17712
  // default starts recording, a false/0 stops recording
17619
17713
  // optionally add a filename to the downloading file
@@ -17633,7 +17727,7 @@ class Mercury extends MercuryInterpreter {
17633
17727
  anchor.click();
17634
17728
  }
17635
17729
  } catch(e) {
17636
- console.log(`Error starting/stopping recording ${e}`);
17730
+ Util.log(`Error starting/stopping recording ${e}`);
17637
17731
  }
17638
17732
  }
17639
17733
 
@@ -17643,5 +17737,5 @@ class Mercury extends MercuryInterpreter {
17643
17737
  }
17644
17738
  }
17645
17739
  module.exports = { Mercury };
17646
- },{"./interpreter":68,"tone":44}]},{},[69])(69)
17740
+ },{"./core/Util.js":66,"./interpreter":68,"tone":44,"webmidi":55}]},{},[69])(69)
17647
17741
  });