@marmooo/midy 0.0.5 → 0.0.6

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
@@ -41,8 +41,8 @@ export class MidyGM1 {
41
41
  masterGain: any;
42
42
  channels: {
43
43
  scheduledNotes: Map<any, any>;
44
- gainNode: any;
45
- pannerNode: any;
44
+ gainL: any;
45
+ gainR: any;
46
46
  expression: number;
47
47
  modulation: number;
48
48
  sustainPedal: boolean;
@@ -65,13 +65,13 @@ export class MidyGM1 {
65
65
  loadSoundFont(soundFontUrl: any): Promise<void>;
66
66
  loadMIDI(midiUrl: any): Promise<void>;
67
67
  setChannelAudioNodes(audioContext: any): {
68
- gainNode: any;
69
- pannerNode: any;
68
+ gainL: any;
69
+ gainR: any;
70
70
  };
71
71
  createChannels(audioContext: any): {
72
72
  scheduledNotes: Map<any, any>;
73
- gainNode: any;
74
- pannerNode: any;
73
+ gainL: any;
74
+ gainR: any;
75
75
  expression: number;
76
76
  modulation: number;
77
77
  sustainPedal: boolean;
@@ -128,10 +128,14 @@ export class MidyGM1 {
128
128
  handleMIDIMessage(statusByte: any, data1: any, data2: any): void | any[] | Promise<any>;
129
129
  handleProgramChange(channelNumber: any, program: any): void;
130
130
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
131
- handlePitchBend(channelNumber: any, pitchBend: any): void;
131
+ setPitchBend(channelNumber: any, pitchBend: any): void;
132
132
  handleControlChange(channelNumber: any, controller: any, value: any): void | any[];
133
133
  setModulation(channelNumber: any, modulation: any): void;
134
134
  setVolume(channelNumber: any, volume: any): void;
135
+ panToGain(pan: any): {
136
+ gainLeft: number;
137
+ gainRight: number;
138
+ };
135
139
  setPan(channelNumber: any, pan: any): void;
136
140
  setExpression(channelNumber: any, expression: any): void;
137
141
  updateChannelGain(channel: any): void;
@@ -139,6 +143,8 @@ export class MidyGM1 {
139
143
  setRPNMSB(channelNumber: any, value: any): void;
140
144
  setRPNLSB(channelNumber: any, value: any): void;
141
145
  setDataEntry(channelNumber: any, value: any, isMSB: any): void;
146
+ handlePitchBendRangeMessage(channelNumber: any, dataMSB: any, dataLSB: any): void;
147
+ setPitchBendRange(channelNumber: any, pitchBendRange: any): void;
142
148
  allSoundOff(channelNumber: any): any[];
143
149
  resetAllControllers(channelNumber: any): void;
144
150
  allNotesOff(channelNumber: any): any[];
@@ -146,7 +152,7 @@ export class MidyGM1 {
146
152
  GM1SystemOn(): void;
147
153
  handleUniversalRealTimeExclusiveMessage(data: any): void;
148
154
  handleMasterVolumeSysEx(data: any): void;
149
- handleMasterVolume(volume: any): void;
155
+ setMasterVolume(volume: any): void;
150
156
  handleExclusiveMessage(data: any): void;
151
157
  handleSysEx(data: any): void;
152
158
  scheduleTask(callback: any, startTime: any): Promise<any>;
@@ -158,8 +164,6 @@ declare class Note {
158
164
  filterNode: any;
159
165
  modLFO: any;
160
166
  modLFOGain: any;
161
- vibLFO: any;
162
- vibLFOGain: any;
163
167
  noteNumber: any;
164
168
  velocity: any;
165
169
  startTime: any;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAuBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA9CD,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;IAyBhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;MAaC;IAED;;;;;;;;;;;;;;;;;;;;QAUC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EA+CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAyEC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,sDAEC;IAED,2BAEC;IAED,4BAEC;IAED,sCAGC;IAED,mFAGC;IAED,iDAmBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHA6BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIAmDC;IAED,0FAGC;IAED,kEAeC;IAED,wFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,0DAiBC;IAED,mFA+BC;IAED,yDAiBC;IAED,iDAIC;IAED,2CAMC;IAED,yDAIC;IAED,sCAKC;IAED,sDAMC;IAED,gDAEC;IAED,gDAEC;IAED,+DAoBC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,sCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAv+BD;IASE,gFAKC;IAbD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
1
+ {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAqBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA9CD,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;IAyBhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;MAYC;IAED;;;;;;;;;;;;;;;;;;;;QAUC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EA+CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA8DC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,sDAEC;IAED,2BAEC;IAED,4BAEC;IAED,sCAGC;IAED,mFAGC;IAED,iDAiBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHA6BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIAmDC;IAED,0FAGC;IAED,kEAeC;IAED,wFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,uDAeC;IAED,mFA+BC;IAED,yDAiBC;IAED,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,sCAUC;IAED,sDAMC;IAED,gDAEC;IAED,gDAEC;IAED,+DAuBC;IAED,kFAGC;IAED,iEAeC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAz/BD;IAOE,gFAKC;IAXD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
package/esm/midy-GM1.js CHANGED
@@ -32,18 +32,6 @@ class Note {
32
32
  writable: true,
33
33
  value: void 0
34
34
  });
35
- Object.defineProperty(this, "vibLFO", {
36
- enumerable: true,
37
- configurable: true,
38
- writable: true,
39
- value: void 0
40
- });
41
- Object.defineProperty(this, "vibLFOGain", {
42
- enumerable: true,
43
- configurable: true,
44
- writable: true,
45
- value: void 0
46
- });
47
35
  this.noteNumber = noteNumber;
48
36
  this.velocity = velocity;
49
37
  this.startTime = startTime;
@@ -195,17 +183,16 @@ export class MidyGM1 {
195
183
  this.totalTime = this.calcTotalTime();
196
184
  }
197
185
  setChannelAudioNodes(audioContext) {
198
- const gainNode = new GainNode(audioContext, {
199
- gain: MidyGM1.channelSettings.volume,
200
- });
201
- const pannerNode = new StereoPannerNode(audioContext, {
202
- pan: MidyGM1.channelSettings.pan,
203
- });
204
- pannerNode.connect(gainNode);
205
- gainNode.connect(this.masterGain);
186
+ const { gainLeft, gainRight } = this.panToGain(MidyGM1.channelSettings.pan);
187
+ const gainL = new GainNode(audioContext, { gain: gainLeft });
188
+ const gainR = new GainNode(audioContext, { gain: gainRight });
189
+ const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
190
+ gainL.connect(merger, 0, 0);
191
+ gainR.connect(merger, 0, 1);
192
+ merger.connect(this.masterGain);
206
193
  return {
207
- gainNode,
208
- pannerNode,
194
+ gainL,
195
+ gainR,
209
196
  };
210
197
  }
211
198
  createChannels(audioContext) {
@@ -290,7 +277,7 @@ export class MidyGM1 {
290
277
  this.handleProgramChange(event.channel, event.programNumber);
291
278
  break;
292
279
  case "pitchBend":
293
- this.handlePitchBend(event.channel, event.value);
280
+ this.setPitchBend(event.channel, event.value);
294
281
  break;
295
282
  case "sysEx":
296
283
  this.handleSysEx(event.data);
@@ -370,7 +357,6 @@ export class MidyGM1 {
370
357
  const tmpChannels = new Array(16);
371
358
  for (let i = 0; i < tmpChannels.length; i++) {
372
359
  tmpChannels[i] = {
373
- durationTicks: new Map(),
374
360
  programNumber: -1,
375
361
  bank: this.channels[i].bank,
376
362
  };
@@ -387,16 +373,6 @@ export class MidyGM1 {
387
373
  instruments.add(`${channel.bank}:0`);
388
374
  channel.programNumber = 0;
389
375
  }
390
- channel.durationTicks.set(event.noteNumber, {
391
- ticks: event.ticks,
392
- noteOn: event,
393
- });
394
- break;
395
- }
396
- case "noteOff": {
397
- const { ticks, noteOn } = tmpChannels[event.channel].durationTicks
398
- .get(event.noteNumber);
399
- noteOn.durationTicks = event.ticks - ticks;
400
376
  break;
401
377
  }
402
378
  case "programChange": {
@@ -410,8 +386,8 @@ export class MidyGM1 {
410
386
  });
411
387
  });
412
388
  const priority = {
413
- setTempo: 0,
414
- controller: 1,
389
+ controller: 0,
390
+ sysEx: 1,
415
391
  };
416
392
  timeline.sort((a, b) => {
417
393
  if (a.ticks !== b.ticks)
@@ -534,9 +510,7 @@ export class MidyGM1 {
534
510
  }
535
511
  setVolumeEnvelope(channel, note) {
536
512
  const { instrumentKey, startTime, velocity } = note;
537
- note.gainNode = new GainNode(this.audioContext, {
538
- gain: 0,
539
- });
513
+ note.gainNode = new GainNode(this.audioContext, { gain: 0 });
540
514
  let volume = (velocity / 127) * channel.volume * channel.expression;
541
515
  if (volume === 0)
542
516
  volume = 1e-6; // exponentialRampToValueAtTime() requires a non-zero value
@@ -726,20 +700,22 @@ export class MidyGM1 {
726
700
  }
727
701
  handlePitchBendMessage(channelNumber, lsb, msb) {
728
702
  const pitchBend = msb * 128 + lsb;
729
- this.handlePitchBend(channelNumber, pitchBend);
703
+ this.setPitchBend(channelNumber, pitchBend);
730
704
  }
731
- handlePitchBend(channelNumber, pitchBend) {
705
+ setPitchBend(channelNumber, pitchBend) {
732
706
  const now = this.audioContext.currentTime;
733
707
  const channel = this.channels[channelNumber];
708
+ const prevPitchBend = channel.pitchBend;
734
709
  channel.pitchBend = (pitchBend - 8192) / 8192;
735
- const semitoneOffset = this.calcSemitoneOffset(channel);
710
+ const detuneChange = (channel.pitchBend - prevPitchBend) *
711
+ channel.pitchBendRange * 100;
736
712
  const activeNotes = this.getActiveNotes(channel, now);
737
713
  activeNotes.forEach((activeNote) => {
738
- const { bufferSource, instrumentKey, noteNumber } = activeNote;
739
- const playbackRate = calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
740
- bufferSource.playbackRate
714
+ const { bufferSource } = activeNote;
715
+ const detune = bufferSource.detune.value + detuneChange;
716
+ bufferSource.detune
741
717
  .cancelScheduledValues(now)
742
- .setValueAtTime(playbackRate * pressure, now);
718
+ .setValueAtTime(detune, now);
743
719
  });
744
720
  }
745
721
  handleControlChange(channelNumber, controller, value) {
@@ -793,12 +769,17 @@ export class MidyGM1 {
793
769
  channel.volume = volume / 127;
794
770
  this.updateChannelGain(channel);
795
771
  }
772
+ panToGain(pan) {
773
+ const theta = Math.PI / 2 * Math.max(0, pan - 1) / 126;
774
+ return {
775
+ gainLeft: Math.cos(theta),
776
+ gainRight: Math.sin(theta),
777
+ };
778
+ }
796
779
  setPan(channelNumber, pan) {
797
- const now = this.audioContext.currentTime;
798
780
  const channel = this.channels[channelNumber];
799
- channel.pan = pan / 127 * 2 - 1; // -1 (left) - +1 (right)
800
- channel.pannerNode.pan.cancelScheduledValues(now);
801
- channel.pannerNode.pan.setValueAtTime(channel.pan, now);
781
+ channel.pan = pan;
782
+ this.updateChannelGain(channel);
802
783
  }
803
784
  setExpression(channelNumber, expression) {
804
785
  const channel = this.channels[channelNumber];
@@ -808,8 +789,13 @@ export class MidyGM1 {
808
789
  updateChannelGain(channel) {
809
790
  const now = this.audioContext.currentTime;
810
791
  const volume = channel.volume * channel.expression;
811
- channel.gainNode.gain.cancelScheduledValues(now);
812
- channel.gainNode.gain.setValueAtTime(volume, now);
792
+ const { gainLeft, gainRight } = this.panToGain(channel.pan);
793
+ channel.gainL.gain
794
+ .cancelScheduledValues(now)
795
+ .setValueAtTime(volume * gainLeft, now);
796
+ channel.gainR.gain
797
+ .cancelScheduledValues(now)
798
+ .setValueAtTime(volume * gainRight, now);
813
799
  }
814
800
  setSustainPedal(channelNumber, value) {
815
801
  const isOn = value >= 64;
@@ -831,8 +817,7 @@ export class MidyGM1 {
831
817
  const { dataMSB, dataLSB } = channel;
832
818
  switch (rpn) {
833
819
  case 0:
834
- channel.pitchBendRange = dataMSB + dataLSB / 100;
835
- break;
820
+ return this.handlePitchBendRangeMessage(channelNumber, dataMSB, dataLSB);
836
821
  case 1:
837
822
  channel.fineTuning = (dataMSB * 128 + dataLSB - 8192) / 8192;
838
823
  break;
@@ -843,6 +828,26 @@ export class MidyGM1 {
843
828
  console.warn(`Channel ${channelNumber}: Unsupported RPN MSB=${channel.rpnMSB} LSB=${channel.rpnLSB}`);
844
829
  }
845
830
  }
831
+ handlePitchBendRangeMessage(channelNumber, dataMSB, dataLSB) {
832
+ const pitchBendRange = dataMSB + dataLSB / 100;
833
+ this.setPitchBendRange(channelNumber, pitchBendRange);
834
+ }
835
+ setPitchBendRange(channelNumber, pitchBendRange) {
836
+ const now = this.audioContext.currentTime;
837
+ const channel = this.channels[channelNumber];
838
+ const prevPitchBendRange = channel.pitchBendRange;
839
+ channel.pitchBendRange = pitchBendRange;
840
+ const detuneChange = (channel.pitchBendRange - prevPitchBendRange) *
841
+ channel.pitchBend * 100;
842
+ const activeNotes = this.getActiveNotes(channel, now);
843
+ activeNotes.forEach((activeNote) => {
844
+ const { bufferSource } = activeNote;
845
+ const detune = bufferSource.detune.value + detuneChange;
846
+ bufferSource.detune
847
+ .cancelScheduledValues(now)
848
+ .setValueAtTime(detune, now);
849
+ });
850
+ }
846
851
  allSoundOff(channelNumber) {
847
852
  const now = this.audioContext.currentTime;
848
853
  const channel = this.channels[channelNumber];
@@ -918,9 +923,9 @@ export class MidyGM1 {
918
923
  }
919
924
  handleMasterVolumeSysEx(data) {
920
925
  const volume = (data[5] * 128 + data[4]) / 16383;
921
- this.handleMasterVolume(volume);
926
+ this.setMasterVolume(volume);
922
927
  }
923
- handleMasterVolume(volume) {
928
+ setMasterVolume(volume) {
924
929
  if (volume < 0 && 1 < volume) {
925
930
  console.error("Master Volume is out of range");
926
931
  }
@@ -961,7 +966,7 @@ Object.defineProperty(MidyGM1, "channelSettings", {
961
966
  writable: true,
962
967
  value: {
963
968
  volume: 100 / 127,
964
- pan: 0,
969
+ pan: 64,
965
970
  bank: 0,
966
971
  dataMSB: 0,
967
972
  dataLSB: 0,
package/esm/midy-GM2.d.ts CHANGED
@@ -234,12 +234,16 @@ export class MidyGM2 {
234
234
  handleProgramChange(channelNumber: any, program: any): void;
235
235
  handleChannelPressure(channelNumber: any, pressure: any): void;
236
236
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
237
- handlePitchBend(channelNumber: any, pitchBend: any): void;
237
+ setPitchBend(channelNumber: any, pitchBend: any): void;
238
238
  handleControlChange(channelNumber: any, controller: any, value: any): void | any[];
239
239
  setBankMSB(channelNumber: any, msb: any): void;
240
240
  setModulation(channelNumber: any, modulation: any): void;
241
241
  setPortamentoTime(channelNumber: any, portamentoTime: any): void;
242
242
  setVolume(channelNumber: any, volume: any): void;
243
+ panToGain(pan: any): {
244
+ gainLeft: number;
245
+ gainRight: number;
246
+ };
243
247
  setPan(channelNumber: any, pan: any): void;
244
248
  setExpression(channelNumber: any, expression: any): void;
245
249
  setBankLSB(channelNumber: any, lsb: any): void;
@@ -253,6 +257,8 @@ export class MidyGM2 {
253
257
  setRPNMSB(channelNumber: any, value: any): void;
254
258
  setRPNLSB(channelNumber: any, value: any): void;
255
259
  setDataEntry(channelNumber: any, value: any, isMSB: any): void;
260
+ handlePitchBendRangeMessage(channelNumber: any, dataMSB: any, dataLSB: any): void;
261
+ setPitchBendRange(channelNumber: any, pitchBendRange: any): void;
256
262
  allSoundOff(channelNumber: any): any[];
257
263
  resetAllControllers(channelNumber: any): void;
258
264
  allNotesOff(channelNumber: any): any[];
@@ -265,11 +271,11 @@ export class MidyGM2 {
265
271
  GM2SystemOn(): void;
266
272
  handleUniversalRealTimeExclusiveMessage(data: any): void;
267
273
  handleMasterVolumeSysEx(data: any): void;
268
- handleMasterVolume(volume: any): void;
274
+ setMasterVolume(volume: any): void;
269
275
  handleMasterFineTuningSysEx(data: any): void;
270
- handleMasterFineTuning(fineTuning: any): void;
276
+ setMasterFineTuning(fineTuning: any): void;
271
277
  handleMasterCoarseTuningSysEx(data: any): void;
272
- handleMasterCoarseTuning(coarseTuning: any): void;
278
+ setMasterCoarseTuning(coarseTuning: any): void;
273
279
  handleExclusiveMessage(data: any): void;
274
280
  handleSysEx(data: any): void;
275
281
  scheduleTask(callback: any, startTime: any): Promise<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAuBA;IAwBE;;;;;;;;;;;;;;;;;MAiBE;IAEF;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IAtED,qBAAmB;IACnB,kBAAc;IACd,qBAAmB;IACnB,yBAAqB;IACrB,2BAAuB;IACvB,cAAa;IACb,cAAa;IACb,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;IA4ChB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;;;;;;;;;;;MAoBC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAcC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EAkDC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA2GC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED;;;;MAoCC;IAED;;;;;MA2CC;IAED,sDA2BC;IAED,2BAEC;IAED,4BAEC;IAED,sCAKC;IAED,mFAGC;IAED,iDAmBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHAiCC;IAED,gDAQC;IAED,kGAgCC;IAED,0EAGC;IAED,sIAoDC;IAED,0FAGC;IAED,kEAeC;IAED,oEAYC;IAED,wFAmBC;IAED,4DAIC;IAED,+DAcC;IAED,qEAGC;IAED,0DAiBC;IAED,mFAuDC;IAED,+CAEC;IAED,yDAiBC;IAED,iEAEC;IAED,iDAIC;IAED,2CAMC;IAED,yDAIC;IAED,+CAEC;IAED,sCAKC;IAED,sDAMC;IAED,oDAEC;IAED,iDASC;IAED,iDAIC;IAED,wDAUC;IAED,uDAGC;IAED,gDAEC;IAED,gDAEC;IAED,+DAuBC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,gBAEC;IAED,eAEC;IAED,eAEC;IAED,eAEC;IAED,4DAmBC;IAED,oBAQC;IAED,oBAQC;IAED,yDAgDC;IAED,yCAGC;IAED,sCAQC;IAED,6CAGC;IAED,8CAMC;IAED,+CAGC;IAED,kDAMC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAv3CD;IASE,gFAKC;IAbD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
1
+ {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAuBA;IAwBE;;;;;;;;;;;;;;;;;MAiBE;IAEF;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IAtED,qBAAmB;IACnB,kBAAc;IACd,qBAAmB;IACnB,yBAAqB;IACrB,2BAAuB;IACvB,cAAa;IACb,cAAa;IACb,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;IA4ChB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;;;;;;;;;;;MAoBC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAcC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EAkDC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgGC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED;;;;MAoCC;IAED;;;;;MAqCC;IAED,sDA2BC;IAED,2BAEC;IAED,4BAEC;IAED,sCAKC;IAED,mFAGC;IAED,iDAiBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHAiCC;IAED,gDAQC;IAED,kGAgCC;IAED,0EAGC;IAED,sIAoDC;IAED,0FAGC;IAED,kEAeC;IAED,oEAYC;IAED,wFAmBC;IAED,4DAIC;IAED,+DAcC;IAED,qEAGC;IAED,uDAeC;IAED,mFAuDC;IAED,+CAEC;IAED,yDAiBC;IAED,iEAEC;IAED,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,+CAEC;IAED,sCAUC;IAED,sDAMC;IAED,oDAEC;IAED,iDASC;IAED,iDAIC;IAED,wDAWC;IAED,uDAGC;IAED,gDAEC;IAED,gDAEC;IAED,+DA0BC;IAED,kFAGC;IAED,iEAeC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,gBAEC;IAED,eAEC;IAED,eAEC;IAED,eAEC;IAED,4DAmBC;IAED,oBAQC;IAED,oBAQC;IAED,yDAgDC;IAED,yCAGC;IAED,mCAQC;IAED,6CAGC;IAED,2CAMC;IAED,+CAGC;IAED,+CAMC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAv4CD;IASE,gFAKC;IAbD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
package/esm/midy-GM2.js CHANGED
@@ -334,7 +334,7 @@ export class MidyGM2 {
334
334
  this.handleChannelPressure(event.channel, event.amount);
335
335
  break;
336
336
  case "pitchBend":
337
- this.handlePitchBend(event.channel, event.value);
337
+ this.setPitchBend(event.channel, event.value);
338
338
  break;
339
339
  case "sysEx":
340
340
  this.handleSysEx(event.data);
@@ -414,7 +414,6 @@ export class MidyGM2 {
414
414
  const tmpChannels = new Array(16);
415
415
  for (let i = 0; i < tmpChannels.length; i++) {
416
416
  tmpChannels[i] = {
417
- durationTicks: new Map(),
418
417
  programNumber: -1,
419
418
  bankMSB: this.channels[i].bankMSB,
420
419
  bankLSB: this.channels[i].bankLSB,
@@ -444,16 +443,6 @@ export class MidyGM2 {
444
443
  }
445
444
  channel.programNumber = 0;
446
445
  }
447
- channel.durationTicks.set(event.noteNumber, {
448
- ticks: event.ticks,
449
- noteOn: event,
450
- });
451
- break;
452
- }
453
- case "noteOff": {
454
- const { ticks, noteOn } = tmpChannels[event.channel].durationTicks
455
- .get(event.noteNumber);
456
- noteOn.durationTicks = event.ticks - ticks;
457
446
  break;
458
447
  }
459
448
  case "controller":
@@ -488,8 +477,8 @@ export class MidyGM2 {
488
477
  });
489
478
  });
490
479
  const priority = {
491
- setTempo: 0,
492
- controller: 1,
480
+ controller: 0,
481
+ sysEx: 1,
493
482
  };
494
483
  timeline.sort((a, b) => {
495
484
  if (a.ticks !== b.ticks)
@@ -627,12 +616,8 @@ export class MidyGM2 {
627
616
  }
628
617
  createChorusEffect(audioContext, options = {}) {
629
618
  const { chorusCount = 2, chorusRate = 0.6, chorusDepth = 0.15, delay = 0.01, variance = delay * 0.1, } = options;
630
- const lfo = new OscillatorNode(audioContext, {
631
- frequency: chorusRate,
632
- });
633
- const lfoGain = new GainNode(audioContext, {
634
- gain: chorusDepth,
635
- });
619
+ const lfo = new OscillatorNode(audioContext, { frequency: chorusRate });
620
+ const lfoGain = new GainNode(audioContext, { gain: chorusDepth });
636
621
  const chorusGains = [];
637
622
  const delayNodes = [];
638
623
  const baseGain = 1 / chorusCount;
@@ -643,9 +628,7 @@ export class MidyGM2 {
643
628
  maxDelayTime: delayTime,
644
629
  });
645
630
  delayNodes.push(delayNode);
646
- const chorusGain = new GainNode(audioContext, {
647
- gain: baseGain,
648
- });
631
+ const chorusGain = new GainNode(audioContext, { gain: baseGain });
649
632
  chorusGains.push(chorusGain);
650
633
  lfo.connect(lfoGain);
651
634
  lfoGain.connect(delayNode.delayTime);
@@ -707,9 +690,7 @@ export class MidyGM2 {
707
690
  }
708
691
  setVolumeEnvelope(channel, note) {
709
692
  const { instrumentKey, startTime, velocity } = note;
710
- note.gainNode = new GainNode(this.audioContext, {
711
- gain: 0,
712
- });
693
+ note.gainNode = new GainNode(this.audioContext, { gain: 0 });
713
694
  let volume = (velocity / 127) * channel.volume * channel.expression;
714
695
  if (volume === 0)
715
696
  volume = 1e-6; // exponentialRampToValueAtTime() requires a non-zero value
@@ -948,20 +929,22 @@ export class MidyGM2 {
948
929
  }
949
930
  handlePitchBendMessage(channelNumber, lsb, msb) {
950
931
  const pitchBend = msb * 128 + lsb;
951
- this.handlePitchBend(channelNumber, pitchBend);
932
+ this.setPitchBend(channelNumber, pitchBend);
952
933
  }
953
- handlePitchBend(channelNumber, pitchBend) {
934
+ setPitchBend(channelNumber, pitchBend) {
954
935
  const now = this.audioContext.currentTime;
955
936
  const channel = this.channels[channelNumber];
937
+ const prevPitchBend = channel.pitchBend;
956
938
  channel.pitchBend = (pitchBend - 8192) / 8192;
957
- const semitoneOffset = this.calcSemitoneOffset(channel);
939
+ const detuneChange = (channel.pitchBend - prevPitchBend) *
940
+ channel.pitchBendRange * 100;
958
941
  const activeNotes = this.getActiveNotes(channel, now);
959
942
  activeNotes.forEach((activeNote) => {
960
- const { bufferSource, instrumentKey, noteNumber } = activeNote;
961
- const playbackRate = calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
962
- bufferSource.playbackRate
943
+ const { bufferSource } = activeNote;
944
+ const detune = bufferSource.detune.value + detuneChange;
945
+ bufferSource.detune
963
946
  .cancelScheduledValues(now)
964
- .setValueAtTime(playbackRate * pressure, now);
947
+ .setValueAtTime(detune, now);
965
948
  });
966
949
  }
967
950
  handleControlChange(channelNumber, controller, value) {
@@ -1045,12 +1028,17 @@ export class MidyGM2 {
1045
1028
  channel.volume = volume / 127;
1046
1029
  this.updateChannelGain(channel);
1047
1030
  }
1031
+ panToGain(pan) {
1032
+ const theta = Math.PI / 2 * Math.max(0, pan - 1) / 126;
1033
+ return {
1034
+ gainLeft: Math.cos(theta),
1035
+ gainRight: Math.sin(theta),
1036
+ };
1037
+ }
1048
1038
  setPan(channelNumber, pan) {
1049
- const now = this.audioContext.currentTime;
1050
1039
  const channel = this.channels[channelNumber];
1051
- channel.pan = pan / 127 * 2 - 1; // -1 (left) - +1 (right)
1052
- channel.pannerNode.pan.cancelScheduledValues(now);
1053
- channel.pannerNode.pan.setValueAtTime(channel.pan, now);
1040
+ channel.pan = pan;
1041
+ this.updateChannelGain(channel);
1054
1042
  }
1055
1043
  setExpression(channelNumber, expression) {
1056
1044
  const channel = this.channels[channelNumber];
@@ -1063,8 +1051,13 @@ export class MidyGM2 {
1063
1051
  updateChannelGain(channel) {
1064
1052
  const now = this.audioContext.currentTime;
1065
1053
  const volume = channel.volume * channel.expression;
1066
- channel.gainNode.gain.cancelScheduledValues(now);
1067
- channel.gainNode.gain.setValueAtTime(volume, now);
1054
+ const { gainLeft, gainRight } = this.panToGain(channel.pan);
1055
+ channel.gainL.gain
1056
+ .cancelScheduledValues(now)
1057
+ .setValueAtTime(volume * gainLeft, now);
1058
+ channel.gainR.gain
1059
+ .cancelScheduledValues(now)
1060
+ .setValueAtTime(volume * gainRight, now);
1068
1061
  }
1069
1062
  setSustainPedal(channelNumber, value) {
1070
1063
  const isOn = value >= 64;
@@ -1096,7 +1089,8 @@ export class MidyGM2 {
1096
1089
  const channel = this.channels[channelNumber];
1097
1090
  channel.sostenutoPedal = isOn;
1098
1091
  if (isOn) {
1099
- const activeNotes = this.getActiveNotes(channel);
1092
+ const now = this.audioContext.currentTime;
1093
+ const activeNotes = this.getActiveNotes(channel, now);
1100
1094
  channel.sostenutoNotes = new Map(activeNotes);
1101
1095
  }
1102
1096
  else {
@@ -1120,8 +1114,7 @@ export class MidyGM2 {
1120
1114
  const { dataMSB, dataLSB } = channel;
1121
1115
  switch (rpn) {
1122
1116
  case 0:
1123
- channel.pitchBendRange = dataMSB + dataLSB / 100;
1124
- break;
1117
+ return this.handlePitchBendRangeMessage(channelNumber, dataMSB, dataLSB);
1125
1118
  case 1:
1126
1119
  channel.fineTuning = (dataMSB * 128 + dataLSB - 8192) / 8192;
1127
1120
  break;
@@ -1135,6 +1128,26 @@ export class MidyGM2 {
1135
1128
  console.warn(`Channel ${channelNumber}: Unsupported RPN MSB=${channel.rpnMSB} LSB=${channel.rpnLSB}`);
1136
1129
  }
1137
1130
  }
1131
+ handlePitchBendRangeMessage(channelNumber, dataMSB, dataLSB) {
1132
+ const pitchBendRange = dataMSB + dataLSB / 100;
1133
+ this.setPitchBendRange(channelNumber, pitchBendRange);
1134
+ }
1135
+ setPitchBendRange(channelNumber, pitchBendRange) {
1136
+ const now = this.audioContext.currentTime;
1137
+ const channel = this.channels[channelNumber];
1138
+ const prevPitchBendRange = channel.pitchBendRange;
1139
+ channel.pitchBendRange = pitchBendRange;
1140
+ const detuneChange = (channel.pitchBendRange - prevPitchBendRange) *
1141
+ channel.pitchBend * 100;
1142
+ const activeNotes = this.getActiveNotes(channel, now);
1143
+ activeNotes.forEach((activeNote) => {
1144
+ const { bufferSource } = activeNote;
1145
+ const detune = bufferSource.detune.value + detuneChange;
1146
+ bufferSource.detune
1147
+ .cancelScheduledValues(now)
1148
+ .setValueAtTime(detune, now);
1149
+ });
1150
+ }
1138
1151
  allSoundOff(channelNumber) {
1139
1152
  const now = this.audioContext.currentTime;
1140
1153
  const channel = this.channels[channelNumber];
@@ -1225,9 +1238,9 @@ export class MidyGM2 {
1225
1238
  case 1:
1226
1239
  return this.handleMasterVolumeSysEx(data);
1227
1240
  case 3:
1228
- return this.handleMasterFineTuning(data);
1241
+ return this.handleMasterFineTuningSysEx(data);
1229
1242
  case 4:
1230
- return this.handleMasterCoarseTuning(data);
1243
+ return this.handleMasterCoarseTuningSysEx(data);
1231
1244
  // case 5: // TODO: Global Parameter Control
1232
1245
  default:
1233
1246
  console.warn(`Unsupported Exclusive Message ${data}`);
@@ -1269,9 +1282,9 @@ export class MidyGM2 {
1269
1282
  }
1270
1283
  handleMasterVolumeSysEx(data) {
1271
1284
  const volume = (data[5] * 128 + data[4]) / 16383;
1272
- this.handleMasterVolume(volume);
1285
+ this.setMasterVolume(volume);
1273
1286
  }
1274
- handleMasterVolume(volume) {
1287
+ setMasterVolume(volume) {
1275
1288
  if (volume < 0 && 1 < volume) {
1276
1289
  console.error("Master Volume is out of range");
1277
1290
  }
@@ -1283,9 +1296,9 @@ export class MidyGM2 {
1283
1296
  }
1284
1297
  handleMasterFineTuningSysEx(data) {
1285
1298
  const fineTuning = (data[5] * 128 + data[4] - 8192) / 8192;
1286
- this.handleMasterFineTuning(fineTuning);
1299
+ this.setMasterFineTuning(fineTuning);
1287
1300
  }
1288
- handleMasterFineTuning(fineTuning) {
1301
+ setMasterFineTuning(fineTuning) {
1289
1302
  if (fineTuning < -1 && 1 < fineTuning) {
1290
1303
  console.error("Master Fine Tuning value is out of range");
1291
1304
  }
@@ -1295,9 +1308,9 @@ export class MidyGM2 {
1295
1308
  }
1296
1309
  handleMasterCoarseTuningSysEx(data) {
1297
1310
  const coarseTuning = data[4];
1298
- this.handleMasterCoarseTuning(coarseTuning);
1311
+ this.setMasterCoarseTuning(coarseTuning);
1299
1312
  }
1300
- handleMasterCoarseTuning(coarseTuning) {
1313
+ setMasterCoarseTuning(coarseTuning) {
1301
1314
  if (coarseTuning < 0 && 127 < coarseTuning) {
1302
1315
  console.error("Master Coarse Tuning value is out of range");
1303
1316
  }
@@ -39,8 +39,8 @@ export class MidyGMLite {
39
39
  masterGain: any;
40
40
  channels: {
41
41
  scheduledNotes: Map<any, any>;
42
- gainNode: any;
43
- pannerNode: any;
42
+ gainL: any;
43
+ gainR: any;
44
44
  expression: number;
45
45
  modulation: number;
46
46
  sustainPedal: boolean;
@@ -61,13 +61,13 @@ export class MidyGMLite {
61
61
  loadSoundFont(soundFontUrl: any): Promise<void>;
62
62
  loadMIDI(midiUrl: any): Promise<void>;
63
63
  setChannelAudioNodes(audioContext: any): {
64
- gainNode: any;
65
- pannerNode: any;
64
+ gainL: any;
65
+ gainR: any;
66
66
  };
67
67
  createChannels(audioContext: any): {
68
68
  scheduledNotes: Map<any, any>;
69
- gainNode: any;
70
- pannerNode: any;
69
+ gainL: any;
70
+ gainR: any;
71
71
  expression: number;
72
72
  modulation: number;
73
73
  sustainPedal: boolean;
@@ -122,10 +122,14 @@ export class MidyGMLite {
122
122
  handleMIDIMessage(statusByte: any, data1: any, data2: any): void | any[] | Promise<any>;
123
123
  handleProgramChange(channelNumber: any, program: any): void;
124
124
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
125
- handlePitchBend(channelNumber: any, pitchBend: any): void;
125
+ setPitchBend(channelNumber: any, pitchBend: any): void;
126
126
  handleControlChange(channelNumber: any, controller: any, value: any): void | any[];
127
127
  setModulation(channelNumber: any, modulation: any): void;
128
128
  setVolume(channelNumber: any, volume: any): void;
129
+ panToGain(pan: any): {
130
+ gainLeft: number;
131
+ gainRight: number;
132
+ };
129
133
  setPan(channelNumber: any, pan: any): void;
130
134
  setExpression(channelNumber: any, expression: any): void;
131
135
  updateChannelGain(channel: any): void;
@@ -133,6 +137,8 @@ export class MidyGMLite {
133
137
  setRPNMSB(channelNumber: any, value: any): void;
134
138
  setRPNLSB(channelNumber: any, value: any): void;
135
139
  setDataEntry(channelNumber: any, value: any, isMSB: any): void;
140
+ handlePitchBendRangeMessage(channelNumber: any, dataMSB: any, dataLSB: any): void;
141
+ setPitchBendRange(channelNumber: any, pitchBendRange: any): void;
136
142
  allSoundOff(channelNumber: any): any[];
137
143
  resetAllControllers(channelNumber: any): void;
138
144
  allNotesOff(channelNumber: any): any[];
@@ -140,7 +146,7 @@ export class MidyGMLite {
140
146
  GM1SystemOn(): void;
141
147
  handleUniversalRealTimeExclusiveMessage(data: any): void;
142
148
  handleMasterVolumeSysEx(data: any): void;
143
- handleMasterVolume(volume: any): void;
149
+ setMasterVolume(volume: any): void;
144
150
  handleExclusiveMessage(data: any): void;
145
151
  handleSysEx(data: any): void;
146
152
  scheduleTask(callback: any, startTime: any): Promise<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAqBA;IAmBE;;;;;;;;;MASE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA5CD,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;IAuBhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;MAaC;IAED;;;;;;;;;;;;;;;;;;QAUC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EA+CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAyEC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,sDAEC;IAED,2BAEC;IAED,4BAEC;IAED,yCAEC;IAED,mFAGC;IAED,iDAmBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHA6BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIAmDC;IAED,0FAGC;IAED,kEAeC;IAED,wFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,0DAiBC;IAED,mFA+BC;IAED,yDAiBC;IAED,iDAIC;IAED,2CAMC;IAED,yDAIC;IAED,sCAKC;IAED,sDAMC;IAED,gDAEC;IAED,gDAEC;IAED,+DAcC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,sCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AA59BD;IAOE,gFAKC;IAXD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
1
+ {"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAqBA;IAmBE;;;;;;;;;MASE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA5CD,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;IAuBhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;MAcC;IAED;;;;;;;;;;;;;;;;;;QAUC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EA+CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA8DC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,sDAEC;IAED,2BAEC;IAED,4BAEC;IAED,yCAEC;IAED,mFAGC;IAED,iDAiBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHA6BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIAmDC;IAED,0FAGC;IAED,kEAeC;IAED,wFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,uDAeC;IAED,mFA+BC;IAED,yDAiBC;IAED,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,sCAUC;IAED,sDAMC;IAED,gDAEC;IAED,gDAEC;IAED,+DAiBC;IAED,kFAGC;IAED,iEAeC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAl/BD;IAOE,gFAKC;IAXD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}