@marmooo/midy 0.2.3 → 0.2.5

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
@@ -22,6 +22,8 @@ export class MidyGM1 {
22
22
  resumeTime: number;
23
23
  soundFonts: any[];
24
24
  soundFontTable: any[];
25
+ audioBufferCounter: Map<any, any>;
26
+ audioBufferCache: Map<any, any>;
25
27
  isPlaying: boolean;
26
28
  isPausing: boolean;
27
29
  isPaused: boolean;
@@ -30,7 +32,7 @@ export class MidyGM1 {
30
32
  timeline: any[];
31
33
  instruments: any[];
32
34
  notePromises: any[];
33
- exclusiveClassMap: Map<any, any>;
35
+ exclusiveClassMap: SparseMap;
34
36
  audioContext: any;
35
37
  masterVolume: any;
36
38
  voiceParamsHandlers: {
@@ -71,12 +73,13 @@ export class MidyGM1 {
71
73
  };
72
74
  createChannels(audioContext: any): any[];
73
75
  createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
74
- createNoteBufferNode(voiceParams: any, isSF3: any): Promise<any>;
76
+ createNoteBufferNode(audioBuffer: any, voiceParams: any): any;
75
77
  scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
76
78
  getQueueIndex(second: any): number;
77
79
  playNotes(): Promise<any>;
78
80
  ticksToSecond(ticks: any, secondsPerBeat: any): number;
79
81
  secondToTicks(second: any, secondsPerBeat: any): number;
82
+ getAudioBufferId(programNumber: any, noteNumber: any, velocity: any): string;
80
83
  extractMidiData(midi: any): {
81
84
  instruments: Set<any>;
82
85
  timeline: any[];
@@ -90,19 +93,21 @@ export class MidyGM1 {
90
93
  seekTo(second: any): void;
91
94
  calcTotalTime(): number;
92
95
  currentTime(): number;
93
- getActiveNotes(channel: any, time: any): Map<any, any>;
96
+ getActiveNotes(channel: any, time: any): SparseMap;
94
97
  getActiveNote(noteList: any, time: any): any;
95
98
  cbToRatio(cb: any): number;
96
99
  rateToCent(rate: any): number;
97
100
  centToRate(cent: any): number;
98
101
  centToHz(cent: any): number;
99
102
  calcChannelDetune(channel: any): any;
100
- updateDetune(channel: any): void;
103
+ updateChannelDetune(channel: any): void;
104
+ updateDetune(channel: any, note: any): void;
101
105
  setVolumeEnvelope(note: any): void;
102
106
  setPitchEnvelope(note: any): void;
103
107
  clampCutoffFrequency(frequency: any): number;
104
108
  setFilterEnvelope(note: any): void;
105
109
  startModulation(channel: any, note: any, startTime: any): void;
110
+ getAudioBuffer(program: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
106
111
  createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
107
112
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
108
113
  noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
@@ -185,6 +190,19 @@ export class MidyGM1 {
185
190
  handleSysEx(data: any): void;
186
191
  scheduleTask(callback: any, startTime: any): Promise<any>;
187
192
  }
193
+ declare class SparseMap {
194
+ constructor(size: any);
195
+ data: any[];
196
+ activeIndices: any[];
197
+ set(key: any, value: any): void;
198
+ get(key: any): any;
199
+ delete(key: any): boolean;
200
+ has(key: any): boolean;
201
+ get size(): number;
202
+ clear(): void;
203
+ forEach(callback: any): void;
204
+ [Symbol.iterator](): Generator<any[], void, unknown>;
205
+ }
188
206
  declare class Note {
189
207
  constructor(noteNumber: any, velocity: any, startTime: any, voice: any, voiceParams: any);
190
208
  bufferSource: any;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAqFA;IAoBE;;;;;;;;;;;;MAYE;IAEF,+BAQC;IAzCD,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAClB,iCAA8B;IAiB5B,kBAAgC;IAChC,kBAA8C;IAC9C;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,6DA2BC;IAED,iEAUC;IAED,2EA+CC;IAED,mCAOC;IAED,0BAkDC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgEC;IAED,+EAmBC;IAED,qDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,iCAWC;IAED,mCAgBC;IAED,kCAqBC;IAED,6CAIC;IAED,mCAuBC;IAED,+DAoBC;IAED,gHA2BC;IAED,kGAgDC;IAED,0EAGC;IAED,qFA4BC;IAED,6HAuBC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,mDASC;IAED,gDASC;IAED,gDASC;IAED,qCAMC;IAED,mCAQC;IAED,gCAOC;IAED,+BAMC;IAED;;;;;;;;;;;MA4CC;IAED,oFAMC;IAED,0DA6CC;IAED;;;;;;;;;;;;;MAeC;IAED,+EAWC;IAED,qCAeC;IAED,8DAIC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,wCAWC;IAED,sDAKC;IAED,kFAeC;IAED,2DAMC;IAED,oCAkBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,kDAKC;IAED,wDASC;IAED,8CAKC;IAED,oDAOC;IAED,gDAKC;IAED,sDAOC;IAED,+CAEC;IAED,8CAqBC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAMC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAjzCD;IAUE,0FAMC;IAfD,kBAAa;IACb,gBAAW;IACX,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IAGX,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":"AAkJA;IAsBE;;;;;;;;;;;;MAYE;IAEF,+BAQC;IA3CD,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;IAiBrC,kBAAgC;IAChC,kBAA8C;IAC9C;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,6DA2BC;IAED,8DASC;IAED,2EA+CC;IAED,mCAOC;IAED,0BAoDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MA4EC;IAED,+EAmBC;IAED,qDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,mDASC;IAED,6CAQC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,wCAQC;IAED,4CAKC;IAED,mCAgBC;IAED,kCAqBC;IAED,6CAIC;IAED,mCAuBC;IAED,+DAoBC;IAED,yGAgBC;IAED,gHAuCC;IAED,kGAgDC;IAED,0EAGC;IAED,qFA4BC;IAED,6HAuBC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,mDASC;IAED,gDASC;IAED,gDASC;IAED,qCAMC;IAED,mCAQC;IAED,gCAOC;IAED,+BAMC;IAED;;;;;;;;;;;MA4CC;IAED,oFAMC;IAED,0DA6CC;IAED;;;;;;;;;;;;;MAeC;IAED,+EAWC;IAED,qCAeC;IAED,8DAIC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,wCAWC;IAED,sDAKC;IAED,kFAeC;IAED,2DAMC;IAED,oCAkBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,kDAKC;IAED,wDASC;IAED,8CAKC;IAED,oDAOC;IAED,gDAKC;IAED,sDAOC;IAED,+CAEC;IAED,8CAqBC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAMC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAl6CD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IAUE,0FAMC;IAfD,kBAAa;IACb,gBAAW;IACX,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
package/esm/midy-GM1.js CHANGED
@@ -1,5 +1,57 @@
1
1
  import { parseMidi } from "midi-file";
2
2
  import { parse, SoundFont } from "@marmooo/soundfont-parser";
3
+ // 2-3 times faster than Map
4
+ class SparseMap {
5
+ constructor(size) {
6
+ this.data = new Array(size);
7
+ this.activeIndices = [];
8
+ }
9
+ set(key, value) {
10
+ if (this.data[key] === undefined) {
11
+ this.activeIndices.push(key);
12
+ }
13
+ this.data[key] = value;
14
+ }
15
+ get(key) {
16
+ return this.data[key];
17
+ }
18
+ delete(key) {
19
+ if (this.data[key] !== undefined) {
20
+ this.data[key] = undefined;
21
+ const index = this.activeIndices.indexOf(key);
22
+ if (index !== -1) {
23
+ this.activeIndices.splice(index, 1);
24
+ }
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+ has(key) {
30
+ return this.data[key] !== undefined;
31
+ }
32
+ get size() {
33
+ return this.activeIndices.length;
34
+ }
35
+ clear() {
36
+ for (let i = 0; i < this.activeIndices.length; i++) {
37
+ const key = this.activeIndices[i];
38
+ this.data[key] = undefined;
39
+ }
40
+ this.activeIndices = [];
41
+ }
42
+ *[Symbol.iterator]() {
43
+ for (let i = 0; i < this.activeIndices.length; i++) {
44
+ const key = this.activeIndices[i];
45
+ yield [key, this.data[key]];
46
+ }
47
+ }
48
+ forEach(callback) {
49
+ for (let i = 0; i < this.activeIndices.length; i++) {
50
+ const key = this.activeIndices[i];
51
+ callback(this.data[key], key, this);
52
+ }
53
+ }
54
+ }
3
55
  class Note {
4
56
  constructor(noteNumber, velocity, startTime, voice, voiceParams) {
5
57
  Object.defineProperty(this, "bufferSource", {
@@ -178,6 +230,18 @@ export class MidyGM1 {
178
230
  writable: true,
179
231
  value: this.initSoundFontTable()
180
232
  });
233
+ Object.defineProperty(this, "audioBufferCounter", {
234
+ enumerable: true,
235
+ configurable: true,
236
+ writable: true,
237
+ value: new Map()
238
+ });
239
+ Object.defineProperty(this, "audioBufferCache", {
240
+ enumerable: true,
241
+ configurable: true,
242
+ writable: true,
243
+ value: new Map()
244
+ });
181
245
  Object.defineProperty(this, "isPlaying", {
182
246
  enumerable: true,
183
247
  configurable: true,
@@ -230,7 +294,7 @@ export class MidyGM1 {
230
294
  enumerable: true,
231
295
  configurable: true,
232
296
  writable: true,
233
- value: new Map()
297
+ value: new SparseMap(128)
234
298
  });
235
299
  this.audioContext = audioContext;
236
300
  this.masterVolume = new GainNode(audioContext);
@@ -243,7 +307,7 @@ export class MidyGM1 {
243
307
  initSoundFontTable() {
244
308
  const table = new Array(128);
245
309
  for (let i = 0; i < 128; i++) {
246
- table[i] = new Map();
310
+ table[i] = new SparseMap(128);
247
311
  }
248
312
  return table;
249
313
  }
@@ -296,7 +360,7 @@ export class MidyGM1 {
296
360
  ...this.constructor.channelSettings,
297
361
  state: new ControllerState(),
298
362
  ...this.setChannelAudioNodes(audioContext),
299
- scheduledNotes: new Map(),
363
+ scheduledNotes: new SparseMap(128),
300
364
  };
301
365
  });
302
366
  return channels;
@@ -330,9 +394,8 @@ export class MidyGM1 {
330
394
  return audioBuffer;
331
395
  }
332
396
  }
333
- async createNoteBufferNode(voiceParams, isSF3) {
397
+ createNoteBufferNode(audioBuffer, voiceParams) {
334
398
  const bufferSource = new AudioBufferSourceNode(this.audioContext);
335
- const audioBuffer = await this.createNoteBuffer(voiceParams, isSF3);
336
399
  bufferSource.buffer = audioBuffer;
337
400
  bufferSource.loop = voiceParams.sampleModes % 2 !== 0;
338
401
  if (bufferSource.loop) {
@@ -397,6 +460,7 @@ export class MidyGM1 {
397
460
  await Promise.all(this.notePromises);
398
461
  this.notePromises = [];
399
462
  this.exclusiveClassMap.clear();
463
+ this.audioBufferCache.clear();
400
464
  resolve();
401
465
  return;
402
466
  }
@@ -412,8 +476,9 @@ export class MidyGM1 {
412
476
  }
413
477
  else if (this.isStopping) {
414
478
  await this.stopNotes(0, true);
415
- this.exclusiveClassMap.clear();
416
479
  this.notePromises = [];
480
+ this.exclusiveClassMap.clear();
481
+ this.audioBufferCache.clear();
417
482
  resolve();
418
483
  this.isStopping = false;
419
484
  this.isPaused = false;
@@ -444,6 +509,9 @@ export class MidyGM1 {
444
509
  secondToTicks(second, secondsPerBeat) {
445
510
  return second * this.ticksPerBeat / secondsPerBeat;
446
511
  }
512
+ getAudioBufferId(programNumber, noteNumber, velocity) {
513
+ return `${programNumber}:${noteNumber}:${velocity}`;
514
+ }
447
515
  extractMidiData(midi) {
448
516
  const instruments = new Set();
449
517
  const timeline = [];
@@ -464,6 +532,8 @@ export class MidyGM1 {
464
532
  switch (event.type) {
465
533
  case "noteOn": {
466
534
  const channel = tmpChannels[event.channel];
535
+ const audioBufferId = this.getAudioBufferId(channel.programNumber, event.noteNumber, event.velocity);
536
+ this.audioBufferCounter.set(audioBufferId, (this.audioBufferCounter.get(audioBufferId) ?? 0) + 1);
467
537
  if (channel.programNumber < 0) {
468
538
  instruments.add(`${channel.bank}:0`);
469
539
  channel.programNumber = 0;
@@ -480,6 +550,10 @@ export class MidyGM1 {
480
550
  timeline.push(event);
481
551
  }
482
552
  }
553
+ for (const [audioBufferId, count] of this.audioBufferCounter) {
554
+ if (count === 1)
555
+ this.audioBufferCounter.delete(audioBufferId);
556
+ }
483
557
  const priority = {
484
558
  controller: 0,
485
559
  sysEx: 1,
@@ -570,7 +644,7 @@ export class MidyGM1 {
570
644
  return this.resumeTime + now - this.startTime - this.startDelay;
571
645
  }
572
646
  getActiveNotes(channel, time) {
573
- const activeNotes = new Map();
647
+ const activeNotes = new SparseMap(128);
574
648
  channel.scheduledNotes.forEach((noteList) => {
575
649
  const activeNote = this.getActiveNote(noteList, time);
576
650
  if (activeNote) {
@@ -609,19 +683,22 @@ export class MidyGM1 {
609
683
  const pitch = pitchWheel * pitchWheelSensitivity;
610
684
  return tuning + pitch;
611
685
  }
612
- updateDetune(channel) {
613
- const now = this.audioContext.currentTime;
686
+ updateChannelDetune(channel) {
614
687
  channel.scheduledNotes.forEach((noteList) => {
615
688
  for (let i = 0; i < noteList.length; i++) {
616
689
  const note = noteList[i];
617
690
  if (!note)
618
691
  continue;
619
- note.bufferSource.detune
620
- .cancelScheduledValues(now)
621
- .setValueAtTime(channel.detune, now);
692
+ this.updateDetune(channel, note);
622
693
  }
623
694
  });
624
695
  }
696
+ updateDetune(channel, note) {
697
+ const now = this.audioContext.currentTime;
698
+ note.bufferSource.detune
699
+ .cancelScheduledValues(now)
700
+ .setValueAtTime(channel.detune, now);
701
+ }
625
702
  setVolumeEnvelope(note) {
626
703
  const now = this.audioContext.currentTime;
627
704
  const { voiceParams, startTime } = note;
@@ -709,11 +786,31 @@ export class MidyGM1 {
709
786
  note.modulationLFO.connect(note.volumeDepth);
710
787
  note.volumeDepth.connect(note.volumeEnvelopeNode.gain);
711
788
  }
789
+ async getAudioBuffer(program, noteNumber, velocity, voiceParams, isSF3) {
790
+ const audioBufferId = this.getAudioBufferId(program, noteNumber, velocity);
791
+ const cache = this.audioBufferCache.get(audioBufferId);
792
+ if (cache) {
793
+ cache.counter += 1;
794
+ if (cache.maxCount <= cache.counter) {
795
+ this.audioBufferCache.delete(audioBufferId);
796
+ }
797
+ return cache.audioBuffer;
798
+ }
799
+ else {
800
+ const maxCount = this.audioBufferCounter.get(audioBufferId) ?? 0;
801
+ const audioBuffer = await this.createNoteBuffer(voiceParams, isSF3);
802
+ const cache = { audioBuffer, maxCount, counter: 1 };
803
+ this.audioBufferCache.set(audioBufferId, cache);
804
+ return audioBuffer;
805
+ }
806
+ }
712
807
  async createNote(channel, voice, noteNumber, velocity, startTime, isSF3) {
713
808
  const state = channel.state;
714
- const voiceParams = voice.getAllParams(state.array);
809
+ const controllerState = this.getControllerState(channel, noteNumber, velocity);
810
+ const voiceParams = voice.getAllParams(controllerState);
715
811
  const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
716
- note.bufferSource = await this.createNoteBufferNode(voiceParams, isSF3);
812
+ const audioBuffer = await this.getAudioBuffer(channel.program, noteNumber, velocity, voiceParams, isSF3);
813
+ note.bufferSource = this.createNoteBufferNode(audioBuffer, voiceParams);
717
814
  note.volumeEnvelopeNode = new GainNode(this.audioContext);
718
815
  note.filterNode = new BiquadFilterNode(this.audioContext, {
719
816
  type: "lowpass",
@@ -737,10 +834,10 @@ export class MidyGM1 {
737
834
  if (soundFontIndex === undefined)
738
835
  return;
739
836
  const soundFont = this.soundFonts[soundFontIndex];
740
- const isSF3 = soundFont.parsed.info.version.major === 3;
741
837
  const voice = soundFont.getVoice(bankNumber, channel.program, noteNumber, velocity);
742
838
  if (!voice)
743
839
  return;
840
+ const isSF3 = soundFont.parsed.info.version.major === 3;
744
841
  const note = await this.createNote(channel, voice, noteNumber, velocity, startTime, isSF3);
745
842
  note.volumeEnvelopeNode.connect(channel.gainL);
746
843
  note.volumeEnvelopeNode.connect(channel.gainR);
@@ -874,7 +971,7 @@ export class MidyGM1 {
874
971
  const next = (value - 8192) / 8192;
875
972
  state.pitchWheel = value / 16383;
876
973
  channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
877
- this.updateDetune(channel);
974
+ this.updateChannelDetune(channel);
878
975
  this.applyVoiceParams(channel, 14);
879
976
  }
880
977
  setModLfoToPitch(channel, note) {
@@ -972,7 +1069,7 @@ export class MidyGM1 {
972
1069
  const freqVibLFO = note.voiceParams.freqVibLFO;
973
1070
  note.vibratoLFO.frequency
974
1071
  .cancelScheduledValues(now)
975
- .setValueAtTime(freqVibLFO * channel.state.vibratoRate, now);
1072
+ .setValueAtTime(freqVibLFO * channel.state.vibratoRate * 2, now);
976
1073
  }
977
1074
  },
978
1075
  };
@@ -1012,7 +1109,7 @@ export class MidyGM1 {
1012
1109
  if (key in voiceParams)
1013
1110
  noteVoiceParams[key] = voiceParams[key];
1014
1111
  }
1015
- this.setFilterEnvelope(channel, note);
1112
+ this.setFilterEnvelope(note);
1016
1113
  this.setPitchEnvelope(note);
1017
1114
  }
1018
1115
  else if (volumeEnvelopeKeySet.has(key)) {
@@ -1052,7 +1149,7 @@ export class MidyGM1 {
1052
1149
  if (handler) {
1053
1150
  handler.call(this, channelNumber, value);
1054
1151
  const channel = this.channels[channelNumber];
1055
- this.applyVoiceParams(channel, controller + 128);
1152
+ this.applyVoiceParams(channel, controllerType + 128);
1056
1153
  }
1057
1154
  else {
1058
1155
  console.warn(`Unsupported Control change: controllerType=${controllerType} value=${value}`);
@@ -1191,7 +1288,7 @@ export class MidyGM1 {
1191
1288
  const next = value / 128;
1192
1289
  state.pitchWheelSensitivity = next;
1193
1290
  channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
1194
- this.updateDetune(channel);
1291
+ this.updateChannelDetune(channel);
1195
1292
  this.applyVoiceParams(channel, 16);
1196
1293
  }
1197
1294
  handleFineTuningRPN(channelNumber) {
@@ -1206,7 +1303,7 @@ export class MidyGM1 {
1206
1303
  const next = (value - 8192) / 8.192; // cent
1207
1304
  channel.fineTuning = next;
1208
1305
  channel.detune += next - prev;
1209
- this.updateDetune(channel);
1306
+ this.updateChannelDetune(channel);
1210
1307
  }
1211
1308
  handleCoarseTuningRPN(channelNumber) {
1212
1309
  const channel = this.channels[channelNumber];
@@ -1220,7 +1317,7 @@ export class MidyGM1 {
1220
1317
  const next = (value - 64) * 100; // cent
1221
1318
  channel.coarseTuning = next;
1222
1319
  channel.detune += next - prev;
1223
- this.updateDetune(channel);
1320
+ this.updateChannelDetune(channel);
1224
1321
  }
1225
1322
  allSoundOff(channelNumber) {
1226
1323
  return this.stopChannelNotes(channelNumber, 0, true);
@@ -1236,7 +1333,7 @@ export class MidyGM1 {
1236
1333
  const state = channel.state;
1237
1334
  for (let i = 0; i < stateTypes.length; i++) {
1238
1335
  const type = stateTypes[i];
1239
- state[type] = defaultControllerState[type];
1336
+ state[type] = defaultControllerState[type].defaultValue;
1240
1337
  }
1241
1338
  const settingTypes = [
1242
1339
  "rpnMSB",
package/esm/midy-GM2.d.ts CHANGED
@@ -2,8 +2,8 @@ export class MidyGM2 {
2
2
  static channelSettings: {
3
3
  currentBufferSource: null;
4
4
  detune: number;
5
- scaleOctaveTuningTable: any[];
6
- pressureTable: Uint8Array<ArrayBuffer>;
5
+ scaleOctaveTuningTable: Int8Array<ArrayBuffer>;
6
+ channelPressureTable: Uint8Array<ArrayBuffer>;
7
7
  keyBasedInstrumentControlTable: Int8Array<ArrayBuffer>;
8
8
  program: number;
9
9
  bank: number;
@@ -17,14 +17,6 @@ export class MidyGM2 {
17
17
  coarseTuning: number;
18
18
  modulationDepthRange: number;
19
19
  };
20
- static controllerDestinationSettings: {
21
- pitchControl: number;
22
- filterCutoffControl: number;
23
- amplitudeControl: number;
24
- lfoPitchDepth: number;
25
- lfoFilterDepth: number;
26
- lfoAmplitudeDepth: number;
27
- };
28
20
  constructor(audioContext: any, options?: {
29
21
  reverbAlgorithm: (audioContext: any) => {
30
22
  input: any;
@@ -55,6 +47,8 @@ export class MidyGM2 {
55
47
  resumeTime: number;
56
48
  soundFonts: any[];
57
49
  soundFontTable: any[];
50
+ audioBufferCounter: Map<any, any>;
51
+ audioBufferCache: Map<any, any>;
58
52
  isPlaying: boolean;
59
53
  isPausing: boolean;
60
54
  isPaused: boolean;
@@ -63,7 +57,7 @@ export class MidyGM2 {
63
57
  timeline: any[];
64
58
  instruments: any[];
65
59
  notePromises: any[];
66
- exclusiveClassMap: Map<any, any>;
60
+ exclusiveClassMap: SparseMap;
67
61
  defaultOptions: {
68
62
  reverbAlgorithm: (audioContext: any) => {
69
63
  input: any;
@@ -141,13 +135,14 @@ export class MidyGM2 {
141
135
  };
142
136
  createChannels(audioContext: any): any[];
143
137
  createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
144
- createNoteBufferNode(voiceParams: any, isSF3: any): Promise<any>;
138
+ createNoteBufferNode(audioBuffer: any, voiceParams: any): any;
145
139
  findPortamentoTarget(queueIndex: any): any;
146
140
  scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
147
141
  getQueueIndex(second: any): number;
148
142
  playNotes(): Promise<any>;
149
143
  ticksToSecond(ticks: any, secondsPerBeat: any): number;
150
144
  secondToTicks(second: any, secondsPerBeat: any): number;
145
+ getAudioBufferId(programNumber: any, noteNumber: any, velocity: any): string;
151
146
  extractMidiData(midi: any): {
152
147
  instruments: Set<any>;
153
148
  timeline: any[];
@@ -161,7 +156,7 @@ export class MidyGM2 {
161
156
  seekTo(second: any): void;
162
157
  calcTotalTime(): number;
163
158
  currentTime(): number;
164
- getActiveNotes(channel: any, time: any): Map<any, any>;
159
+ getActiveNotes(channel: any, time: any): SparseMap;
165
160
  getActiveNote(noteList: any, time: any): any;
166
161
  createConvolutionReverbImpulse(audioContext: any, decay: any, preDecay: any): any;
167
162
  createConvolutionReverb(audioContext: any, impulse: any): {
@@ -191,16 +186,18 @@ export class MidyGM2 {
191
186
  centToHz(cent: any): number;
192
187
  calcChannelDetune(channel: any): any;
193
188
  calcNoteDetune(channel: any, note: any): any;
194
- updateDetune(channel: any): void;
189
+ updateChannelDetune(channel: any): void;
190
+ updateDetune(channel: any, note: any, pressure: any): void;
195
191
  getPortamentoTime(channel: any): number;
196
192
  setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
197
- setVolumeEnvelope(channel: any, note: any): void;
193
+ setVolumeEnvelope(note: any, pressure: any): void;
198
194
  setPitchEnvelope(note: any): void;
199
195
  clampCutoffFrequency(frequency: any): number;
200
196
  setPortamentoStartFilterEnvelope(channel: any, note: any): void;
201
- setFilterEnvelope(channel: any, note: any): void;
197
+ setFilterEnvelope(channel: any, note: any, pressure: any): void;
202
198
  startModulation(channel: any, note: any, startTime: any): void;
203
199
  startVibrato(channel: any, note: any, startTime: any): void;
200
+ getAudioBuffer(program: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
204
201
  createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
205
202
  calcBank(channel: any, channelNumber: any): any;
206
203
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
@@ -213,17 +210,17 @@ export class MidyGM2 {
213
210
  handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
214
211
  handleProgramChange(channelNumber: any, program: any): void;
215
212
  handleChannelPressure(channelNumber: any, value: any): void;
216
- setChannelPressure(channel: any, note: any): void;
217
213
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
218
214
  setPitchBend(channelNumber: any, value: any): void;
219
- setModLfoToPitch(channel: any, note: any): void;
215
+ setModLfoToPitch(channel: any, note: any, pressure: any): void;
220
216
  setVibLfoToPitch(channel: any, note: any): void;
221
- setModLfoToFilterFc(channel: any, note: any): void;
222
- setModLfoToVolume(channel: any, note: any): void;
217
+ setModLfoToFilterFc(note: any, pressure: any): void;
218
+ setModLfoToVolume(note: any, pressure: any): void;
223
219
  setReverbEffectsSend(channel: any, note: any, prevValue: any): void;
224
220
  setChorusEffectsSend(channel: any, note: any, prevValue: any): void;
225
221
  setDelayModLFO(note: any): void;
226
222
  setFreqModLFO(note: any): void;
223
+ setFreqVibLFO(channel: any, note: any): void;
227
224
  createVoiceParamsHandlers(): {
228
225
  modLfoToPitch: (channel: any, note: any, _prevValue: any) => void;
229
226
  vibLfoToPitch: (channel: any, note: any, _prevValue: any) => void;
@@ -311,7 +308,7 @@ export class MidyGM2 {
311
308
  handleUniversalNonRealTimeExclusiveMessage(data: any): void;
312
309
  GM1SystemOn(): void;
313
310
  GM2SystemOn(): void;
314
- handleUniversalRealTimeExclusiveMessage(data: any): void;
311
+ handleUniversalRealTimeExclusiveMessage(data: any): any;
315
312
  handleMasterVolumeSysEx(data: any): void;
316
313
  setMasterVolume(volume: any): void;
317
314
  handleMasterFineTuningSysEx(data: any): void;
@@ -337,18 +334,31 @@ export class MidyGM2 {
337
334
  setChorusSendToReverb(value: any): void;
338
335
  getChorusSendToReverb(value: any): number;
339
336
  getChannelBitmap(data: any): any[];
340
- handleScaleOctaveTuning1ByteFormatSysEx(data: any): void;
337
+ handleScaleOctaveTuning1ByteFormatSysEx(data: any, realtime: any): void;
341
338
  applyDestinationSettings(channel: any, note: any, table: any): void;
342
- handleChannelPressureSysEx(data: any): void;
339
+ handleChannelPressureSysEx(data: any, tableName: any): void;
343
340
  initControlTable(): Uint8Array<ArrayBuffer>;
344
341
  applyControlTable(channel: any, controllerType: any): void;
345
342
  handleControlChangeSysEx(data: any): void;
346
343
  getKeyBasedInstrumentControlValue(channel: any, keyNumber: any, controllerType: any): number;
347
344
  handleKeyBasedInstrumentControlSysEx(data: any): void;
348
345
  handleExclusiveMessage(data: any): void;
349
- handleSysEx(data: any): void;
346
+ handleSysEx(data: any): any;
350
347
  scheduleTask(callback: any, startTime: any): Promise<any>;
351
348
  }
349
+ declare class SparseMap {
350
+ constructor(size: any);
351
+ data: any[];
352
+ activeIndices: any[];
353
+ set(key: any, value: any): void;
354
+ get(key: any): any;
355
+ delete(key: any): boolean;
356
+ has(key: any): boolean;
357
+ get size(): number;
358
+ clear(): void;
359
+ forEach(callback: any): void;
360
+ [Symbol.iterator](): Generator<any[], void, unknown>;
361
+ }
352
362
  declare class Note {
353
363
  constructor(noteNumber: any, velocity: any, startTime: any, voice: any, voiceParams: any);
354
364
  bufferSource: any;
@@ -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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"}