@marmooo/midy 0.2.9 → 0.3.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
@@ -1,9 +1,7 @@
1
1
  export class MidyGM1 {
2
2
  static channelSettings: {
3
- currentBufferSource: null;
4
- isDrum: boolean;
5
3
  detune: number;
6
- program: number;
4
+ programNumber: number;
7
5
  bank: number;
8
6
  dataMSB: number;
9
7
  dataLSB: number;
@@ -15,6 +13,7 @@ export class MidyGM1 {
15
13
  };
16
14
  constructor(audioContext: any);
17
15
  mode: string;
16
+ numChannels: number;
18
17
  ticksPerBeat: number;
19
18
  totalTime: number;
20
19
  noteCheckInterval: number;
@@ -34,7 +33,7 @@ export class MidyGM1 {
34
33
  timeline: any[];
35
34
  instruments: any[];
36
35
  notePromises: any[];
37
- exclusiveClassMap: SparseMap;
36
+ exclusiveClassNotes: any[];
38
37
  audioContext: any;
39
38
  masterVolume: any;
40
39
  scheduler: any;
@@ -112,16 +111,18 @@ export class MidyGM1 {
112
111
  clampCutoffFrequency(frequency: any): number;
113
112
  setFilterEnvelope(note: any, scheduleTime: any): void;
114
113
  startModulation(channel: any, note: any, scheduleTime: any): void;
115
- getAudioBuffer(program: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
114
+ getAudioBuffer(programNumber: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
116
115
  createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
116
+ handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
117
117
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
118
118
  noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
119
+ disconnectNote(note: any, scheduledNotes: any, index: any): void;
119
120
  stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
120
121
  scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): Promise<any> | undefined;
121
122
  noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
122
123
  releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
123
124
  handleMIDIMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
124
- handleProgramChange(channelNumber: any, program: any, _scheduleTime: any): void;
125
+ handleProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
125
126
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
126
127
  setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
127
128
  setModLfoToPitch(channel: any, note: any, scheduleTime: any): void;
@@ -183,6 +184,7 @@ export class MidyGM1 {
183
184
  handleCoarseTuningRPN(channelNumber: any, scheduleTime: any): void;
184
185
  setCoarseTuning(channelNumber: any, value: any, scheduleTime: any): void;
185
186
  allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
187
+ resetAllStates(channelNumber: any): void;
186
188
  resetAllControllers(channelNumber: any): void;
187
189
  allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
188
190
  handleUniversalNonRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAiJA;IAuBE;;;;;;;;;;;;;MAaE;IAEF,+BAcC;IAnDD,aAAa;IACb,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,kCAA+B;IAC/B,gCAA6B;IAC7B,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAClB,6BAAuC;IAkBrC,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAMnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAWC;IAED,6DA2BC;IAED,4DASC;IAED,2EAsDC;IAED,mCAOC;IAED,0BAoDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MA4EC;IAED,mGAgBC;IAED,wEAMC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,2DASC;IAED,qDAQC;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,yGAgBC;IAED,gHAwCC;IAED,kGAkDC;IAED,6FAQC;IAED,qFAwBC;IAED,yHAuBC;IAED,yGASC;IAED,4GAeC;IAED,mGA2BC;IAED,gFAGC;IAED,wFAGC;IAED,sEAWC;IAED,mEAQC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MA2BC;IAED,oFAMC;IAED,6EA2CC;IAED;;;;;;;;;;;;;MAeC;IAED,kGAWC;IAED,wDAUC;IAED,iFAMC;IAED,oEAKC;IAED;;;MAMC;IAED,8DAKC;IAED,4EAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAYC;IAED,kFAeC;IAED,2DAMC;IAED,uDAkBC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAWC;IAED,iEAKC;IAED,uEASC;IAED,mEAKC;IAED,yEASC;IAED,gFAGC;IAED,8CAqBC;IAED,gFAGC;IAED,+EAgBC;IAED,qCAWC;IAED,4EAaC;IAED,4DAGC;IAED,sDASC;IAED,gDAYC;IAED,6DAgBC;CACF;AA97CD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IASE,0FAMC;IAdD,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":"AAiJA;IAwBE;;;;;;;;;;;MAWE;IAEF,+BAcC;IAlDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,kCAA+B;IAC/B,gCAA6B;IAC7B,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAClB,2BAAqC;IAgBnC,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAMnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAaC;IAED,6DA2BC;IAED,4DASC;IAED,2EAsDC;IAED,mCAOC;IAED,0BAoDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MA4EC;IAED,mGAgBC;IAED,wEAMC;IAED,uBAKC;IAED,aAMC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,2DASC;IAED,qDAQC;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,+GA0BC;IAED,gHAwCC;IAED,0EAiBC;IAED,kGAqCC;IAED,6FAQC;IAED,iEAUC;IAED,qFAgBC;IAED,yHAuBC;IAED,yGASC;IAED,4GAeC;IAED,mGA2BC;IAED,sFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAQC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MA2BC;IAED,oFAMC;IAED,6EA2CC;IAED;;;;;;;;;;;;;MAeC;IAED,kGAWC;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,iEAKC;IAED,uEAQC;IAED,mEAKC;IAED,yEAQC;IAED,gFAGC;IAED,yCAUC;IAGD,8CAqBC;IAED,gFAGC;IAED,+EAgBC;IAED,qCAWC;IAED,4EAaC;IAED,4DAGC;IAED,sDASC;IAED,gDAYC;IAGD,6DAgBC;CACF;AA99CD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IASE,0FAMC;IAdD,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
package/esm/midy-GM1.js CHANGED
@@ -176,6 +176,12 @@ export class MidyGM1 {
176
176
  writable: true,
177
177
  value: "GM1"
178
178
  });
179
+ Object.defineProperty(this, "numChannels", {
180
+ enumerable: true,
181
+ configurable: true,
182
+ writable: true,
183
+ value: 16
184
+ });
179
185
  Object.defineProperty(this, "ticksPerBeat", {
180
186
  enumerable: true,
181
187
  configurable: true,
@@ -290,11 +296,11 @@ export class MidyGM1 {
290
296
  writable: true,
291
297
  value: []
292
298
  });
293
- Object.defineProperty(this, "exclusiveClassMap", {
299
+ Object.defineProperty(this, "exclusiveClassNotes", {
294
300
  enumerable: true,
295
301
  configurable: true,
296
302
  writable: true,
297
- value: new SparseMap(128)
303
+ value: new Array(128)
298
304
  });
299
305
  this.audioContext = audioContext;
300
306
  this.masterVolume = new GainNode(audioContext);
@@ -361,8 +367,10 @@ export class MidyGM1 {
361
367
  };
362
368
  }
363
369
  createChannels(audioContext) {
364
- const channels = Array.from({ length: 16 }, () => {
370
+ const channels = Array.from({ length: this.numChannels }, () => {
365
371
  return {
372
+ currentBufferSource: null,
373
+ isDrum: false,
366
374
  ...this.constructor.channelSettings,
367
375
  state: new ControllerState(),
368
376
  ...this.setChannelAudioNodes(audioContext),
@@ -467,7 +475,7 @@ export class MidyGM1 {
467
475
  if (queueIndex >= this.timeline.length) {
468
476
  await Promise.all(this.notePromises);
469
477
  this.notePromises = [];
470
- this.exclusiveClassMap.clear();
478
+ this.exclusiveClassNotes.flll(undefined);
471
479
  this.audioBufferCache.clear();
472
480
  resolve();
473
481
  return;
@@ -486,7 +494,7 @@ export class MidyGM1 {
486
494
  else if (this.isStopping) {
487
495
  await this.stopNotes(0, true, now);
488
496
  this.notePromises = [];
489
- this.exclusiveClassMap.clear();
497
+ this.exclusiveClassNotes.fill(undefined);
490
498
  this.audioBufferCache.clear();
491
499
  resolve();
492
500
  this.isStopping = false;
@@ -495,7 +503,7 @@ export class MidyGM1 {
495
503
  }
496
504
  else if (this.isSeeking) {
497
505
  this.stopNotes(0, true, now);
498
- this.exclusiveClassMap.clear();
506
+ this.exclusiveClassNotes.fill(undefined);
499
507
  this.startTime = this.audioContext.currentTime;
500
508
  queueIndex = this.getQueueIndex(this.resumeTime);
501
509
  offset = this.resumeTime - this.startTime;
@@ -523,7 +531,7 @@ export class MidyGM1 {
523
531
  extractMidiData(midi) {
524
532
  const instruments = new Set();
525
533
  const timeline = [];
526
- const tmpChannels = new Array(16);
534
+ const tmpChannels = new Array(this.channels.length);
527
535
  for (let i = 0; i < tmpChannels.length; i++) {
528
536
  tmpChannels[i] = {
529
537
  programNumber: -1,
@@ -615,6 +623,9 @@ export class MidyGM1 {
615
623
  if (!this.isPlaying)
616
624
  return;
617
625
  this.isStopping = true;
626
+ for (let i = 0; i < this.channels.length; i++) {
627
+ this.resetAllStates(i);
628
+ }
618
629
  }
619
630
  pause() {
620
631
  if (!this.isPlaying || this.isPaused)
@@ -792,8 +803,8 @@ export class MidyGM1 {
792
803
  note.modulationLFO.connect(note.volumeDepth);
793
804
  note.volumeDepth.connect(note.volumeEnvelopeNode.gain);
794
805
  }
795
- async getAudioBuffer(program, noteNumber, velocity, voiceParams, isSF3) {
796
- const audioBufferId = this.getAudioBufferId(program, noteNumber, velocity);
806
+ async getAudioBuffer(programNumber, noteNumber, velocity, voiceParams, isSF3) {
807
+ const audioBufferId = this.getAudioBufferId(programNumber, noteNumber, velocity);
797
808
  const cache = this.audioBufferCache.get(audioBufferId);
798
809
  if (cache) {
799
810
  cache.counter += 1;
@@ -816,7 +827,7 @@ export class MidyGM1 {
816
827
  const controllerState = this.getControllerState(channel, noteNumber, velocity);
817
828
  const voiceParams = voice.getAllParams(controllerState);
818
829
  const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
819
- const audioBuffer = await this.getAudioBuffer(channel.program, noteNumber, velocity, voiceParams, isSF3);
830
+ const audioBuffer = await this.getAudioBuffer(channel.programNumber, noteNumber, velocity, voiceParams, isSF3);
820
831
  note.bufferSource = this.createBufferSource(audioBuffer, voiceParams);
821
832
  note.volumeEnvelopeNode = new GainNode(this.audioContext);
822
833
  note.filterNode = new BiquadFilterNode(this.audioContext, {
@@ -834,14 +845,28 @@ export class MidyGM1 {
834
845
  note.bufferSource.start(startTime);
835
846
  return note;
836
847
  }
848
+ handleExclusiveClass(note, channelNumber, startTime) {
849
+ const exclusiveClass = note.voiceParams.exclusiveClass;
850
+ if (exclusiveClass === 0)
851
+ return;
852
+ const prev = this.exclusiveClassNotes[exclusiveClass];
853
+ if (prev) {
854
+ const [prevNote, prevChannelNumber] = prev;
855
+ if (prevNote && !prevNote.ending) {
856
+ this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
857
+ startTime, true);
858
+ }
859
+ }
860
+ this.exclusiveClassNotes[exclusiveClass] = [note, channelNumber];
861
+ }
837
862
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
838
863
  const channel = this.channels[channelNumber];
839
864
  const bankNumber = channel.bank;
840
- const soundFontIndex = this.soundFontTable[channel.program].get(bankNumber);
865
+ const soundFontIndex = this.soundFontTable[channel.programNumber].get(bankNumber);
841
866
  if (soundFontIndex === undefined)
842
867
  return;
843
868
  const soundFont = this.soundFonts[soundFontIndex];
844
- const voice = soundFont.getVoice(bankNumber, channel.program, noteNumber, velocity);
869
+ const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
845
870
  if (!voice)
846
871
  return;
847
872
  const isSF3 = soundFont.parsed.info.version.major === 3;
@@ -851,30 +876,31 @@ export class MidyGM1 {
851
876
  if (0.5 <= channel.state.sustainPedal) {
852
877
  channel.sustainNotes.push(note);
853
878
  }
854
- const exclusiveClass = note.voiceParams.exclusiveClass;
855
- if (exclusiveClass !== 0) {
856
- if (this.exclusiveClassMap.has(exclusiveClass)) {
857
- const prevEntry = this.exclusiveClassMap.get(exclusiveClass);
858
- const [prevNote, prevChannelNumber] = prevEntry;
859
- if (prevNote && !prevNote.ending) {
860
- this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
861
- startTime, true);
862
- }
863
- }
864
- this.exclusiveClassMap.set(exclusiveClass, [note, channelNumber]);
865
- }
866
- const scheduledNotes = channel.scheduledNotes;
867
- if (scheduledNotes.has(noteNumber)) {
868
- scheduledNotes.get(noteNumber).push(note);
879
+ this.handleExclusiveClass(note, channelNumber, startTime);
880
+ let notes = scheduledNotes.get(noteNumber);
881
+ if (notes) {
882
+ notes.push(note);
869
883
  }
870
884
  else {
871
- scheduledNotes.set(noteNumber, [note]);
885
+ notes = [note];
886
+ scheduledNotes.set(noteNumber, notes);
872
887
  }
873
888
  }
874
889
  noteOn(channelNumber, noteNumber, velocity, scheduleTime) {
875
890
  scheduleTime ??= this.audioContext.currentTime;
876
891
  return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime);
877
892
  }
893
+ disconnectNote(note, scheduledNotes, index) {
894
+ scheduledNotes[index] = null;
895
+ note.bufferSource.disconnect();
896
+ note.filterNode.disconnect();
897
+ note.volumeEnvelopeNode.disconnect();
898
+ if (note.modulationDepth) {
899
+ note.volumeDepth.disconnect();
900
+ note.modulationDepth.disconnect();
901
+ note.modulationLFO.stop();
902
+ }
903
+ }
878
904
  stopNote(endTime, stopTime, scheduledNotes, index) {
879
905
  const note = scheduledNotes[index];
880
906
  note.volumeEnvelopeNode.gain
@@ -886,15 +912,7 @@ export class MidyGM1 {
886
912
  }, stopTime);
887
913
  return new Promise((resolve) => {
888
914
  note.bufferSource.onended = () => {
889
- scheduledNotes[index] = null;
890
- note.bufferSource.disconnect();
891
- note.filterNode.disconnect();
892
- note.volumeEnvelopeNode.disconnect();
893
- if (note.modulationDepth) {
894
- note.volumeDepth.disconnect();
895
- note.modulationDepth.disconnect();
896
- note.modulationLFO.stop();
897
- }
915
+ this.disconnectNote(note, scheduledNotes, index);
898
916
  resolve();
899
917
  };
900
918
  note.bufferSource.stop(stopTime);
@@ -955,9 +973,9 @@ export class MidyGM1 {
955
973
  console.warn(`Unsupported MIDI message: ${messageType.toString(16)}`);
956
974
  }
957
975
  }
958
- handleProgramChange(channelNumber, program, _scheduleTime) {
976
+ handleProgramChange(channelNumber, programNumber, _scheduleTime) {
959
977
  const channel = this.channels[channelNumber];
960
- channel.program = program;
978
+ channel.programNumber = programNumber;
961
979
  }
962
980
  handlePitchBendMessage(channelNumber, lsb, msb, scheduleTime) {
963
981
  const pitchBend = msb * 128 + lsb;
@@ -965,8 +983,6 @@ export class MidyGM1 {
965
983
  }
966
984
  setPitchBend(channelNumber, value, scheduleTime) {
967
985
  const channel = this.channels[channelNumber];
968
- if (channel.isDrum)
969
- return;
970
986
  scheduleTime ??= this.audioContext.currentTime;
971
987
  const state = channel.state;
972
988
  const prev = state.pitchWheel * 2 - 1;
@@ -1129,8 +1145,6 @@ export class MidyGM1 {
1129
1145
  }
1130
1146
  setModulationDepth(channelNumber, modulation, scheduleTime) {
1131
1147
  const channel = this.channels[channelNumber];
1132
- if (channel.isDrum)
1133
- return;
1134
1148
  scheduleTime ??= this.audioContext.currentTime;
1135
1149
  channel.state.modulationDepth = modulation / 127;
1136
1150
  this.updateModulation(channel, scheduleTime);
@@ -1177,8 +1191,6 @@ export class MidyGM1 {
1177
1191
  }
1178
1192
  setSustainPedal(channelNumber, value, scheduleTime) {
1179
1193
  const channel = this.channels[channelNumber];
1180
- if (channel.isDrum)
1181
- return;
1182
1194
  scheduleTime ??= this.audioContext.currentTime;
1183
1195
  channel.state.sustainPedal = value / 127;
1184
1196
  if (64 <= value) {
@@ -1251,8 +1263,6 @@ export class MidyGM1 {
1251
1263
  }
1252
1264
  setPitchBendRange(channelNumber, value, scheduleTime) {
1253
1265
  const channel = this.channels[channelNumber];
1254
- if (channel.isDrum)
1255
- return;
1256
1266
  scheduleTime ??= this.audioContext.currentTime;
1257
1267
  const state = channel.state;
1258
1268
  const prev = state.pitchWheelSensitivity;
@@ -1270,8 +1280,6 @@ export class MidyGM1 {
1270
1280
  }
1271
1281
  setFineTuning(channelNumber, value, scheduleTime) {
1272
1282
  const channel = this.channels[channelNumber];
1273
- if (channel.isDrum)
1274
- return;
1275
1283
  scheduleTime ??= this.audioContext.currentTime;
1276
1284
  const prev = channel.fineTuning;
1277
1285
  const next = (value - 8192) / 8.192; // cent
@@ -1287,8 +1295,6 @@ export class MidyGM1 {
1287
1295
  }
1288
1296
  setCoarseTuning(channelNumber, value, scheduleTime) {
1289
1297
  const channel = this.channels[channelNumber];
1290
- if (channel.isDrum)
1291
- return;
1292
1298
  scheduleTime ??= this.audioContext.currentTime;
1293
1299
  const prev = channel.coarseTuning;
1294
1300
  const next = (value - 64) * 100; // cent
@@ -1300,12 +1306,24 @@ export class MidyGM1 {
1300
1306
  scheduleTime ??= this.audioContext.currentTime;
1301
1307
  return this.stopChannelNotes(channelNumber, 0, true, scheduleTime);
1302
1308
  }
1309
+ resetAllStates(channelNumber) {
1310
+ const channel = this.channels[channelNumber];
1311
+ const state = channel.state;
1312
+ for (const type of Object.keys(defaultControllerState)) {
1313
+ state[type] = defaultControllerState[type].defaultValue;
1314
+ }
1315
+ for (const type of Object.keys(this.constructor.channelSettings)) {
1316
+ channel[type] = this.constructor.channelSettings[type];
1317
+ }
1318
+ this.mode = "GM1";
1319
+ }
1320
+ // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
1303
1321
  resetAllControllers(channelNumber) {
1304
1322
  const stateTypes = [
1323
+ "pitchWheel",
1305
1324
  "expression",
1306
1325
  "modulationDepth",
1307
1326
  "sustainPedal",
1308
- "pitchWheelSensitivity",
1309
1327
  ];
1310
1328
  const channel = this.channels[channelNumber];
1311
1329
  const state = channel.state;
@@ -1394,6 +1412,7 @@ export class MidyGM1 {
1394
1412
  console.warn(`Unsupported Exclusive Message: ${data}`);
1395
1413
  }
1396
1414
  }
1415
+ // https://github.com/marmooo/js-timer-benchmark
1397
1416
  scheduleTask(callback, scheduleTime) {
1398
1417
  return new Promise((resolve) => {
1399
1418
  const bufferSource = new AudioBufferSourceNode(this.audioContext, {
@@ -1418,10 +1437,8 @@ Object.defineProperty(MidyGM1, "channelSettings", {
1418
1437
  configurable: true,
1419
1438
  writable: true,
1420
1439
  value: {
1421
- currentBufferSource: null,
1422
- isDrum: false,
1423
1440
  detune: 0,
1424
- program: 0,
1441
+ programNumber: 0,
1425
1442
  bank: 0,
1426
1443
  dataMSB: 0,
1427
1444
  dataLSB: 0,
package/esm/midy-GM2.d.ts CHANGED
@@ -1,9 +1,7 @@
1
1
  export class MidyGM2 {
2
2
  static channelSettings: {
3
- currentBufferSource: null;
4
- isDrum: boolean;
5
3
  detune: number;
6
- program: number;
4
+ programNumber: number;
7
5
  bank: number;
8
6
  bankMSB: number;
9
7
  bankLSB: number;
@@ -23,8 +21,6 @@ export class MidyGM2 {
23
21
  };
24
22
  });
25
23
  mode: string;
26
- ticksPerBeat: number;
27
- totalTime: number;
28
24
  masterFineTuning: number;
29
25
  masterCoarseTuning: number;
30
26
  reverb: {
@@ -38,6 +34,9 @@ export class MidyGM2 {
38
34
  sendToReverb: number;
39
35
  delayTimes: any[];
40
36
  };
37
+ numChannels: number;
38
+ ticksPerBeat: number;
39
+ totalTime: number;
41
40
  noteCheckInterval: number;
42
41
  lookAhead: number;
43
42
  startDelay: number;
@@ -55,7 +54,8 @@ export class MidyGM2 {
55
54
  timeline: any[];
56
55
  instruments: any[];
57
56
  notePromises: any[];
58
- exclusiveClassMap: SparseMap;
57
+ exclusiveClassNotes: any[];
58
+ drumExclusiveClassNotes: any[];
59
59
  defaultOptions: {
60
60
  reverbAlgorithm: (audioContext: any) => {
61
61
  input: any;
@@ -135,8 +135,7 @@ export class MidyGM2 {
135
135
  };
136
136
  createChannels(audioContext: any): any[];
137
137
  createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
138
- calcLoopMode(channel: any, note: any, voiceParams: any): boolean;
139
- createBufferSource(channel: any, note: any, voiceParams: any, audioBuffer: any): any;
138
+ createBufferSource(voiceParams: any, audioBuffer: any): any;
140
139
  findPortamentoTarget(queueIndex: any): any;
141
140
  scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
142
141
  getQueueIndex(second: any): number;
@@ -199,18 +198,22 @@ export class MidyGM2 {
199
198
  setFilterEnvelope(channel: any, note: any, scheduleTime: any): void;
200
199
  startModulation(channel: any, note: any, scheduleTime: any): void;
201
200
  startVibrato(channel: any, note: any, scheduleTime: any): void;
202
- getAudioBuffer(program: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
201
+ getAudioBuffer(programNumber: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
203
202
  createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
204
203
  calcBank(channel: any): any;
204
+ handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
205
+ handleDrumExclusiveClass(note: any, channelNumber: any, startTime: any): void;
206
+ isDrumNoteOffException(channel: any, noteNumber: any): boolean;
205
207
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
206
208
  noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
209
+ disconnectNote(note: any, scheduledNotes: any, index: any): void;
207
210
  stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
208
211
  scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any, portamentoNoteNumber: any): Promise<any> | undefined;
209
212
  noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
210
213
  releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
211
214
  releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): any[];
212
215
  handleMIDIMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
213
- handleProgramChange(channelNumber: any, program: any, _scheduleTime: any): void;
216
+ handleProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
214
217
  handleChannelPressure(channelNumber: any, value: any, scheduleTime: any): void;
215
218
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
216
219
  setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
@@ -301,6 +304,7 @@ export class MidyGM2 {
301
304
  handleModulationDepthRangeRPN(channelNumber: any, scheduleTime: any): void;
302
305
  setModulationDepthRange(channelNumber: any, modulationDepthRange: any, scheduleTime: any): void;
303
306
  allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
307
+ resetAllStates(channelNumber: any): void;
304
308
  resetAllControllers(channelNumber: any): void;
305
309
  allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
306
310
  omniOff(channelNumber: any, value: any, scheduleTime: any): void;
@@ -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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"}