@marmooo/midy 0.3.6 → 0.3.8

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/esm/midy-GM1.js CHANGED
@@ -200,7 +200,7 @@ export class MidyGM1 {
200
200
  enumerable: true,
201
201
  configurable: true,
202
202
  writable: true,
203
- value: this.initSoundFontTable()
203
+ value: Array.from({ length: 128 }, () => [])
204
204
  });
205
205
  Object.defineProperty(this, "voiceCounter", {
206
206
  enumerable: true,
@@ -244,6 +244,12 @@ export class MidyGM1 {
244
244
  writable: true,
245
245
  value: false
246
246
  });
247
+ Object.defineProperty(this, "playPromise", {
248
+ enumerable: true,
249
+ configurable: true,
250
+ writable: true,
251
+ value: void 0
252
+ });
247
253
  Object.defineProperty(this, "timeline", {
248
254
  enumerable: true,
249
255
  configurable: true,
@@ -275,6 +281,7 @@ export class MidyGM1 {
275
281
  length: 1,
276
282
  sampleRate: audioContext.sampleRate,
277
283
  });
284
+ this.messageHandlers = this.createMessageHandlers();
278
285
  this.voiceParamsHandlers = this.createVoiceParamsHandlers();
279
286
  this.controlChangeHandlers = this.createControlChangeHandlers();
280
287
  this.channels = this.createChannels(audioContext);
@@ -282,21 +289,14 @@ export class MidyGM1 {
282
289
  this.scheduler.connect(audioContext.destination);
283
290
  this.GM1SystemOn();
284
291
  }
285
- initSoundFontTable() {
286
- const table = new Array(128);
287
- for (let i = 0; i < 128; i++) {
288
- table[i] = new Map();
289
- }
290
- return table;
291
- }
292
292
  addSoundFont(soundFont) {
293
293
  const index = this.soundFonts.length;
294
294
  this.soundFonts.push(soundFont);
295
295
  const presetHeaders = soundFont.parsed.presetHeaders;
296
+ const soundFontTable = this.soundFontTable;
296
297
  for (let i = 0; i < presetHeaders.length; i++) {
297
- const presetHeader = presetHeaders[i];
298
- const banks = this.soundFontTable[presetHeader.preset];
299
- banks.set(presetHeader.bank, index);
298
+ const { preset, bank } = presetHeaders[i];
299
+ soundFontTable[preset][bank] = index;
300
300
  }
301
301
  }
302
302
  async toUint8Array(input) {
@@ -374,13 +374,16 @@ export class MidyGM1 {
374
374
  this.GM1SystemOn();
375
375
  }
376
376
  getVoiceId(channel, noteNumber, velocity) {
377
- const bankNumber = this.calcBank(channel);
378
- const soundFontIndex = this.soundFontTable[channel.programNumber]
379
- .get(bankNumber);
377
+ const programNumber = channel.programNumber;
378
+ const bankTable = this.soundFontTable[programNumber];
379
+ if (!bankTable)
380
+ return;
381
+ const bank = channel.isDrum ? 128 : 0;
382
+ const soundFontIndex = bankTable[bank];
380
383
  if (soundFontIndex === undefined)
381
384
  return;
382
385
  const soundFont = this.soundFonts[soundFontIndex];
383
- const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
386
+ const voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
384
387
  const { instrument, sampleID } = voice.generators;
385
388
  return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
386
389
  }
@@ -429,13 +432,16 @@ export class MidyGM1 {
429
432
  }
430
433
  return bufferSource;
431
434
  }
432
- async scheduleTimelineEvents(t, resumeTime, queueIndex) {
433
- while (queueIndex < this.timeline.length) {
434
- const event = this.timeline[queueIndex];
435
- if (event.startTime > t + this.lookAhead)
435
+ async scheduleTimelineEvents(scheduleTime, queueIndex) {
436
+ const timeOffset = this.resumeTime - this.startTime;
437
+ const lookAheadCheckTime = scheduleTime + timeOffset + this.lookAhead;
438
+ const schedulingOffset = this.startDelay - timeOffset;
439
+ const timeline = this.timeline;
440
+ while (queueIndex < timeline.length) {
441
+ const event = timeline[queueIndex];
442
+ if (lookAheadCheckTime < event.startTime)
436
443
  break;
437
- const delay = this.startDelay - resumeTime;
438
- const startTime = event.startTime + delay;
444
+ const startTime = event.startTime + schedulingOffset;
439
445
  switch (event.type) {
440
446
  case "noteOn":
441
447
  await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, startTime);
@@ -470,69 +476,77 @@ export class MidyGM1 {
470
476
  }
471
477
  return 0;
472
478
  }
473
- playNotes() {
474
- return new Promise((resolve) => {
475
- this.isPlaying = true;
476
- this.isPaused = false;
477
- this.startTime = this.audioContext.currentTime;
478
- let queueIndex = this.getQueueIndex(this.resumeTime);
479
- let resumeTime = this.resumeTime - this.startTime;
479
+ resetAllStates() {
480
+ this.exclusiveClassNotes.fill(undefined);
481
+ this.drumExclusiveClassNotes.fill(undefined);
482
+ this.voiceCache.clear();
483
+ for (let i = 0; i < this.channels.length; i++) {
484
+ this.channels[i].scheduledNotes = [];
485
+ this.resetChannelStates(i);
486
+ }
487
+ }
488
+ updateStates(queueIndex, nextQueueIndex) {
489
+ if (nextQueueIndex < queueIndex)
490
+ queueIndex = 0;
491
+ for (let i = queueIndex; i < nextQueueIndex; i++) {
492
+ const event = this.timeline[i];
493
+ switch (event.type) {
494
+ case "controller":
495
+ this.setControlChange(event.channel, event.controllerType, event.value, 0);
496
+ break;
497
+ case "programChange":
498
+ this.setProgramChange(event.channel, event.programNumber, 0);
499
+ break;
500
+ case "pitchBend":
501
+ this.setPitchBend(event.channel, event.value + 8192, 0);
502
+ break;
503
+ case "sysEx":
504
+ this.handleSysEx(event.data, 0);
505
+ }
506
+ }
507
+ }
508
+ async playNotes() {
509
+ if (this.audioContext.state === "suspended") {
510
+ await this.audioContext.resume();
511
+ }
512
+ this.isPlaying = true;
513
+ this.isPaused = false;
514
+ this.startTime = this.audioContext.currentTime;
515
+ let queueIndex = this.getQueueIndex(this.resumeTime);
516
+ let finished = false;
517
+ this.notePromises = [];
518
+ while (queueIndex < this.timeline.length) {
519
+ const now = this.audioContext.currentTime;
520
+ queueIndex = await this.scheduleTimelineEvents(now, queueIndex);
521
+ if (this.isPausing) {
522
+ await this.stopNotes(0, true, now);
523
+ await this.audioContext.suspend();
524
+ this.notePromises = [];
525
+ break;
526
+ }
527
+ else if (this.isStopping) {
528
+ await this.stopNotes(0, true, now);
529
+ await this.audioContext.suspend();
530
+ finished = true;
531
+ break;
532
+ }
533
+ else if (this.isSeeking) {
534
+ await this.stopNotes(0, true, now);
535
+ this.startTime = this.audioContext.currentTime;
536
+ const nextQueueIndex = this.getQueueIndex(this.resumeTime);
537
+ this.updateStates(queueIndex, nextQueueIndex);
538
+ queueIndex = nextQueueIndex;
539
+ this.isSeeking = false;
540
+ continue;
541
+ }
542
+ const waitTime = now + this.noteCheckInterval;
543
+ await this.scheduleTask(() => { }, waitTime);
544
+ }
545
+ if (finished) {
480
546
  this.notePromises = [];
481
- const schedulePlayback = async () => {
482
- if (queueIndex >= this.timeline.length) {
483
- await Promise.all(this.notePromises);
484
- this.notePromises = [];
485
- this.exclusiveClassNotes.fill(undefined);
486
- this.voiceCache.clear();
487
- for (let i = 0; i < this.channels.length; i++) {
488
- this.channels[i].scheduledNotes = [];
489
- this.resetAllStates(i);
490
- }
491
- resolve();
492
- return;
493
- }
494
- const now = this.audioContext.currentTime;
495
- const t = now + resumeTime;
496
- queueIndex = await this.scheduleTimelineEvents(t, resumeTime, queueIndex);
497
- if (this.isPausing) {
498
- await this.stopNotes(0, true, now);
499
- this.notePromises = [];
500
- this.isPausing = false;
501
- this.isPaused = true;
502
- resolve();
503
- return;
504
- }
505
- else if (this.isStopping) {
506
- await this.stopNotes(0, true, now);
507
- this.notePromises = [];
508
- this.exclusiveClassNotes.fill(undefined);
509
- this.voiceCache.clear();
510
- for (let i = 0; i < this.channels.length; i++) {
511
- this.channels[i].scheduledNotes = [];
512
- this.resetAllStates(i);
513
- }
514
- this.isStopping = false;
515
- this.isPaused = false;
516
- resolve();
517
- return;
518
- }
519
- else if (this.isSeeking) {
520
- this.stopNotes(0, true, now);
521
- this.exclusiveClassNotes.fill(undefined);
522
- this.startTime = this.audioContext.currentTime;
523
- queueIndex = this.getQueueIndex(this.resumeTime);
524
- resumeTime = this.resumeTime - this.startTime;
525
- this.isSeeking = false;
526
- await schedulePlayback();
527
- }
528
- else {
529
- const waitTime = now + this.noteCheckInterval;
530
- await this.scheduleTask(() => { }, waitTime);
531
- await schedulePlayback();
532
- }
533
- };
534
- schedulePlayback();
535
- });
547
+ this.resetAllStates();
548
+ }
549
+ this.isPlaying = false;
536
550
  }
537
551
  ticksToSecond(ticks, secondsPerBeat) {
538
552
  return ticks * secondsPerBeat / this.ticksPerBeat;
@@ -540,16 +554,16 @@ export class MidyGM1 {
540
554
  secondToTicks(second, secondsPerBeat) {
541
555
  return second * this.ticksPerBeat / secondsPerBeat;
542
556
  }
557
+ getSoundFontId(channel) {
558
+ const programNumber = channel.programNumber;
559
+ const bank = channel.isDrum ? "128" : "000";
560
+ const program = programNumber.toString().padStart(3, "0");
561
+ return `${bank}:${program}`;
562
+ }
543
563
  extractMidiData(midi) {
544
564
  const instruments = new Set();
545
565
  const timeline = [];
546
- const tmpChannels = new Array(this.channels.length);
547
- for (let i = 0; i < tmpChannels.length; i++) {
548
- tmpChannels[i] = {
549
- programNumber: -1,
550
- bank: this.channels[i].bank,
551
- };
552
- }
566
+ const channels = this.channels;
553
567
  for (let i = 0; i < midi.tracks.length; i++) {
554
568
  const track = midi.tracks[i];
555
569
  let currentTicks = 0;
@@ -559,17 +573,15 @@ export class MidyGM1 {
559
573
  event.ticks = currentTicks;
560
574
  switch (event.type) {
561
575
  case "noteOn": {
562
- const channel = tmpChannels[event.channel];
563
- if (channel.programNumber < 0) {
564
- instruments.add(`${channel.bank}:0`);
565
- channel.programNumber = 0;
566
- }
576
+ const channel = channels[event.channel];
577
+ instruments.add(this.getSoundFontId(channel));
567
578
  break;
568
579
  }
569
580
  case "programChange": {
570
- const channel = tmpChannels[event.channel];
571
- channel.programNumber = event.programNumber;
572
- instruments.add(`${channel.bankNumber}:${channel.programNumber}`);
581
+ const channel = channels[event.channel];
582
+ this.setProgramChange(event.channel, event.programNumber);
583
+ instruments.add(this.getSoundFontId(channel));
584
+ break;
573
585
  }
574
586
  }
575
587
  delete event.deltaTime;
@@ -633,26 +645,32 @@ export class MidyGM1 {
633
645
  this.resumeTime = 0;
634
646
  if (this.voiceCounter.size === 0)
635
647
  this.cacheVoiceIds();
636
- await this.playNotes();
637
- this.isPlaying = false;
648
+ this.playPromise = this.playNotes();
649
+ await this.playPromise;
638
650
  }
639
- stop() {
651
+ async stop() {
640
652
  if (!this.isPlaying)
641
653
  return;
642
654
  this.isStopping = true;
655
+ await this.playPromise;
656
+ this.isStopping = false;
643
657
  }
644
- pause() {
658
+ async pause() {
645
659
  if (!this.isPlaying || this.isPaused)
646
660
  return;
647
661
  const now = this.audioContext.currentTime;
648
662
  this.resumeTime += now - this.startTime - this.startDelay;
649
663
  this.isPausing = true;
664
+ await this.playPromise;
665
+ this.isPausing = false;
666
+ this.isPaused = true;
650
667
  }
651
668
  async resume() {
652
669
  if (!this.isPaused)
653
670
  return;
654
- await this.playNotes();
655
- this.isPlaying = false;
671
+ this.playPromise = this.playNotes();
672
+ await this.playPromise;
673
+ this.isPaused = false;
656
674
  }
657
675
  seekTo(second) {
658
676
  this.resumeTime = second;
@@ -869,13 +887,16 @@ export class MidyGM1 {
869
887
  }
870
888
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
871
889
  const channel = this.channels[channelNumber];
872
- const bankNumber = channel.bank;
873
- const soundFontIndex = this.soundFontTable[channel.programNumber]
874
- .get(bankNumber);
890
+ const programNumber = channel.programNumber;
891
+ const bankTable = this.soundFontTable[programNumber];
892
+ if (!bankTable)
893
+ return;
894
+ const bank = channel.isDrum ? 128 : 0;
895
+ const soundFontIndex = bankTable[bank];
875
896
  if (soundFontIndex === undefined)
876
897
  return;
877
898
  const soundFont = this.soundFonts[soundFontIndex];
878
- const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
899
+ const voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
879
900
  if (!voice)
880
901
  return;
881
902
  const note = await this.createNote(channel, voice, noteNumber, velocity, startTime);
@@ -977,7 +998,26 @@ export class MidyGM1 {
977
998
  channel.sustainNotes = [];
978
999
  return promises;
979
1000
  }
980
- handleMIDIMessage(statusByte, data1, data2, scheduleTime) {
1001
+ createMessageHandlers() {
1002
+ const handlers = new Array(256);
1003
+ // Channel Message
1004
+ handlers[0x80] = (data, scheduleTime) => this.noteOff(data[0] & 0x0F, data[1], data[2], scheduleTime);
1005
+ handlers[0x90] = (data, scheduleTime) => this.noteOn(data[0] & 0x0F, data[1], data[2], scheduleTime);
1006
+ handlers[0xB0] = (data, scheduleTime) => this.setControlChange(data[0] & 0x0F, data[1], data[2], scheduleTime);
1007
+ handlers[0xC0] = (data, scheduleTime) => this.setProgramChange(data[0] & 0x0F, data[1], scheduleTime);
1008
+ handlers[0xE0] = (data, scheduleTime) => this.handlePitchBendMessage(data[0] & 0x0F, data[1], data[2], scheduleTime);
1009
+ return handlers;
1010
+ }
1011
+ handleMessage(data, scheduleTime) {
1012
+ const status = data[0];
1013
+ if (status === 0xF0) {
1014
+ return this.handleSysEx(data.subarray(1), scheduleTime);
1015
+ }
1016
+ const handler = this.messageHandlers[status];
1017
+ if (handler)
1018
+ handler(data, scheduleTime);
1019
+ }
1020
+ handleChannelMessage(statusByte, data1, data2, scheduleTime) {
981
1021
  const channelNumber = statusByte & 0x0F;
982
1022
  const messageType = statusByte & 0xF0;
983
1023
  switch (messageType) {
@@ -1057,28 +1097,36 @@ export class MidyGM1 {
1057
1097
  }
1058
1098
  createVoiceParamsHandlers() {
1059
1099
  return {
1060
- modLfoToPitch: (channel, note, _prevValue, scheduleTime) => {
1100
+ modLfoToPitch: (channel, note, scheduleTime) => {
1061
1101
  if (0 < channel.state.modulationDepth) {
1062
1102
  this.setModLfoToPitch(channel, note, scheduleTime);
1063
1103
  }
1064
1104
  },
1065
- vibLfoToPitch: (_channel, _note, _prevValue, _scheduleTime) => { },
1066
- modLfoToFilterFc: (channel, note, _prevValue, scheduleTime) => {
1105
+ vibLfoToPitch: (_channel, _note, _scheduleTime) => { },
1106
+ modLfoToFilterFc: (channel, note, scheduleTime) => {
1067
1107
  if (0 < channel.state.modulationDepth) {
1068
1108
  this.setModLfoToFilterFc(note, scheduleTime);
1069
1109
  }
1070
1110
  },
1071
- modLfoToVolume: (channel, note, _prevValue, scheduleTime) => {
1111
+ modLfoToVolume: (channel, note, scheduleTime) => {
1072
1112
  if (0 < channel.state.modulationDepth) {
1073
1113
  this.setModLfoToVolume(note, scheduleTime);
1074
1114
  }
1075
1115
  },
1076
- chorusEffectsSend: (_channel, _note, _prevValue, _scheduleTime) => { },
1077
- reverbEffectsSend: (_channel, _note, _prevValue, _scheduleTime) => { },
1078
- delayModLFO: (_channel, note, _prevValue, scheduleTime) => this.setDelayModLFO(note, scheduleTime),
1079
- freqModLFO: (_channel, note, _prevValue, scheduleTime) => this.setFreqModLFO(note, scheduleTime),
1080
- delayVibLFO: (_channel, _note, _prevValue, _scheduleTime) => { },
1081
- freqVibLFO: (_channel, _note, _prevValue, _scheduleTime) => { },
1116
+ chorusEffectsSend: (_channel, _note, _scheduleTime) => { },
1117
+ reverbEffectsSend: (_channel, _note, _scheduleTime) => { },
1118
+ delayModLFO: (_channel, note, scheduleTime) => {
1119
+ if (0 < channel.state.modulationDepth) {
1120
+ this.setDelayModLFO(note, scheduleTime);
1121
+ }
1122
+ },
1123
+ freqModLFO: (_channel, note, scheduleTime) => {
1124
+ if (0 < channel.state.modulationDepth) {
1125
+ this.setFreqModLFO(note, scheduleTime);
1126
+ }
1127
+ },
1128
+ delayVibLFO: (_channel, _note, _scheduleTime) => { },
1129
+ freqVibLFO: (_channel, _note, _scheduleTime) => { },
1082
1130
  };
1083
1131
  }
1084
1132
  getControllerState(channel, noteNumber, velocity) {
@@ -1101,7 +1149,7 @@ export class MidyGM1 {
1101
1149
  continue;
1102
1150
  note.voiceParams[key] = value;
1103
1151
  if (key in this.voiceParamsHandlers) {
1104
- this.voiceParamsHandlers[key](channel, note, prevValue, scheduleTime);
1152
+ this.voiceParamsHandlers[key](channel, note, scheduleTime);
1105
1153
  }
1106
1154
  else {
1107
1155
  if (volumeEnvelopeKeySet.has(key))
@@ -1272,8 +1320,8 @@ export class MidyGM1 {
1272
1320
  }
1273
1321
  handlePitchBendRangeRPN(channelNumber, scheduleTime) {
1274
1322
  const channel = this.channels[channelNumber];
1275
- this.limitData(channel, 0, 127, 0, 99);
1276
- const pitchBendRange = channel.dataMSB + channel.dataLSB / 100;
1323
+ this.limitData(channel, 0, 127, 0, 127);
1324
+ const pitchBendRange = (channel.dataMSB + channel.dataLSB / 128) * 100;
1277
1325
  this.setPitchBendRange(channelNumber, pitchBendRange, scheduleTime);
1278
1326
  }
1279
1327
  setPitchBendRange(channelNumber, value, scheduleTime) {
@@ -1281,7 +1329,7 @@ export class MidyGM1 {
1281
1329
  scheduleTime ??= this.audioContext.currentTime;
1282
1330
  const state = channel.state;
1283
1331
  const prev = state.pitchWheelSensitivity;
1284
- const next = value / 128;
1332
+ const next = value / 12800;
1285
1333
  state.pitchWheelSensitivity = next;
1286
1334
  channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
1287
1335
  this.updateChannelDetune(channel, scheduleTime);
@@ -1290,14 +1338,15 @@ export class MidyGM1 {
1290
1338
  handleFineTuningRPN(channelNumber, scheduleTime) {
1291
1339
  const channel = this.channels[channelNumber];
1292
1340
  this.limitData(channel, 0, 127, 0, 127);
1293
- const fineTuning = channel.dataMSB * 128 + channel.dataLSB;
1341
+ const value = channel.dataMSB * 128 + channel.dataLSB;
1342
+ const fineTuning = (value - 8192) / 8192 * 100;
1294
1343
  this.setFineTuning(channelNumber, fineTuning, scheduleTime);
1295
1344
  }
1296
1345
  setFineTuning(channelNumber, value, scheduleTime) {
1297
1346
  const channel = this.channels[channelNumber];
1298
1347
  scheduleTime ??= this.audioContext.currentTime;
1299
1348
  const prev = channel.fineTuning;
1300
- const next = (value - 8192) / 8.192; // cent
1349
+ const next = value;
1301
1350
  channel.fineTuning = next;
1302
1351
  channel.detune += next - prev;
1303
1352
  this.updateChannelDetune(channel, scheduleTime);
@@ -1305,14 +1354,14 @@ export class MidyGM1 {
1305
1354
  handleCoarseTuningRPN(channelNumber, scheduleTime) {
1306
1355
  const channel = this.channels[channelNumber];
1307
1356
  this.limitDataMSB(channel, 0, 127);
1308
- const coarseTuning = channel.dataMSB;
1357
+ const coarseTuning = (channel.dataMSB - 64) * 100;
1309
1358
  this.setCoarseTuning(channelNumber, coarseTuning, scheduleTime);
1310
1359
  }
1311
1360
  setCoarseTuning(channelNumber, value, scheduleTime) {
1312
1361
  const channel = this.channels[channelNumber];
1313
1362
  scheduleTime ??= this.audioContext.currentTime;
1314
1363
  const prev = channel.coarseTuning;
1315
- const next = (value - 64) * 100; // cent
1364
+ const next = value;
1316
1365
  channel.coarseTuning = next;
1317
1366
  channel.detune += next - prev;
1318
1367
  this.updateChannelDetune(channel, scheduleTime);
@@ -1321,7 +1370,7 @@ export class MidyGM1 {
1321
1370
  scheduleTime ??= this.audioContext.currentTime;
1322
1371
  return this.stopActiveNotes(channelNumber, 0, true, scheduleTime);
1323
1372
  }
1324
- resetAllStates(channelNumber) {
1373
+ resetChannelStates(channelNumber) {
1325
1374
  const scheduleTime = this.audioContext.currentTime;
1326
1375
  const channel = this.channels[channelNumber];
1327
1376
  const state = channel.state;
@@ -1396,10 +1445,8 @@ export class MidyGM1 {
1396
1445
  for (let i = 0; i < this.channels.length; i++) {
1397
1446
  this.allSoundOff(i, 0, scheduleTime);
1398
1447
  const channel = this.channels[i];
1399
- channel.bank = 0;
1400
1448
  channel.isDrum = false;
1401
1449
  }
1402
- this.channels[9].bank = 128;
1403
1450
  this.channels[9].isDrum = true;
1404
1451
  }
1405
1452
  handleUniversalRealTimeExclusiveMessage(data, scheduleTime) {
@@ -1420,16 +1467,11 @@ export class MidyGM1 {
1420
1467
  const volume = (data[5] * 128 + data[4]) / 16383;
1421
1468
  this.setMasterVolume(volume, scheduleTime);
1422
1469
  }
1423
- setMasterVolume(volume, scheduleTime) {
1470
+ setMasterVolume(value, scheduleTime) {
1424
1471
  scheduleTime ??= this.audioContext.currentTime;
1425
- if (volume < 0 && 1 < volume) {
1426
- console.error("Master Volume is out of range");
1427
- }
1428
- else {
1429
- this.masterVolume.gain
1430
- .cancelScheduledValues(scheduleTime)
1431
- .setValueAtTime(volume * volume, scheduleTime);
1432
- }
1472
+ this.masterVolume.gain
1473
+ .cancelScheduledValues(scheduleTime)
1474
+ .setValueAtTime(value * value, scheduleTime);
1433
1475
  }
1434
1476
  handleSysEx(data, scheduleTime) {
1435
1477
  switch (data[0]) {
@@ -1466,15 +1508,15 @@ Object.defineProperty(MidyGM1, "channelSettings", {
1466
1508
  configurable: true,
1467
1509
  writable: true,
1468
1510
  value: {
1511
+ scheduleIndex: 0,
1469
1512
  detune: 0,
1470
1513
  programNumber: 0,
1471
- bank: 0,
1472
1514
  dataMSB: 0,
1473
1515
  dataLSB: 0,
1474
1516
  rpnMSB: 127,
1475
1517
  rpnLSB: 127,
1476
1518
  modulationDepthRange: 50, // cent
1477
- fineTuning: 0, // cb
1478
- coarseTuning: 0, // cb
1519
+ fineTuning: 0, // cent
1520
+ coarseTuning: 0, // cent
1479
1521
  }
1480
1522
  });