@marmooo/midy 0.3.8 → 0.4.0

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.d.ts CHANGED
@@ -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,17 +105,16 @@ 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): void;
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
118
  releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
119
119
  createMessageHandlers(): any[];
120
120
  handleMessage(data: 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,kDAUC;IAED,4DASC;IAED,yEAqDC;IAED,mCAOC;IAED,uBASC;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,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,uEAmCC;IAED,0EAiBC;IAED,oEASC;IAED,0FAwBC;IAED,gCASC;IAED,iEAqBC;IAED,4FAmBC;IAED,6CAUC;IAED,qDAUC;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"}
package/esm/midy-GM1.js CHANGED
@@ -1,7 +1,19 @@
1
1
  import { parseMidi } from "midi-file";
2
2
  import { parse, SoundFont } from "@marmooo/soundfont-parser";
3
3
  class Note {
4
- constructor(noteNumber, velocity, startTime, voice, voiceParams) {
4
+ constructor(noteNumber, velocity, startTime) {
5
+ Object.defineProperty(this, "voice", {
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true,
9
+ value: void 0
10
+ });
11
+ Object.defineProperty(this, "voiceParams", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: void 0
16
+ });
5
17
  Object.defineProperty(this, "index", {
6
18
  enumerable: true,
7
19
  configurable: true,
@@ -14,6 +26,12 @@ class Note {
14
26
  writable: true,
15
27
  value: false
16
28
  });
29
+ Object.defineProperty(this, "pending", {
30
+ enumerable: true,
31
+ configurable: true,
32
+ writable: true,
33
+ value: true
34
+ });
17
35
  Object.defineProperty(this, "bufferSource", {
18
36
  enumerable: true,
19
37
  configurable: true,
@@ -59,8 +77,6 @@ class Note {
59
77
  this.noteNumber = noteNumber;
60
78
  this.velocity = velocity;
61
79
  this.startTime = startTime;
62
- this.voice = voice;
63
- this.voiceParams = voiceParams;
64
80
  }
65
81
  }
66
82
  // normalized to 0-1 for use with the SF2 modulator model
@@ -214,6 +230,12 @@ export class MidyGM1 {
214
230
  writable: true,
215
231
  value: new Map()
216
232
  });
233
+ Object.defineProperty(this, "realtimeVoiceCache", {
234
+ enumerable: true,
235
+ configurable: true,
236
+ writable: true,
237
+ value: new Map()
238
+ });
217
239
  Object.defineProperty(this, "isPlaying", {
218
240
  enumerable: true,
219
241
  configurable: true,
@@ -444,10 +466,10 @@ export class MidyGM1 {
444
466
  const startTime = event.startTime + schedulingOffset;
445
467
  switch (event.type) {
446
468
  case "noteOn":
447
- await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, startTime);
469
+ await this.noteOn(event.channel, event.noteNumber, event.velocity, startTime);
448
470
  break;
449
471
  case "noteOff": {
450
- const notePromise = this.scheduleNoteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
472
+ const notePromise = this.noteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
451
473
  if (notePromise)
452
474
  this.notePromises.push(notePromise);
453
475
  break;
@@ -480,6 +502,7 @@ export class MidyGM1 {
480
502
  this.exclusiveClassNotes.fill(undefined);
481
503
  this.drumExclusiveClassNotes.fill(undefined);
482
504
  this.voiceCache.clear();
505
+ this.realtimeVoiceCache.clear();
483
506
  for (let i = 0; i < this.channels.length; i++) {
484
507
  this.channels[i].scheduledNotes = [];
485
508
  this.resetChannelStates(i);
@@ -517,7 +540,6 @@ export class MidyGM1 {
517
540
  this.notePromises = [];
518
541
  while (queueIndex < this.timeline.length) {
519
542
  const now = this.audioContext.currentTime;
520
- queueIndex = await this.scheduleTimelineEvents(now, queueIndex);
521
543
  if (this.isPausing) {
522
544
  await this.stopNotes(0, true, now);
523
545
  await this.audioContext.suspend();
@@ -539,6 +561,7 @@ export class MidyGM1 {
539
561
  this.isSeeking = false;
540
562
  continue;
541
563
  }
564
+ queueIndex = await this.scheduleTimelineEvents(now, queueIndex);
542
565
  const waitTime = now + this.noteCheckInterval;
543
566
  await this.scheduleTask(() => { }, waitTime);
544
567
  }
@@ -616,7 +639,7 @@ export class MidyGM1 {
616
639
  const channel = this.channels[channelNumber];
617
640
  const promises = [];
618
641
  this.processActiveNotes(channel, scheduleTime, (note) => {
619
- const promise = this.scheduleNoteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force);
642
+ const promise = this.noteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force);
620
643
  this.notePromises.push(promise);
621
644
  promises.push(promise);
622
645
  });
@@ -626,7 +649,7 @@ export class MidyGM1 {
626
649
  const channel = this.channels[channelNumber];
627
650
  const promises = [];
628
651
  this.processScheduledNotes(channel, (note) => {
629
- const promise = this.scheduleNoteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force);
652
+ const promise = this.noteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force);
630
653
  this.notePromises.push(promise);
631
654
  promises.push(promise);
632
655
  });
@@ -659,7 +682,7 @@ export class MidyGM1 {
659
682
  if (!this.isPlaying || this.isPaused)
660
683
  return;
661
684
  const now = this.audioContext.currentTime;
662
- this.resumeTime += now - this.startTime - this.startDelay;
685
+ this.resumeTime = now - this.startTime - this.startDelay;
663
686
  this.isPausing = true;
664
687
  await this.playPromise;
665
688
  this.isPausing = false;
@@ -685,11 +708,13 @@ export class MidyGM1 {
685
708
  if (totalTime < event.startTime)
686
709
  totalTime = event.startTime;
687
710
  }
688
- return totalTime;
711
+ return totalTime + this.startDelay;
689
712
  }
690
713
  currentTime() {
714
+ if (!this.isPlaying)
715
+ return this.resumeTime;
691
716
  const now = this.audioContext.currentTime;
692
- return this.resumeTime + now - this.startTime - this.startDelay;
717
+ return now + this.resumeTime - this.startTime;
693
718
  }
694
719
  processScheduledNotes(channel, callback) {
695
720
  const scheduledNotes = channel.scheduledNotes;
@@ -828,31 +853,42 @@ export class MidyGM1 {
828
853
  note.modulationLFO.connect(note.volumeDepth);
829
854
  note.volumeDepth.connect(note.volumeEnvelopeNode.gain);
830
855
  }
831
- async getAudioBuffer(channel, noteNumber, velocity, voiceParams) {
856
+ async getAudioBuffer(channel, noteNumber, velocity, voiceParams, realtime) {
832
857
  const audioBufferId = this.getVoiceId(channel, noteNumber, velocity);
833
- const cache = this.voiceCache.get(audioBufferId);
834
- if (cache) {
835
- cache.counter += 1;
836
- if (cache.maxCount <= cache.counter) {
837
- this.voiceCache.delete(audioBufferId);
838
- }
839
- return cache.audioBuffer;
840
- }
841
- else {
842
- const maxCount = this.voiceCounter.get(audioBufferId) ?? 0;
858
+ if (realtime) {
859
+ const cachedAudioBuffer = this.realtimeVoiceCache.get(audioBufferId);
860
+ if (cachedAudioBuffer)
861
+ return cachedAudioBuffer;
843
862
  const audioBuffer = await this.createAudioBuffer(voiceParams);
844
- const cache = { audioBuffer, maxCount, counter: 1 };
845
- this.voiceCache.set(audioBufferId, cache);
863
+ this.realtimeVoiceCache.set(audioBufferId, audioBuffer);
846
864
  return audioBuffer;
847
865
  }
866
+ else {
867
+ const cache = this.voiceCache.get(audioBufferId);
868
+ if (cache) {
869
+ cache.counter += 1;
870
+ if (cache.maxCount <= cache.counter) {
871
+ this.voiceCache.delete(audioBufferId);
872
+ }
873
+ return cache.audioBuffer;
874
+ }
875
+ else {
876
+ const maxCount = this.voiceCounter.get(audioBufferId) ?? 0;
877
+ const audioBuffer = await this.createAudioBuffer(voiceParams);
878
+ const cache = { audioBuffer, maxCount, counter: 1 };
879
+ this.voiceCache.set(audioBufferId, cache);
880
+ return audioBuffer;
881
+ }
882
+ }
848
883
  }
849
- async createNote(channel, voice, noteNumber, velocity, startTime) {
884
+ async setNoteAudioNode(channel, note, realtime) {
850
885
  const now = this.audioContext.currentTime;
886
+ const { noteNumber, velocity, startTime } = note;
851
887
  const state = channel.state;
852
888
  const controllerState = this.getControllerState(channel, noteNumber, velocity);
853
- const voiceParams = voice.getAllParams(controllerState);
854
- const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
855
- const audioBuffer = await this.getAudioBuffer(channel, noteNumber, velocity, voiceParams);
889
+ const voiceParams = note.voice.getAllParams(controllerState);
890
+ note.voiceParams = voiceParams;
891
+ const audioBuffer = await this.getAudioBuffer(channel, noteNumber, velocity, voiceParams, realtime);
856
892
  note.bufferSource = this.createBufferSource(voiceParams, audioBuffer);
857
893
  note.volumeEnvelopeNode = new GainNode(this.audioContext);
858
894
  note.filterNode = new BiquadFilterNode(this.audioContext, {
@@ -879,14 +915,31 @@ export class MidyGM1 {
879
915
  if (prev) {
880
916
  const [prevNote, prevChannelNumber] = prev;
881
917
  if (prevNote && !prevNote.ending) {
882
- this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
918
+ this.noteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
883
919
  startTime, true);
884
920
  }
885
921
  }
886
922
  this.exclusiveClassNotes[exclusiveClass] = [note, channelNumber];
887
923
  }
888
- async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
924
+ setNoteRouting(channelNumber, note, startTime) {
889
925
  const channel = this.channels[channelNumber];
926
+ const volumeEnvelopeNode = note.volumeEnvelopeNode;
927
+ volumeEnvelopeNode.connect(channel.gainL);
928
+ volumeEnvelopeNode.connect(channel.gainR);
929
+ if (0.5 <= channel.state.sustainPedal) {
930
+ channel.sustainNotes.push(note);
931
+ }
932
+ this.handleExclusiveClass(note, channelNumber, startTime);
933
+ }
934
+ async noteOn(channelNumber, noteNumber, velocity, startTime) {
935
+ const channel = this.channels[channelNumber];
936
+ const realtime = startTime === undefined;
937
+ if (realtime)
938
+ startTime = this.audioContext.currentTime;
939
+ const note = new Note(noteNumber, velocity, startTime);
940
+ const scheduledNotes = channel.scheduledNotes;
941
+ note.index = scheduledNotes.length;
942
+ scheduledNotes.push(note);
890
943
  const programNumber = channel.programNumber;
891
944
  const bankTable = this.soundFontTable[programNumber];
892
945
  if (!bankTable)
@@ -896,23 +949,16 @@ export class MidyGM1 {
896
949
  if (soundFontIndex === undefined)
897
950
  return;
898
951
  const soundFont = this.soundFonts[soundFontIndex];
899
- const voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
900
- if (!voice)
952
+ note.voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
953
+ if (!note.voice)
901
954
  return;
902
- const note = await this.createNote(channel, voice, noteNumber, velocity, startTime);
903
- note.volumeEnvelopeNode.connect(channel.gainL);
904
- note.volumeEnvelopeNode.connect(channel.gainR);
905
- if (0.5 <= channel.state.sustainPedal) {
906
- channel.sustainNotes.push(note);
955
+ await this.setNoteAudioNode(channel, note, realtime);
956
+ this.setNoteRouting(channelNumber, note, startTime);
957
+ note.pending = false;
958
+ const off = note.offEvent;
959
+ if (off) {
960
+ this.noteOff(channelNumber, noteNumber, off.velocity, off.startTime);
907
961
  }
908
- this.handleExclusiveClass(note, channelNumber, startTime);
909
- const scheduledNotes = channel.scheduledNotes;
910
- note.index = scheduledNotes.length;
911
- scheduledNotes.push(note);
912
- }
913
- noteOn(channelNumber, noteNumber, velocity, scheduleTime) {
914
- scheduleTime ??= this.audioContext.currentTime;
915
- return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime, undefined);
916
962
  }
917
963
  disconnectNote(note) {
918
964
  note.bufferSource.disconnect();
@@ -925,6 +971,7 @@ export class MidyGM1 {
925
971
  }
926
972
  }
927
973
  releaseNote(channel, note, endTime) {
974
+ endTime ??= this.audioContext.currentTime;
928
975
  const volRelease = endTime + note.voiceParams.volRelease;
929
976
  const modRelease = endTime + note.voiceParams.modRelease;
930
977
  const stopTime = Math.min(volRelease, modRelease);
@@ -945,7 +992,7 @@ export class MidyGM1 {
945
992
  }, stopTime);
946
993
  });
947
994
  }
948
- scheduleNoteOff(channelNumber, noteNumber, _velocity, endTime, force) {
995
+ noteOff(channelNumber, noteNumber, velocity, endTime, force) {
949
996
  const channel = this.channels[channelNumber];
950
997
  if (!force && 0.5 <= channel.state.sustainPedal)
951
998
  return;
@@ -953,6 +1000,10 @@ export class MidyGM1 {
953
1000
  if (index < 0)
954
1001
  return;
955
1002
  const note = channel.scheduledNotes[index];
1003
+ if (note.pending) {
1004
+ note.offEvent = { velocity, startTime: endTime };
1005
+ return;
1006
+ }
956
1007
  note.ending = true;
957
1008
  this.setNoteIndex(channel, index);
958
1009
  this.releaseNote(channel, note, endTime);
@@ -983,16 +1034,12 @@ export class MidyGM1 {
983
1034
  }
984
1035
  return -1;
985
1036
  }
986
- noteOff(channelNumber, noteNumber, velocity, scheduleTime) {
987
- scheduleTime ??= this.audioContext.currentTime;
988
- return this.scheduleNoteOff(channelNumber, noteNumber, velocity, scheduleTime, false);
989
- }
990
1037
  releaseSustainPedal(channelNumber, halfVelocity, scheduleTime) {
991
1038
  const velocity = halfVelocity * 2;
992
1039
  const channel = this.channels[channelNumber];
993
1040
  const promises = [];
994
1041
  for (let i = 0; i < channel.sustainNotes.length; i++) {
995
- const promise = this.scheduleNoteOff(channelNumber, channel.sustainNotes[i].noteNumber, velocity, scheduleTime);
1042
+ const promise = this.noteOff(channelNumber, channel.sustainNotes[i].noteNumber, velocity, scheduleTime);
996
1043
  promises.push(promise);
997
1044
  }
998
1045
  channel.sustainNotes = [];
package/esm/midy-GM2.d.ts CHANGED
@@ -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,18 +174,17 @@ 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): void;
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
188
  releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
189
189
  releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
190
190
  createMessageHandlers(): any[];
@@ -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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"}