@marmooo/midy 0.3.8 → 0.4.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marmooo/midy",
3
- "version": "0.3.8",
3
+ "version": "0.4.1",
4
4
  "description": "A MIDI player/synthesizer written in JavaScript that supports GM-Lite/GM1 and SF2/SF3.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,7 +22,7 @@
22
22
  "test": "node test_runner.js"
23
23
  },
24
24
  "dependencies": {
25
- "@marmooo/soundfont-parser": "^0.1.4",
25
+ "@marmooo/soundfont-parser": "^0.1.5",
26
26
  "midi-file": "^1.2.4"
27
27
  },
28
28
  "devDependencies": {
@@ -25,6 +25,7 @@ export class MidyGM1 {
25
25
  soundFontTable: never[][];
26
26
  voiceCounter: Map<any, any>;
27
27
  voiceCache: Map<any, any>;
28
+ realtimeVoiceCache: Map<any, any>;
28
29
  isPlaying: boolean;
29
30
  isPausing: boolean;
30
31
  isPaused: boolean;
@@ -104,21 +105,20 @@ export class MidyGM1 {
104
105
  clampCutoffFrequency(frequency: any): number;
105
106
  setFilterEnvelope(note: any, scheduleTime: any): void;
106
107
  startModulation(channel: any, note: any, scheduleTime: any): void;
107
- getAudioBuffer(channel: any, noteNumber: any, velocity: any, voiceParams: any): Promise<any>;
108
- createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any): Promise<Note>;
108
+ getAudioBuffer(channel: any, noteNumber: any, velocity: any, voiceParams: any, realtime: any): Promise<any>;
109
+ setNoteAudioNode(channel: any, note: any, realtime: any): Promise<any>;
109
110
  handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
110
- scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
111
- noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
111
+ setNoteRouting(channelNumber: any, note: any, startTime: any): void;
112
+ noteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
112
113
  disconnectNote(note: any): void;
113
114
  releaseNote(channel: any, note: any, endTime: any): Promise<any>;
114
- scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): void;
115
+ noteOff(channelNumber: any, noteNumber: any, velocity: any, endTime: any, force: any): Promise<any> | undefined;
115
116
  setNoteIndex(channel: any, index: any): void;
116
117
  findNoteOffIndex(channel: any, noteNumber: any): any;
117
- noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): void;
118
- releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
118
+ releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
119
119
  createMessageHandlers(): any[];
120
120
  handleMessage(data: any, scheduleTime: any): void;
121
- handleChannelMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<void>;
121
+ handleChannelMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
122
122
  setProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
123
123
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
124
124
  setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
@@ -179,22 +179,4 @@ export class MidyGM1 {
179
179
  handleSysEx(data: any, scheduleTime: any): void;
180
180
  scheduleTask(callback: any, scheduleTime: any): Promise<any>;
181
181
  }
182
- declare class Note {
183
- constructor(noteNumber: any, velocity: any, startTime: any, voice: any, voiceParams: any);
184
- index: number;
185
- ending: boolean;
186
- bufferSource: any;
187
- filterNode: any;
188
- filterDepth: any;
189
- volumeEnvelopeNode: any;
190
- volumeDepth: any;
191
- modulationLFO: any;
192
- modulationDepth: any;
193
- noteNumber: any;
194
- velocity: any;
195
- startTime: any;
196
- voice: any;
197
- voiceParams: any;
198
- }
199
- export {};
200
182
  //# sourceMappingURL=midy-GM1.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AA4FA;IAyBE;;;;;;;;;;;MAWE;IAEF,+BAeC;IApDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,0BAAuD;IACvD,4BAAyB;IACzB,0BAAuB;IACvB,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IAgBnC,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF,uBAAmD;IACnD;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,gBAAiD;IAMnD,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAWC;IAED;;;;MAeC;IAED,yCAaC;IAED,kDAUC;IAED,4DASC;IAED,yEAqDC;IAED,mCAOC;IAED,uBAQC;IAED,yDA2BC;IAED,2BAwCC;IAED,uDAEC;IAED,wDAEC;IAED,qCAKC;IAED;;;MAwDC;IAED,kGAeC;IAED,mGAeC;IAED,wEAMC;IAED,uBAMC;IAED,sBAKC;IAED,uBAQC;IAED,wBAKC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,yEASC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,2DAIC;IAED,+DAIC;IAED,sDAeC;IAED,qDAoBC;IAED,6CAIC;IAED,sDAsBC;IAED,kEAoBC;IAED,6FAyBC;IAED,oGAuCC;IAED,0EAiBC;IAED,kGAgCC;IAED,6FASC;IAED,gCASC;IAED,iEAoBC;IAED,qGAeC;IAED,6CAUC;IAED,qDAUC;IAED,qFASC;IAED,sFAeC;IAED,+BAmBC;IAED,kDAOC;IAED,uGA2BC;IAED,mFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAWC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MAiCC;IAED,oFAMC;IAED,6EA2BC;IAED,qCAeC;IAED,+FAWC;IAED,wDASC;IAED,iFAKC;IAED,oEAKC;IAED;;;MAMC;IAED,8DAKC;IAED,4EAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAWC;IAED,kFAeC;IAED,2DAMC;IAED,uDAkBC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAUC;IAED,iEAMC;IAED,uEAQC;IAED,mEAKC;IAED,yEAQC;IAED,gFAGC;IAED,6CAqBC;IAGD,8EAgCC;IAED,gFAGC;IAED,+EAgBC;IAED,qCASC;IAED,4EAaC;IAED,4DAGC;IAED,qDAKC;IAED,gDAYC;IAGD,6DAgBC;CACF;AAtiDD;IAWE,0FAMC;IAhBD,cAAW;IACX,gBAAe;IACf,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
1
+ {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AA6FA;IA0BE;;;;;;;;;;;MAWE;IAEF,+BAeC;IArDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,0BAAuD;IACvD,4BAAyB;IACzB,0BAAuB;IACvB,kCAA+B;IAC/B,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IAgBnC,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF,uBAAmD;IACnD;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,gBAAiD;IAMnD,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAWC;IAED;;;;MAeC;IAED,yCAaC;IAED,kDASC;IAED,4DASC;IAED,yEAoDC;IAED,mCAOC;IAED,uBASC;IAED,yDA2BC;IAED,2BA8CC;IAED,uDAEC;IAED,wDAEC;IAED,qCAKC;IAED;;;MAwDC;IAED,kGAeC;IAED,mGAeC;IAED,wEAMC;IAED,uBAMC;IAED,sBAKC;IAED,uBAQC;IAED,wBAKC;IAED,0BAKC;IAED,wBAOC;IAED,sBAIC;IAED,yDAQC;IAED,yEASC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,2DAIC;IAED,+DAIC;IAED,sDAeC;IAED,qDAoBC;IAED,6CAIC;IAED,sDAsBC;IAED,kEAoBC;IAED,4GAkCC;IAED,uEAwCC;IAED,0EAiBC;IAED,oEASC;IAED,0FAwBC;IAED,gCASC;IAED,iEAqBC;IAED,gHAqBC;IAED,6CAUC;IAED,qDAUC;IAED,4GAeC;IAED,+BAmBC;IAED,kDAOC;IAED,sGA2BC;IAED,mFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAYC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MAiCC;IAED,oFAMC;IAED,6EA2BC;IAED,qCAeC;IAED,+FAWC;IAED,wDAUC;IAED,iFAKC;IAED,oEAKC;IAED;;;MAMC;IAED,8DAKC;IAED,4EAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAWC;IAED,kFAeC;IAED,2DAMC;IAED,uDAkBC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAUC;IAED,iEAMC;IAED,uEAQC;IAED,mEAKC;IAED,yEAQC;IAED,gFAGC;IAED,6CAqBC;IAGD,8EAgCC;IAED,gFAGC;IAED,+EAgBC;IAED,qCASC;IAED,4EAaC;IAED,4DAGC;IAED,qDAKC;IAED,gDAYC;IAGD,6DAgBC;CACF"}
@@ -4,7 +4,19 @@ exports.MidyGM1 = void 0;
4
4
  const midi_file_1 = require("midi-file");
5
5
  const soundfont_parser_1 = require("@marmooo/soundfont-parser");
6
6
  class Note {
7
- constructor(noteNumber, velocity, startTime, voice, voiceParams) {
7
+ constructor(noteNumber, velocity, startTime) {
8
+ Object.defineProperty(this, "voice", {
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true,
12
+ value: void 0
13
+ });
14
+ Object.defineProperty(this, "voiceParams", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: void 0
19
+ });
8
20
  Object.defineProperty(this, "index", {
9
21
  enumerable: true,
10
22
  configurable: true,
@@ -17,6 +29,12 @@ class Note {
17
29
  writable: true,
18
30
  value: false
19
31
  });
32
+ Object.defineProperty(this, "pending", {
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true,
36
+ value: true
37
+ });
20
38
  Object.defineProperty(this, "bufferSource", {
21
39
  enumerable: true,
22
40
  configurable: true,
@@ -62,8 +80,6 @@ class Note {
62
80
  this.noteNumber = noteNumber;
63
81
  this.velocity = velocity;
64
82
  this.startTime = startTime;
65
- this.voice = voice;
66
- this.voiceParams = voiceParams;
67
83
  }
68
84
  }
69
85
  // normalized to 0-1 for use with the SF2 modulator model
@@ -73,11 +89,11 @@ const defaultControllerState = {
73
89
  pitchWheel: { type: 14, defaultValue: 8192 / 16383 },
74
90
  pitchWheelSensitivity: { type: 16, defaultValue: 2 / 128 },
75
91
  link: { type: 127, defaultValue: 0 },
76
- modulationDepth: { type: 128 + 1, defaultValue: 0 },
92
+ modulationDepthMSB: { type: 128 + 1, defaultValue: 0 },
77
93
  // dataMSB: { type: 128 + 6, defaultValue: 0, },
78
- volume: { type: 128 + 7, defaultValue: 100 / 127 },
79
- pan: { type: 128 + 10, defaultValue: 64 / 127 },
80
- expression: { type: 128 + 11, defaultValue: 1 },
94
+ volumeMSB: { type: 128 + 7, defaultValue: 100 / 127 },
95
+ panMSB: { type: 128 + 10, defaultValue: 64 / 127 },
96
+ expressionMSB: { type: 128 + 11, defaultValue: 1 },
81
97
  // dataLSB: { type: 128 + 38, defaultValue: 0, },
82
98
  sustainPedal: { type: 128 + 64, defaultValue: 0 },
83
99
  // rpnLSB: { type: 128 + 100, defaultValue: 127 },
@@ -217,6 +233,12 @@ class MidyGM1 {
217
233
  writable: true,
218
234
  value: new Map()
219
235
  });
236
+ Object.defineProperty(this, "realtimeVoiceCache", {
237
+ enumerable: true,
238
+ configurable: true,
239
+ writable: true,
240
+ value: new Map()
241
+ });
220
242
  Object.defineProperty(this, "isPlaying", {
221
243
  enumerable: true,
222
244
  configurable: true,
@@ -391,7 +413,7 @@ class MidyGM1 {
391
413
  return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
392
414
  }
393
415
  createChannelAudioNodes(audioContext) {
394
- const { gainLeft, gainRight } = this.panToGain(defaultControllerState.pan.defaultValue);
416
+ const { gainLeft, gainRight } = this.panToGain(defaultControllerState.panMSB.defaultValue);
395
417
  const gainL = new GainNode(audioContext, { gain: gainLeft });
396
418
  const gainR = new GainNode(audioContext, { gain: gainRight });
397
419
  const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
@@ -419,10 +441,9 @@ class MidyGM1 {
419
441
  return channels;
420
442
  }
421
443
  async createAudioBuffer(voiceParams) {
422
- const sample = voiceParams.sample;
423
- const sampleStart = voiceParams.start;
424
- const sampleEnd = sample.data.length + voiceParams.end;
425
- const audioBuffer = await sample.toAudioBuffer(this.audioContext, sampleStart, sampleEnd);
444
+ const { sample, start, end } = voiceParams;
445
+ const sampleEnd = sample.data.length + end;
446
+ const audioBuffer = await sample.toAudioBuffer(this.audioContext, start, sampleEnd);
426
447
  return audioBuffer;
427
448
  }
428
449
  createBufferSource(voiceParams, audioBuffer) {
@@ -447,12 +468,10 @@ class MidyGM1 {
447
468
  const startTime = event.startTime + schedulingOffset;
448
469
  switch (event.type) {
449
470
  case "noteOn":
450
- await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, startTime);
471
+ await this.noteOn(event.channel, event.noteNumber, event.velocity, startTime);
451
472
  break;
452
473
  case "noteOff": {
453
- const notePromise = this.scheduleNoteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
454
- if (notePromise)
455
- this.notePromises.push(notePromise);
474
+ this.noteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
456
475
  break;
457
476
  }
458
477
  case "controller":
@@ -483,6 +502,7 @@ class MidyGM1 {
483
502
  this.exclusiveClassNotes.fill(undefined);
484
503
  this.drumExclusiveClassNotes.fill(undefined);
485
504
  this.voiceCache.clear();
505
+ this.realtimeVoiceCache.clear();
486
506
  for (let i = 0; i < this.channels.length; i++) {
487
507
  this.channels[i].scheduledNotes = [];
488
508
  this.resetChannelStates(i);
@@ -520,7 +540,6 @@ class MidyGM1 {
520
540
  this.notePromises = [];
521
541
  while (queueIndex < this.timeline.length) {
522
542
  const now = this.audioContext.currentTime;
523
- queueIndex = await this.scheduleTimelineEvents(now, queueIndex);
524
543
  if (this.isPausing) {
525
544
  await this.stopNotes(0, true, now);
526
545
  await this.audioContext.suspend();
@@ -542,9 +561,16 @@ class MidyGM1 {
542
561
  this.isSeeking = false;
543
562
  continue;
544
563
  }
564
+ queueIndex = await this.scheduleTimelineEvents(now, queueIndex);
545
565
  const waitTime = now + this.noteCheckInterval;
546
566
  await this.scheduleTask(() => { }, waitTime);
547
567
  }
568
+ if (this.timeline.length <= queueIndex) {
569
+ const now = this.audioContext.currentTime;
570
+ await this.stopNotes(0, true, now);
571
+ await this.audioContext.suspend();
572
+ finished = true;
573
+ }
548
574
  if (finished) {
549
575
  this.notePromises = [];
550
576
  this.resetAllStates();
@@ -619,7 +645,7 @@ class MidyGM1 {
619
645
  const channel = this.channels[channelNumber];
620
646
  const promises = [];
621
647
  this.processActiveNotes(channel, scheduleTime, (note) => {
622
- const promise = this.scheduleNoteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force);
648
+ const promise = this.noteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force);
623
649
  this.notePromises.push(promise);
624
650
  promises.push(promise);
625
651
  });
@@ -629,7 +655,7 @@ class MidyGM1 {
629
655
  const channel = this.channels[channelNumber];
630
656
  const promises = [];
631
657
  this.processScheduledNotes(channel, (note) => {
632
- const promise = this.scheduleNoteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force);
658
+ const promise = this.noteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force);
633
659
  this.notePromises.push(promise);
634
660
  promises.push(promise);
635
661
  });
@@ -662,7 +688,7 @@ class MidyGM1 {
662
688
  if (!this.isPlaying || this.isPaused)
663
689
  return;
664
690
  const now = this.audioContext.currentTime;
665
- this.resumeTime += now - this.startTime - this.startDelay;
691
+ this.resumeTime = now - this.startTime - this.startDelay;
666
692
  this.isPausing = true;
667
693
  await this.playPromise;
668
694
  this.isPausing = false;
@@ -688,11 +714,13 @@ class MidyGM1 {
688
714
  if (totalTime < event.startTime)
689
715
  totalTime = event.startTime;
690
716
  }
691
- return totalTime;
717
+ return totalTime + this.startDelay;
692
718
  }
693
719
  currentTime() {
720
+ if (!this.isPlaying)
721
+ return this.resumeTime;
694
722
  const now = this.audioContext.currentTime;
695
- return this.resumeTime + now - this.startTime - this.startDelay;
723
+ return now + this.resumeTime - this.startTime;
696
724
  }
697
725
  processScheduledNotes(channel, callback) {
698
726
  const scheduledNotes = channel.scheduledNotes;
@@ -831,31 +859,42 @@ class MidyGM1 {
831
859
  note.modulationLFO.connect(note.volumeDepth);
832
860
  note.volumeDepth.connect(note.volumeEnvelopeNode.gain);
833
861
  }
834
- async getAudioBuffer(channel, noteNumber, velocity, voiceParams) {
862
+ async getAudioBuffer(channel, noteNumber, velocity, voiceParams, realtime) {
835
863
  const audioBufferId = this.getVoiceId(channel, noteNumber, velocity);
836
- const cache = this.voiceCache.get(audioBufferId);
837
- if (cache) {
838
- cache.counter += 1;
839
- if (cache.maxCount <= cache.counter) {
840
- this.voiceCache.delete(audioBufferId);
841
- }
842
- return cache.audioBuffer;
843
- }
844
- else {
845
- const maxCount = this.voiceCounter.get(audioBufferId) ?? 0;
864
+ if (realtime) {
865
+ const cachedAudioBuffer = this.realtimeVoiceCache.get(audioBufferId);
866
+ if (cachedAudioBuffer)
867
+ return cachedAudioBuffer;
846
868
  const audioBuffer = await this.createAudioBuffer(voiceParams);
847
- const cache = { audioBuffer, maxCount, counter: 1 };
848
- this.voiceCache.set(audioBufferId, cache);
869
+ this.realtimeVoiceCache.set(audioBufferId, audioBuffer);
849
870
  return audioBuffer;
850
871
  }
872
+ else {
873
+ const cache = this.voiceCache.get(audioBufferId);
874
+ if (cache) {
875
+ cache.counter += 1;
876
+ if (cache.maxCount <= cache.counter) {
877
+ this.voiceCache.delete(audioBufferId);
878
+ }
879
+ return cache.audioBuffer;
880
+ }
881
+ else {
882
+ const maxCount = this.voiceCounter.get(audioBufferId) ?? 0;
883
+ const audioBuffer = await this.createAudioBuffer(voiceParams);
884
+ const cache = { audioBuffer, maxCount, counter: 1 };
885
+ this.voiceCache.set(audioBufferId, cache);
886
+ return audioBuffer;
887
+ }
888
+ }
851
889
  }
852
- async createNote(channel, voice, noteNumber, velocity, startTime) {
890
+ async setNoteAudioNode(channel, note, realtime) {
853
891
  const now = this.audioContext.currentTime;
892
+ const { noteNumber, velocity, startTime } = note;
854
893
  const state = channel.state;
855
894
  const controllerState = this.getControllerState(channel, noteNumber, velocity);
856
- const voiceParams = voice.getAllParams(controllerState);
857
- const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
858
- const audioBuffer = await this.getAudioBuffer(channel, noteNumber, velocity, voiceParams);
895
+ const voiceParams = note.voice.getAllParams(controllerState);
896
+ note.voiceParams = voiceParams;
897
+ const audioBuffer = await this.getAudioBuffer(channel, noteNumber, velocity, voiceParams, realtime);
859
898
  note.bufferSource = this.createBufferSource(voiceParams, audioBuffer);
860
899
  note.volumeEnvelopeNode = new GainNode(this.audioContext);
861
900
  note.filterNode = new BiquadFilterNode(this.audioContext, {
@@ -871,7 +910,13 @@ class MidyGM1 {
871
910
  }
872
911
  note.bufferSource.connect(note.filterNode);
873
912
  note.filterNode.connect(note.volumeEnvelopeNode);
874
- note.bufferSource.start(startTime);
913
+ if (voiceParams.sample.type === "compressed") {
914
+ const offset = voiceParams.start / audioBuffer.sampleRate;
915
+ note.bufferSource.start(startTime, offset);
916
+ }
917
+ else {
918
+ note.bufferSource.start(startTime);
919
+ }
875
920
  return note;
876
921
  }
877
922
  handleExclusiveClass(note, channelNumber, startTime) {
@@ -882,14 +927,31 @@ class MidyGM1 {
882
927
  if (prev) {
883
928
  const [prevNote, prevChannelNumber] = prev;
884
929
  if (prevNote && !prevNote.ending) {
885
- this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
930
+ this.noteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
886
931
  startTime, true);
887
932
  }
888
933
  }
889
934
  this.exclusiveClassNotes[exclusiveClass] = [note, channelNumber];
890
935
  }
891
- async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
936
+ setNoteRouting(channelNumber, note, startTime) {
937
+ const channel = this.channels[channelNumber];
938
+ const volumeEnvelopeNode = note.volumeEnvelopeNode;
939
+ volumeEnvelopeNode.connect(channel.gainL);
940
+ volumeEnvelopeNode.connect(channel.gainR);
941
+ if (0.5 <= channel.state.sustainPedal) {
942
+ channel.sustainNotes.push(note);
943
+ }
944
+ this.handleExclusiveClass(note, channelNumber, startTime);
945
+ }
946
+ async noteOn(channelNumber, noteNumber, velocity, startTime) {
892
947
  const channel = this.channels[channelNumber];
948
+ const realtime = startTime === undefined;
949
+ if (realtime)
950
+ startTime = this.audioContext.currentTime;
951
+ const note = new Note(noteNumber, velocity, startTime);
952
+ const scheduledNotes = channel.scheduledNotes;
953
+ note.index = scheduledNotes.length;
954
+ scheduledNotes.push(note);
893
955
  const programNumber = channel.programNumber;
894
956
  const bankTable = this.soundFontTable[programNumber];
895
957
  if (!bankTable)
@@ -899,23 +961,16 @@ class MidyGM1 {
899
961
  if (soundFontIndex === undefined)
900
962
  return;
901
963
  const soundFont = this.soundFonts[soundFontIndex];
902
- const voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
903
- if (!voice)
964
+ note.voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
965
+ if (!note.voice)
904
966
  return;
905
- const note = await this.createNote(channel, voice, noteNumber, velocity, startTime);
906
- note.volumeEnvelopeNode.connect(channel.gainL);
907
- note.volumeEnvelopeNode.connect(channel.gainR);
908
- if (0.5 <= channel.state.sustainPedal) {
909
- channel.sustainNotes.push(note);
967
+ await this.setNoteAudioNode(channel, note, realtime);
968
+ this.setNoteRouting(channelNumber, note, startTime);
969
+ note.pending = false;
970
+ const off = note.offEvent;
971
+ if (off) {
972
+ this.noteOff(channelNumber, noteNumber, off.velocity, off.startTime);
910
973
  }
911
- this.handleExclusiveClass(note, channelNumber, startTime);
912
- const scheduledNotes = channel.scheduledNotes;
913
- note.index = scheduledNotes.length;
914
- scheduledNotes.push(note);
915
- }
916
- noteOn(channelNumber, noteNumber, velocity, scheduleTime) {
917
- scheduleTime ??= this.audioContext.currentTime;
918
- return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime, undefined);
919
974
  }
920
975
  disconnectNote(note) {
921
976
  note.bufferSource.disconnect();
@@ -928,6 +983,7 @@ class MidyGM1 {
928
983
  }
929
984
  }
930
985
  releaseNote(channel, note, endTime) {
986
+ endTime ??= this.audioContext.currentTime;
931
987
  const volRelease = endTime + note.voiceParams.volRelease;
932
988
  const modRelease = endTime + note.voiceParams.modRelease;
933
989
  const stopTime = Math.min(volRelease, modRelease);
@@ -948,7 +1004,7 @@ class MidyGM1 {
948
1004
  }, stopTime);
949
1005
  });
950
1006
  }
951
- scheduleNoteOff(channelNumber, noteNumber, _velocity, endTime, force) {
1007
+ noteOff(channelNumber, noteNumber, velocity, endTime, force) {
952
1008
  const channel = this.channels[channelNumber];
953
1009
  if (!force && 0.5 <= channel.state.sustainPedal)
954
1010
  return;
@@ -956,9 +1012,15 @@ class MidyGM1 {
956
1012
  if (index < 0)
957
1013
  return;
958
1014
  const note = channel.scheduledNotes[index];
1015
+ if (note.pending) {
1016
+ note.offEvent = { velocity, startTime: endTime };
1017
+ return;
1018
+ }
959
1019
  note.ending = true;
960
1020
  this.setNoteIndex(channel, index);
961
- this.releaseNote(channel, note, endTime);
1021
+ const promise = this.releaseNote(channel, note, endTime);
1022
+ this.notePromises.push(promise);
1023
+ return promise;
962
1024
  }
963
1025
  setNoteIndex(channel, index) {
964
1026
  let allEnds = true;
@@ -986,16 +1048,12 @@ class MidyGM1 {
986
1048
  }
987
1049
  return -1;
988
1050
  }
989
- noteOff(channelNumber, noteNumber, velocity, scheduleTime) {
990
- scheduleTime ??= this.audioContext.currentTime;
991
- return this.scheduleNoteOff(channelNumber, noteNumber, velocity, scheduleTime, false);
992
- }
993
1051
  releaseSustainPedal(channelNumber, halfVelocity, scheduleTime) {
994
1052
  const velocity = halfVelocity * 2;
995
1053
  const channel = this.channels[channelNumber];
996
1054
  const promises = [];
997
1055
  for (let i = 0; i < channel.sustainNotes.length; i++) {
998
- const promise = this.scheduleNoteOff(channelNumber, channel.sustainNotes[i].noteNumber, velocity, scheduleTime);
1056
+ const promise = this.noteOff(channelNumber, channel.sustainNotes[i].noteNumber, velocity, scheduleTime);
999
1057
  promises.push(promise);
1000
1058
  }
1001
1059
  channel.sustainNotes = [];
@@ -1060,11 +1118,12 @@ class MidyGM1 {
1060
1118
  setModLfoToPitch(channel, note, scheduleTime) {
1061
1119
  if (note.modulationDepth) {
1062
1120
  const modLfoToPitch = note.voiceParams.modLfoToPitch;
1063
- const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
1064
- const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
1121
+ const baseDepth = Math.abs(modLfoToPitch) +
1122
+ channel.state.modulationDepthMSB;
1123
+ const depth = baseDepth * Math.sign(modLfoToPitch);
1065
1124
  note.modulationDepth.gain
1066
1125
  .cancelScheduledValues(scheduleTime)
1067
- .setValueAtTime(modulationDepth, scheduleTime);
1126
+ .setValueAtTime(depth, scheduleTime);
1068
1127
  }
1069
1128
  else {
1070
1129
  this.startModulation(channel, note, scheduleTime);
@@ -1101,18 +1160,18 @@ class MidyGM1 {
1101
1160
  createVoiceParamsHandlers() {
1102
1161
  return {
1103
1162
  modLfoToPitch: (channel, note, scheduleTime) => {
1104
- if (0 < channel.state.modulationDepth) {
1163
+ if (0 < channel.state.modulationDepthMSB) {
1105
1164
  this.setModLfoToPitch(channel, note, scheduleTime);
1106
1165
  }
1107
1166
  },
1108
1167
  vibLfoToPitch: (_channel, _note, _scheduleTime) => { },
1109
1168
  modLfoToFilterFc: (channel, note, scheduleTime) => {
1110
- if (0 < channel.state.modulationDepth) {
1169
+ if (0 < channel.state.modulationDepthMSB) {
1111
1170
  this.setModLfoToFilterFc(note, scheduleTime);
1112
1171
  }
1113
1172
  },
1114
1173
  modLfoToVolume: (channel, note, scheduleTime) => {
1115
- if (0 < channel.state.modulationDepth) {
1174
+ if (0 < channel.state.modulationDepthMSB) {
1116
1175
  this.setModLfoToVolume(note, scheduleTime);
1117
1176
  }
1118
1177
  },
@@ -1124,7 +1183,7 @@ class MidyGM1 {
1124
1183
  }
1125
1184
  },
1126
1185
  freqModLFO: (_channel, note, scheduleTime) => {
1127
- if (0 < channel.state.modulationDepth) {
1186
+ if (0 < channel.state.modulationDepthMSB) {
1128
1187
  this.setFreqModLFO(note, scheduleTime);
1129
1188
  }
1130
1189
  },
@@ -1199,7 +1258,8 @@ class MidyGM1 {
1199
1258
  }
1200
1259
  }
1201
1260
  updateModulation(channel, scheduleTime) {
1202
- const depth = channel.state.modulationDepth * channel.modulationDepthRange;
1261
+ const depth = channel.state.modulationDepthMSB *
1262
+ channel.modulationDepthRange;
1203
1263
  this.processScheduledNotes(channel, (note) => {
1204
1264
  if (note.modulationDepth) {
1205
1265
  note.modulationDepth.gain.setValueAtTime(depth, scheduleTime);
@@ -1212,13 +1272,13 @@ class MidyGM1 {
1212
1272
  setModulationDepth(channelNumber, modulation, scheduleTime) {
1213
1273
  const channel = this.channels[channelNumber];
1214
1274
  scheduleTime ??= this.audioContext.currentTime;
1215
- channel.state.modulationDepth = modulation / 127;
1275
+ channel.state.modulationDepthMSB = modulation / 127;
1216
1276
  this.updateModulation(channel, scheduleTime);
1217
1277
  }
1218
1278
  setVolume(channelNumber, volume, scheduleTime) {
1219
1279
  scheduleTime ??= this.audioContext.currentTime;
1220
1280
  const channel = this.channels[channelNumber];
1221
- channel.state.volume = volume / 127;
1281
+ channel.state.volumeMSB = volume / 127;
1222
1282
  this.updateChannelVolume(channel, scheduleTime);
1223
1283
  }
1224
1284
  panToGain(pan) {
@@ -1231,13 +1291,13 @@ class MidyGM1 {
1231
1291
  setPan(channelNumber, pan, scheduleTime) {
1232
1292
  scheduleTime ??= this.audioContext.currentTime;
1233
1293
  const channel = this.channels[channelNumber];
1234
- channel.state.pan = pan / 127;
1294
+ channel.state.panMSB = pan / 127;
1235
1295
  this.updateChannelVolume(channel, scheduleTime);
1236
1296
  }
1237
1297
  setExpression(channelNumber, expression, scheduleTime) {
1238
1298
  scheduleTime ??= this.audioContext.currentTime;
1239
1299
  const channel = this.channels[channelNumber];
1240
- channel.state.expression = expression / 127;
1300
+ channel.state.expressionMSB = expression / 127;
1241
1301
  this.updateChannelVolume(channel, scheduleTime);
1242
1302
  }
1243
1303
  dataEntryLSB(channelNumber, value, scheduleTime) {
@@ -1246,8 +1306,8 @@ class MidyGM1 {
1246
1306
  }
1247
1307
  updateChannelVolume(channel, scheduleTime) {
1248
1308
  const state = channel.state;
1249
- const volume = state.volume * state.expression;
1250
- const { gainLeft, gainRight } = this.panToGain(state.pan);
1309
+ const volume = state.volumeMSB * state.expressionMSB;
1310
+ const { gainLeft, gainRight } = this.panToGain(state.panMSB);
1251
1311
  channel.gainL.gain
1252
1312
  .cancelScheduledValues(scheduleTime)
1253
1313
  .setValueAtTime(volume * gainLeft, scheduleTime);
@@ -1395,8 +1455,8 @@ class MidyGM1 {
1395
1455
  resetAllControllers(channelNumber, _value, scheduleTime) {
1396
1456
  const keys = [
1397
1457
  "pitchWheel",
1398
- "expression",
1399
- "modulationDepth",
1458
+ "expressionMSB",
1459
+ "modulationDepthMSB",
1400
1460
  "sustainPedal",
1401
1461
  ];
1402
1462
  const channel = this.channels[channelNumber];
@@ -44,6 +44,7 @@ export class MidyGM2 {
44
44
  soundFontTable: never[][];
45
45
  voiceCounter: Map<any, any>;
46
46
  voiceCache: Map<any, any>;
47
+ realtimeVoiceCache: Map<any, any>;
47
48
  isPlaying: boolean;
48
49
  isPausing: boolean;
49
50
  isPaused: boolean;
@@ -173,20 +174,19 @@ export class MidyGM2 {
173
174
  setFilterEnvelope(channel: any, note: any, scheduleTime: any): void;
174
175
  startModulation(channel: any, note: any, scheduleTime: any): void;
175
176
  startVibrato(channel: any, note: any, scheduleTime: any): void;
176
- getAudioBuffer(channel: any, noteNumber: any, velocity: any, voiceParams: any): Promise<any>;
177
- createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any): Promise<Note>;
177
+ getAudioBuffer(channel: any, noteNumber: any, velocity: any, voiceParams: any, realtime: any): Promise<any>;
178
+ setNoteAudioNode(channel: any, note: any, realtime: any): Promise<any>;
178
179
  handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
179
180
  handleDrumExclusiveClass(note: any, channelNumber: any, startTime: any): void;
180
- scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
181
- noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
181
+ setNoteRouting(channelNumber: any, note: any, startTime: any): void;
182
+ noteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
182
183
  disconnectNote(note: any): void;
183
184
  releaseNote(channel: any, note: any, endTime: any): Promise<any>;
184
- scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): void;
185
+ noteOff(channelNumber: any, noteNumber: any, velocity: any, endTime: any, force: any): Promise<any> | undefined;
185
186
  setNoteIndex(channel: any, index: any): void;
186
187
  findNoteOffIndex(channel: any, noteNumber: any): any;
187
- noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): void;
188
- releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
189
- releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
188
+ releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
189
+ releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
190
190
  createMessageHandlers(): any[];
191
191
  handleMessage(data: any, scheduleTime: any): void;
192
192
  activeSensing(): void;
@@ -312,27 +312,4 @@ export class MidyGM2 {
312
312
  handleSysEx(data: any, scheduleTime: any): void;
313
313
  scheduleTask(callback: any, scheduleTime: any): Promise<any>;
314
314
  }
315
- declare class Note {
316
- constructor(noteNumber: any, velocity: any, startTime: any, voice: any, voiceParams: any);
317
- index: number;
318
- ending: boolean;
319
- bufferSource: any;
320
- filterNode: any;
321
- filterDepth: any;
322
- volumeEnvelopeNode: any;
323
- volumeDepth: any;
324
- modulationLFO: any;
325
- modulationDepth: any;
326
- vibratoLFO: any;
327
- vibratoDepth: any;
328
- reverbSend: any;
329
- chorusSend: any;
330
- portamentoNoteNumber: number;
331
- noteNumber: any;
332
- velocity: any;
333
- startTime: any;
334
- voice: any;
335
- voiceParams: any;
336
- }
337
- export {};
338
315
  //# sourceMappingURL=midy-GM2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}