@marmooo/midy 0.0.5 → 0.0.7

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.
@@ -35,18 +35,6 @@ class Note {
35
35
  writable: true,
36
36
  value: void 0
37
37
  });
38
- Object.defineProperty(this, "vibLFO", {
39
- enumerable: true,
40
- configurable: true,
41
- writable: true,
42
- value: void 0
43
- });
44
- Object.defineProperty(this, "vibLFOGain", {
45
- enumerable: true,
46
- configurable: true,
47
- writable: true,
48
- value: void 0
49
- });
50
38
  this.noteNumber = noteNumber;
51
39
  this.velocity = velocity;
52
40
  this.startTime = startTime;
@@ -198,17 +186,16 @@ class MidyGM1 {
198
186
  this.totalTime = this.calcTotalTime();
199
187
  }
200
188
  setChannelAudioNodes(audioContext) {
201
- const gainNode = new GainNode(audioContext, {
202
- gain: MidyGM1.channelSettings.volume,
203
- });
204
- const pannerNode = new StereoPannerNode(audioContext, {
205
- pan: MidyGM1.channelSettings.pan,
206
- });
207
- pannerNode.connect(gainNode);
208
- gainNode.connect(this.masterGain);
189
+ const { gainLeft, gainRight } = this.panToGain(MidyGM1.channelSettings.pan);
190
+ const gainL = new GainNode(audioContext, { gain: gainLeft });
191
+ const gainR = new GainNode(audioContext, { gain: gainRight });
192
+ const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
193
+ gainL.connect(merger, 0, 0);
194
+ gainR.connect(merger, 0, 1);
195
+ merger.connect(this.masterGain);
209
196
  return {
210
- gainNode,
211
- pannerNode,
197
+ gainL,
198
+ gainR,
212
199
  };
213
200
  }
214
201
  createChannels(audioContext) {
@@ -293,7 +280,7 @@ class MidyGM1 {
293
280
  this.handleProgramChange(event.channel, event.programNumber);
294
281
  break;
295
282
  case "pitchBend":
296
- this.handlePitchBend(event.channel, event.value);
283
+ this.setPitchBend(event.channel, event.value);
297
284
  break;
298
285
  case "sysEx":
299
286
  this.handleSysEx(event.data);
@@ -373,7 +360,6 @@ class MidyGM1 {
373
360
  const tmpChannels = new Array(16);
374
361
  for (let i = 0; i < tmpChannels.length; i++) {
375
362
  tmpChannels[i] = {
376
- durationTicks: new Map(),
377
363
  programNumber: -1,
378
364
  bank: this.channels[i].bank,
379
365
  };
@@ -390,16 +376,6 @@ class MidyGM1 {
390
376
  instruments.add(`${channel.bank}:0`);
391
377
  channel.programNumber = 0;
392
378
  }
393
- channel.durationTicks.set(event.noteNumber, {
394
- ticks: event.ticks,
395
- noteOn: event,
396
- });
397
- break;
398
- }
399
- case "noteOff": {
400
- const { ticks, noteOn } = tmpChannels[event.channel].durationTicks
401
- .get(event.noteNumber);
402
- noteOn.durationTicks = event.ticks - ticks;
403
379
  break;
404
380
  }
405
381
  case "programChange": {
@@ -413,8 +389,8 @@ class MidyGM1 {
413
389
  });
414
390
  });
415
391
  const priority = {
416
- setTempo: 0,
417
- controller: 1,
392
+ controller: 0,
393
+ sysEx: 1,
418
394
  };
419
395
  timeline.sort((a, b) => {
420
396
  if (a.ticks !== b.ticks)
@@ -519,7 +495,8 @@ class MidyGM1 {
519
495
  return noteList[0];
520
496
  }
521
497
  connectNoteEffects(channel, gainNode) {
522
- gainNode.connect(channel.pannerNode);
498
+ gainNode.connect(channel.gainL);
499
+ gainNode.connect(channel.gainR);
523
500
  }
524
501
  cbToRatio(cb) {
525
502
  return Math.pow(10, cb / 200);
@@ -537,9 +514,7 @@ class MidyGM1 {
537
514
  }
538
515
  setVolumeEnvelope(channel, note) {
539
516
  const { instrumentKey, startTime, velocity } = note;
540
- note.gainNode = new GainNode(this.audioContext, {
541
- gain: 0,
542
- });
517
+ note.gainNode = new GainNode(this.audioContext, { gain: 0 });
543
518
  let volume = (velocity / 127) * channel.volume * channel.expression;
544
519
  if (volume === 0)
545
520
  volume = 1e-6; // exponentialRampToValueAtTime() requires a non-zero value
@@ -729,21 +704,15 @@ class MidyGM1 {
729
704
  }
730
705
  handlePitchBendMessage(channelNumber, lsb, msb) {
731
706
  const pitchBend = msb * 128 + lsb;
732
- this.handlePitchBend(channelNumber, pitchBend);
707
+ this.setPitchBend(channelNumber, pitchBend);
733
708
  }
734
- handlePitchBend(channelNumber, pitchBend) {
735
- const now = this.audioContext.currentTime;
709
+ setPitchBend(channelNumber, pitchBend) {
736
710
  const channel = this.channels[channelNumber];
711
+ const prevPitchBend = channel.pitchBend;
737
712
  channel.pitchBend = (pitchBend - 8192) / 8192;
738
- const semitoneOffset = this.calcSemitoneOffset(channel);
739
- const activeNotes = this.getActiveNotes(channel, now);
740
- activeNotes.forEach((activeNote) => {
741
- const { bufferSource, instrumentKey, noteNumber } = activeNote;
742
- const playbackRate = calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
743
- bufferSource.playbackRate
744
- .cancelScheduledValues(now)
745
- .setValueAtTime(playbackRate * pressure, now);
746
- });
713
+ const detuneChange = (channel.pitchBend - prevPitchBend) *
714
+ channel.pitchBendRange * 100;
715
+ this.updateDetune(channel, detuneChange);
747
716
  }
748
717
  handleControlChange(channelNumber, controller, value) {
749
718
  switch (controller) {
@@ -762,9 +731,9 @@ class MidyGM1 {
762
731
  case 64:
763
732
  return this.setSustainPedal(channelNumber, value);
764
733
  case 100:
765
- return this.setRPNMSB(channelNumber, value);
766
- case 101:
767
734
  return this.setRPNLSB(channelNumber, value);
735
+ case 101:
736
+ return this.setRPNMSB(channelNumber, value);
768
737
  case 120:
769
738
  return this.allSoundOff(channelNumber);
770
739
  case 121:
@@ -796,12 +765,17 @@ class MidyGM1 {
796
765
  channel.volume = volume / 127;
797
766
  this.updateChannelGain(channel);
798
767
  }
768
+ panToGain(pan) {
769
+ const theta = Math.PI / 2 * Math.max(0, pan - 1) / 126;
770
+ return {
771
+ gainLeft: Math.cos(theta),
772
+ gainRight: Math.sin(theta),
773
+ };
774
+ }
799
775
  setPan(channelNumber, pan) {
800
- const now = this.audioContext.currentTime;
801
776
  const channel = this.channels[channelNumber];
802
- channel.pan = pan / 127 * 2 - 1; // -1 (left) - +1 (right)
803
- channel.pannerNode.pan.cancelScheduledValues(now);
804
- channel.pannerNode.pan.setValueAtTime(channel.pan, now);
777
+ channel.pan = pan;
778
+ this.updateChannelGain(channel);
805
779
  }
806
780
  setExpression(channelNumber, expression) {
807
781
  const channel = this.channels[channelNumber];
@@ -811,8 +785,13 @@ class MidyGM1 {
811
785
  updateChannelGain(channel) {
812
786
  const now = this.audioContext.currentTime;
813
787
  const volume = channel.volume * channel.expression;
814
- channel.gainNode.gain.cancelScheduledValues(now);
815
- channel.gainNode.gain.setValueAtTime(volume, now);
788
+ const { gainLeft, gainRight } = this.panToGain(channel.pan);
789
+ channel.gainL.gain
790
+ .cancelScheduledValues(now)
791
+ .setValueAtTime(volume * gainLeft, now);
792
+ channel.gainR.gain
793
+ .cancelScheduledValues(now)
794
+ .setValueAtTime(volume * gainRight, now);
816
795
  }
817
796
  setSustainPedal(channelNumber, value) {
818
797
  const isOn = value >= 64;
@@ -821,31 +800,105 @@ class MidyGM1 {
821
800
  this.releaseSustainPedal(channelNumber, value);
822
801
  }
823
802
  }
824
- setRPNMSB(channelNumber, value) {
825
- this.channels[channelNumber].rpnMSB = value;
803
+ limitData(channel, minMSB, maxMSB, minLSB, maxLSB) {
804
+ if (maxLSB < channel.dataLSB) {
805
+ channel.dataMSB++;
806
+ channel.dataLSB = minLSB;
807
+ }
808
+ else if (channel.dataLSB < 0) {
809
+ channel.dataMSB--;
810
+ channel.dataLSB = maxLSB;
811
+ }
812
+ if (maxMSB < channel.dataMSB) {
813
+ channel.dataMSB = maxMSB;
814
+ channel.dataLSB = maxLSB;
815
+ }
816
+ else if (channel.dataMSB < 0) {
817
+ channel.dataMSB = minMSB;
818
+ channel.dataLSB = minLSB;
819
+ }
826
820
  }
827
- setRPNLSB(channelNumber, value) {
828
- this.channels[channelNumber].rpnLSB = value;
821
+ limitDataMSB(channel, minMSB, maxMSB) {
822
+ if (maxMSB < channel.dataMSB) {
823
+ channel.dataMSB = maxMSB;
824
+ }
825
+ else if (channel.dataMSB < 0) {
826
+ channel.dataMSB = minMSB;
827
+ }
829
828
  }
830
- setDataEntry(channelNumber, value, isMSB) {
829
+ handleRPN(channelNumber) {
831
830
  const channel = this.channels[channelNumber];
832
831
  const rpn = channel.rpnMSB * 128 + channel.rpnLSB;
833
- isMSB ? channel.dataMSB = value : channel.dataLSB = value;
834
- const { dataMSB, dataLSB } = channel;
835
832
  switch (rpn) {
836
833
  case 0:
837
- channel.pitchBendRange = dataMSB + dataLSB / 100;
834
+ this.handlePitchBendRangeMessage(channelNumber);
838
835
  break;
839
836
  case 1:
840
- channel.fineTuning = (dataMSB * 128 + dataLSB - 8192) / 8192;
837
+ this.handleFineTuningMessage(channelNumber);
841
838
  break;
842
839
  case 2:
843
- channel.coarseTuning = dataMSB - 64;
840
+ this.handleCoarseTuningMessage(channelNumber);
844
841
  break;
845
842
  default:
846
843
  console.warn(`Channel ${channelNumber}: Unsupported RPN MSB=${channel.rpnMSB} LSB=${channel.rpnLSB}`);
847
844
  }
848
845
  }
846
+ setRPNMSB(channelNumber, value) {
847
+ this.channels[channelNumber].rpnMSB = value;
848
+ }
849
+ setRPNLSB(channelNumber, value) {
850
+ this.channels[channelNumber].rpnLSB = value;
851
+ }
852
+ setDataEntry(channelNumber, value, isMSB) {
853
+ const channel = this.channels[channelNumber];
854
+ isMSB ? channel.dataMSB = value : channel.dataLSB = value;
855
+ this.handleRPN(channelNumber);
856
+ }
857
+ updateDetune(channel, detuneChange) {
858
+ const now = this.audioContext.currentTime;
859
+ const activeNotes = this.getActiveNotes(channel, now);
860
+ activeNotes.forEach((activeNote) => {
861
+ const { bufferSource } = activeNote;
862
+ const detune = bufferSource.detune.value + detuneChange;
863
+ bufferSource.detune
864
+ .cancelScheduledValues(now)
865
+ .setValueAtTime(detune, now);
866
+ });
867
+ }
868
+ handlePitchBendRangeMessage(channelNumber) {
869
+ const channel = this.channels[channelNumber];
870
+ this.limitData(channel, 0, 127, 0, 99);
871
+ const pitchBendRange = channel.dataMSB + channel.dataLSB / 100;
872
+ this.setPitchBendRange(channelNumber, pitchBendRange);
873
+ }
874
+ setPitchBendRange(channelNumber, pitchBendRange) {
875
+ const channel = this.channels[channelNumber];
876
+ const prevPitchBendRange = channel.pitchBendRange;
877
+ channel.pitchBendRange = pitchBendRange;
878
+ const detuneChange = (channel.pitchBendRange - prevPitchBendRange) *
879
+ channel.pitchBend * 100;
880
+ this.updateDetune(channel, detuneChange);
881
+ }
882
+ handleFineTuningMessage(channelNumber) {
883
+ const channel = this.channels[channelNumber];
884
+ this.limitData(channel, 0, 127, 0, 127);
885
+ const fineTuning = (channel.dataMSB * 128 + channel.dataLSB - 8192) / 8192;
886
+ this.setFineTuning(channelNumber, fineTuning);
887
+ }
888
+ setFineTuning(channelNumber, fineTuning) {
889
+ const channel = this.channels[channelNumber];
890
+ channel.fineTuning = fineTuning;
891
+ }
892
+ handleCoarseTuningMessage(channelNumber) {
893
+ const channel = this.channels[channelNumber];
894
+ this.limitDataMSB(channel, 0, 127);
895
+ const coarseTuning = channel.dataMSB - 64;
896
+ this.setFineTuning(channelNumber, coarseTuning);
897
+ }
898
+ setCoarseTuning(channelNumber, coarseTuning) {
899
+ const channel = this.channels[channelNumber];
900
+ channel.fineTuning = coarseTuning;
901
+ }
849
902
  allSoundOff(channelNumber) {
850
903
  const now = this.audioContext.currentTime;
851
904
  const channel = this.channels[channelNumber];
@@ -921,9 +974,9 @@ class MidyGM1 {
921
974
  }
922
975
  handleMasterVolumeSysEx(data) {
923
976
  const volume = (data[5] * 128 + data[4]) / 16383;
924
- this.handleMasterVolume(volume);
977
+ this.setMasterVolume(volume);
925
978
  }
926
- handleMasterVolume(volume) {
979
+ setMasterVolume(volume) {
927
980
  if (volume < 0 && 1 < volume) {
928
981
  console.error("Master Volume is out of range");
929
982
  }
@@ -965,7 +1018,7 @@ Object.defineProperty(MidyGM1, "channelSettings", {
965
1018
  writable: true,
966
1019
  value: {
967
1020
  volume: 100 / 127,
968
- pan: 0,
1021
+ pan: 64,
969
1022
  bank: 0,
970
1023
  dataMSB: 0,
971
1024
  dataLSB: 0,
@@ -73,8 +73,8 @@ export class MidyGM2 {
73
73
  lfoFilterDepth: number;
74
74
  lfoAmplitudeDepth: number;
75
75
  };
76
- gainNode: any;
77
- pannerNode: any;
76
+ gainL: any;
77
+ gainR: any;
78
78
  reverbEffect: {
79
79
  convolverNode: any;
80
80
  dryGain: any;
@@ -117,8 +117,8 @@ export class MidyGM2 {
117
117
  loadSoundFont(soundFontUrl: any): Promise<void>;
118
118
  loadMIDI(midiUrl: any): Promise<void>;
119
119
  setChannelAudioNodes(audioContext: any): {
120
- gainNode: any;
121
- pannerNode: any;
120
+ gainL: any;
121
+ gainR: any;
122
122
  reverbEffect: {
123
123
  convolverNode: any;
124
124
  dryGain: any;
@@ -142,8 +142,8 @@ export class MidyGM2 {
142
142
  lfoFilterDepth: number;
143
143
  lfoAmplitudeDepth: number;
144
144
  };
145
- gainNode: any;
146
- pannerNode: any;
145
+ gainL: any;
146
+ gainR: any;
147
147
  reverbEffect: {
148
148
  convolverNode: any;
149
149
  dryGain: any;
@@ -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;
@@ -250,9 +254,19 @@ export class MidyGM2 {
250
254
  setChorus(channelNumber: any, chorus: any): void;
251
255
  setSostenutoPedal(channelNumber: any, value: any): void;
252
256
  setSoftPedal(channelNumber: any, softPedal: any): void;
257
+ limitData(channel: any, minMSB: any, maxMSB: any, minLSB: any, maxLSB: any): void;
258
+ limitDataMSB(channel: any, minMSB: any, maxMSB: any): void;
259
+ handleRPN(channelNumber: any, value: any): void;
253
260
  setRPNMSB(channelNumber: any, value: any): void;
254
261
  setRPNLSB(channelNumber: any, value: any): void;
255
262
  setDataEntry(channelNumber: any, value: any, isMSB: any): void;
263
+ updateDetune(channel: any, detuneChange: any): void;
264
+ handlePitchBendRangeMessage(channelNumber: any): void;
265
+ setPitchBendRange(channelNumber: any, pitchBendRange: any): void;
266
+ handleFineTuningMessage(channelNumber: any): void;
267
+ setFineTuning(channelNumber: any, fineTuning: any): void;
268
+ handleCoarseTuningMessage(channelNumber: any): void;
269
+ setCoarseTuning(channelNumber: any, coarseTuning: any): void;
256
270
  allSoundOff(channelNumber: any): any[];
257
271
  resetAllControllers(channelNumber: any): void;
258
272
  allNotesOff(channelNumber: any): any[];
@@ -265,11 +279,11 @@ export class MidyGM2 {
265
279
  GM2SystemOn(): void;
266
280
  handleUniversalRealTimeExclusiveMessage(data: any): void;
267
281
  handleMasterVolumeSysEx(data: any): void;
268
- handleMasterVolume(volume: any): void;
282
+ setMasterVolume(volume: any): void;
269
283
  handleMasterFineTuningSysEx(data: any): void;
270
- handleMasterFineTuning(fineTuning: any): void;
284
+ setMasterFineTuning(fineTuning: any): void;
271
285
  handleMasterCoarseTuningSysEx(data: any): void;
272
- handleMasterCoarseTuning(coarseTuning: any): void;
286
+ setMasterCoarseTuning(coarseTuning: any): void;
273
287
  handleExclusiveMessage(data: any): void;
274
288
  handleSysEx(data: any): void;
275
289
  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;;;;;;;;;;;;;;MAqBC;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,sDA6BC;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,uDAOC;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,kFAeC;IAED,2DAMC;IAED,gDAqBC;IAED,gDAEC;IAED,gDAEC;IAED,+DAIC;IAED,oDAUC;IAED,sDAKC;IAED,iEAOC;IAED,kDAKC;IAED,yDAGC;IAED,oDAKC;IAED,6DAGC;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;AA17CD;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"}