@marmooo/midy 0.2.8 → 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 +15 -9
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +112 -58
- package/esm/midy-GM2.d.ts +24 -15
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +311 -102
- package/esm/midy-GMLite.d.ts +17 -8
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +159 -55
- package/esm/midy.d.ts +24 -15
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +352 -113
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +15 -9
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +112 -58
- package/script/midy-GM2.d.ts +24 -15
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +311 -102
- package/script/midy-GMLite.d.ts +17 -8
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +159 -55
- package/script/midy.d.ts +24 -15
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +352 -113
package/esm/midy-GM1.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
export class MidyGM1 {
|
|
2
2
|
static channelSettings: {
|
|
3
|
-
currentBufferSource: null;
|
|
4
3
|
detune: number;
|
|
5
|
-
|
|
4
|
+
programNumber: number;
|
|
6
5
|
bank: number;
|
|
7
6
|
dataMSB: number;
|
|
8
7
|
dataLSB: number;
|
|
9
8
|
rpnMSB: number;
|
|
10
9
|
rpnLSB: number;
|
|
10
|
+
modulationDepthRange: number;
|
|
11
11
|
fineTuning: number;
|
|
12
12
|
coarseTuning: number;
|
|
13
|
-
modulationDepthRange: number;
|
|
14
13
|
};
|
|
15
14
|
constructor(audioContext: any);
|
|
15
|
+
mode: string;
|
|
16
|
+
numChannels: number;
|
|
16
17
|
ticksPerBeat: number;
|
|
17
18
|
totalTime: number;
|
|
18
19
|
noteCheckInterval: number;
|
|
@@ -32,9 +33,11 @@ export class MidyGM1 {
|
|
|
32
33
|
timeline: any[];
|
|
33
34
|
instruments: any[];
|
|
34
35
|
notePromises: any[];
|
|
35
|
-
|
|
36
|
+
exclusiveClassNotes: any[];
|
|
36
37
|
audioContext: any;
|
|
37
38
|
masterVolume: any;
|
|
39
|
+
scheduler: any;
|
|
40
|
+
schedulerBuffer: any;
|
|
38
41
|
voiceParamsHandlers: {
|
|
39
42
|
modLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
|
|
40
43
|
vibLfoToPitch: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
|
|
@@ -73,7 +76,7 @@ export class MidyGM1 {
|
|
|
73
76
|
};
|
|
74
77
|
createChannels(audioContext: any): any[];
|
|
75
78
|
createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
|
|
76
|
-
|
|
79
|
+
createBufferSource(audioBuffer: any, voiceParams: any): any;
|
|
77
80
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
78
81
|
getQueueIndex(second: any): number;
|
|
79
82
|
playNotes(): Promise<any>;
|
|
@@ -108,16 +111,18 @@ export class MidyGM1 {
|
|
|
108
111
|
clampCutoffFrequency(frequency: any): number;
|
|
109
112
|
setFilterEnvelope(note: any, scheduleTime: any): void;
|
|
110
113
|
startModulation(channel: any, note: any, scheduleTime: any): void;
|
|
111
|
-
getAudioBuffer(
|
|
114
|
+
getAudioBuffer(programNumber: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
|
|
112
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;
|
|
113
117
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
114
118
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
|
|
119
|
+
disconnectNote(note: any, scheduledNotes: any, index: any): void;
|
|
115
120
|
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
116
121
|
scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): Promise<any> | undefined;
|
|
117
122
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
|
|
118
123
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
|
|
119
124
|
handleMIDIMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
|
|
120
|
-
handleProgramChange(channelNumber: any,
|
|
125
|
+
handleProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
|
|
121
126
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
|
|
122
127
|
setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
|
|
123
128
|
setModLfoToPitch(channel: any, note: any, scheduleTime: any): void;
|
|
@@ -179,10 +184,11 @@ export class MidyGM1 {
|
|
|
179
184
|
handleCoarseTuningRPN(channelNumber: any, scheduleTime: any): void;
|
|
180
185
|
setCoarseTuning(channelNumber: any, value: any, scheduleTime: any): void;
|
|
181
186
|
allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
187
|
+
resetAllStates(channelNumber: any): void;
|
|
182
188
|
resetAllControllers(channelNumber: any): void;
|
|
183
189
|
allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
184
|
-
handleUniversalNonRealTimeExclusiveMessage(data: any,
|
|
185
|
-
GM1SystemOn(): void;
|
|
190
|
+
handleUniversalNonRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
191
|
+
GM1SystemOn(scheduleTime: any): void;
|
|
186
192
|
handleUniversalRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
187
193
|
handleMasterVolumeSysEx(data: any, scheduleTime: any): void;
|
|
188
194
|
setMasterVolume(volume: any, scheduleTime: any): void;
|
package/esm/midy-GM1.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAiJA;
|
|
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
|
@@ -170,6 +170,18 @@ const volumeEnvelopeKeys = [
|
|
|
170
170
|
const volumeEnvelopeKeySet = new Set(volumeEnvelopeKeys);
|
|
171
171
|
export class MidyGM1 {
|
|
172
172
|
constructor(audioContext) {
|
|
173
|
+
Object.defineProperty(this, "mode", {
|
|
174
|
+
enumerable: true,
|
|
175
|
+
configurable: true,
|
|
176
|
+
writable: true,
|
|
177
|
+
value: "GM1"
|
|
178
|
+
});
|
|
179
|
+
Object.defineProperty(this, "numChannels", {
|
|
180
|
+
enumerable: true,
|
|
181
|
+
configurable: true,
|
|
182
|
+
writable: true,
|
|
183
|
+
value: 16
|
|
184
|
+
});
|
|
173
185
|
Object.defineProperty(this, "ticksPerBeat", {
|
|
174
186
|
enumerable: true,
|
|
175
187
|
configurable: true,
|
|
@@ -284,18 +296,24 @@ export class MidyGM1 {
|
|
|
284
296
|
writable: true,
|
|
285
297
|
value: []
|
|
286
298
|
});
|
|
287
|
-
Object.defineProperty(this, "
|
|
299
|
+
Object.defineProperty(this, "exclusiveClassNotes", {
|
|
288
300
|
enumerable: true,
|
|
289
301
|
configurable: true,
|
|
290
302
|
writable: true,
|
|
291
|
-
value: new
|
|
303
|
+
value: new Array(128)
|
|
292
304
|
});
|
|
293
305
|
this.audioContext = audioContext;
|
|
294
306
|
this.masterVolume = new GainNode(audioContext);
|
|
307
|
+
this.scheduler = new GainNode(audioContext, { gain: 0 });
|
|
308
|
+
this.schedulerBuffer = new AudioBuffer({
|
|
309
|
+
length: 1,
|
|
310
|
+
sampleRate: audioContext.sampleRate,
|
|
311
|
+
});
|
|
295
312
|
this.voiceParamsHandlers = this.createVoiceParamsHandlers();
|
|
296
313
|
this.controlChangeHandlers = this.createControlChangeHandlers();
|
|
297
314
|
this.channels = this.createChannels(audioContext);
|
|
298
315
|
this.masterVolume.connect(audioContext.destination);
|
|
316
|
+
this.scheduler.connect(audioContext.destination);
|
|
299
317
|
this.GM1SystemOn();
|
|
300
318
|
}
|
|
301
319
|
initSoundFontTable() {
|
|
@@ -349,8 +367,10 @@ export class MidyGM1 {
|
|
|
349
367
|
};
|
|
350
368
|
}
|
|
351
369
|
createChannels(audioContext) {
|
|
352
|
-
const channels = Array.from({ length:
|
|
370
|
+
const channels = Array.from({ length: this.numChannels }, () => {
|
|
353
371
|
return {
|
|
372
|
+
currentBufferSource: null,
|
|
373
|
+
isDrum: false,
|
|
354
374
|
...this.constructor.channelSettings,
|
|
355
375
|
state: new ControllerState(),
|
|
356
376
|
...this.setChannelAudioNodes(audioContext),
|
|
@@ -389,7 +409,7 @@ export class MidyGM1 {
|
|
|
389
409
|
return audioBuffer;
|
|
390
410
|
}
|
|
391
411
|
}
|
|
392
|
-
|
|
412
|
+
createBufferSource(audioBuffer, voiceParams) {
|
|
393
413
|
const bufferSource = new AudioBufferSourceNode(this.audioContext);
|
|
394
414
|
bufferSource.buffer = audioBuffer;
|
|
395
415
|
bufferSource.loop = voiceParams.sampleModes % 2 !== 0;
|
|
@@ -455,7 +475,7 @@ export class MidyGM1 {
|
|
|
455
475
|
if (queueIndex >= this.timeline.length) {
|
|
456
476
|
await Promise.all(this.notePromises);
|
|
457
477
|
this.notePromises = [];
|
|
458
|
-
this.
|
|
478
|
+
this.exclusiveClassNotes.flll(undefined);
|
|
459
479
|
this.audioBufferCache.clear();
|
|
460
480
|
resolve();
|
|
461
481
|
return;
|
|
@@ -474,7 +494,7 @@ export class MidyGM1 {
|
|
|
474
494
|
else if (this.isStopping) {
|
|
475
495
|
await this.stopNotes(0, true, now);
|
|
476
496
|
this.notePromises = [];
|
|
477
|
-
this.
|
|
497
|
+
this.exclusiveClassNotes.fill(undefined);
|
|
478
498
|
this.audioBufferCache.clear();
|
|
479
499
|
resolve();
|
|
480
500
|
this.isStopping = false;
|
|
@@ -483,7 +503,7 @@ export class MidyGM1 {
|
|
|
483
503
|
}
|
|
484
504
|
else if (this.isSeeking) {
|
|
485
505
|
this.stopNotes(0, true, now);
|
|
486
|
-
this.
|
|
506
|
+
this.exclusiveClassNotes.fill(undefined);
|
|
487
507
|
this.startTime = this.audioContext.currentTime;
|
|
488
508
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
489
509
|
offset = this.resumeTime - this.startTime;
|
|
@@ -511,7 +531,7 @@ export class MidyGM1 {
|
|
|
511
531
|
extractMidiData(midi) {
|
|
512
532
|
const instruments = new Set();
|
|
513
533
|
const timeline = [];
|
|
514
|
-
const tmpChannels = new Array(
|
|
534
|
+
const tmpChannels = new Array(this.channels.length);
|
|
515
535
|
for (let i = 0; i < tmpChannels.length; i++) {
|
|
516
536
|
tmpChannels[i] = {
|
|
517
537
|
programNumber: -1,
|
|
@@ -603,6 +623,9 @@ export class MidyGM1 {
|
|
|
603
623
|
if (!this.isPlaying)
|
|
604
624
|
return;
|
|
605
625
|
this.isStopping = true;
|
|
626
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
627
|
+
this.resetAllStates(i);
|
|
628
|
+
}
|
|
606
629
|
}
|
|
607
630
|
pause() {
|
|
608
631
|
if (!this.isPlaying || this.isPaused)
|
|
@@ -780,8 +803,8 @@ export class MidyGM1 {
|
|
|
780
803
|
note.modulationLFO.connect(note.volumeDepth);
|
|
781
804
|
note.volumeDepth.connect(note.volumeEnvelopeNode.gain);
|
|
782
805
|
}
|
|
783
|
-
async getAudioBuffer(
|
|
784
|
-
const audioBufferId = this.getAudioBufferId(
|
|
806
|
+
async getAudioBuffer(programNumber, noteNumber, velocity, voiceParams, isSF3) {
|
|
807
|
+
const audioBufferId = this.getAudioBufferId(programNumber, noteNumber, velocity);
|
|
785
808
|
const cache = this.audioBufferCache.get(audioBufferId);
|
|
786
809
|
if (cache) {
|
|
787
810
|
cache.counter += 1;
|
|
@@ -804,8 +827,8 @@ export class MidyGM1 {
|
|
|
804
827
|
const controllerState = this.getControllerState(channel, noteNumber, velocity);
|
|
805
828
|
const voiceParams = voice.getAllParams(controllerState);
|
|
806
829
|
const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
|
|
807
|
-
const audioBuffer = await this.getAudioBuffer(channel.
|
|
808
|
-
note.bufferSource = this.
|
|
830
|
+
const audioBuffer = await this.getAudioBuffer(channel.programNumber, noteNumber, velocity, voiceParams, isSF3);
|
|
831
|
+
note.bufferSource = this.createBufferSource(audioBuffer, voiceParams);
|
|
809
832
|
note.volumeEnvelopeNode = new GainNode(this.audioContext);
|
|
810
833
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
811
834
|
type: "lowpass",
|
|
@@ -822,14 +845,28 @@ export class MidyGM1 {
|
|
|
822
845
|
note.bufferSource.start(startTime);
|
|
823
846
|
return note;
|
|
824
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
|
+
}
|
|
825
862
|
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
|
|
826
863
|
const channel = this.channels[channelNumber];
|
|
827
864
|
const bankNumber = channel.bank;
|
|
828
|
-
const soundFontIndex = this.soundFontTable[channel.
|
|
865
|
+
const soundFontIndex = this.soundFontTable[channel.programNumber].get(bankNumber);
|
|
829
866
|
if (soundFontIndex === undefined)
|
|
830
867
|
return;
|
|
831
868
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
832
|
-
const voice = soundFont.getVoice(bankNumber, channel.
|
|
869
|
+
const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
|
|
833
870
|
if (!voice)
|
|
834
871
|
return;
|
|
835
872
|
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
@@ -839,30 +876,31 @@ export class MidyGM1 {
|
|
|
839
876
|
if (0.5 <= channel.state.sustainPedal) {
|
|
840
877
|
channel.sustainNotes.push(note);
|
|
841
878
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
const [prevNote, prevChannelNumber] = prevEntry;
|
|
847
|
-
if (!prevNote.ending) {
|
|
848
|
-
this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
849
|
-
startTime, true);
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
this.exclusiveClassMap.set(exclusiveClass, [note, channelNumber]);
|
|
853
|
-
}
|
|
854
|
-
const scheduledNotes = channel.scheduledNotes;
|
|
855
|
-
if (scheduledNotes.has(noteNumber)) {
|
|
856
|
-
scheduledNotes.get(noteNumber).push(note);
|
|
879
|
+
this.handleExclusiveClass(note, channelNumber, startTime);
|
|
880
|
+
let notes = scheduledNotes.get(noteNumber);
|
|
881
|
+
if (notes) {
|
|
882
|
+
notes.push(note);
|
|
857
883
|
}
|
|
858
884
|
else {
|
|
859
|
-
|
|
885
|
+
notes = [note];
|
|
886
|
+
scheduledNotes.set(noteNumber, notes);
|
|
860
887
|
}
|
|
861
888
|
}
|
|
862
889
|
noteOn(channelNumber, noteNumber, velocity, scheduleTime) {
|
|
863
890
|
scheduleTime ??= this.audioContext.currentTime;
|
|
864
891
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime);
|
|
865
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
|
+
}
|
|
866
904
|
stopNote(endTime, stopTime, scheduledNotes, index) {
|
|
867
905
|
const note = scheduledNotes[index];
|
|
868
906
|
note.volumeEnvelopeNode.gain
|
|
@@ -874,15 +912,7 @@ export class MidyGM1 {
|
|
|
874
912
|
}, stopTime);
|
|
875
913
|
return new Promise((resolve) => {
|
|
876
914
|
note.bufferSource.onended = () => {
|
|
877
|
-
scheduledNotes
|
|
878
|
-
note.bufferSource.disconnect();
|
|
879
|
-
note.filterNode.disconnect();
|
|
880
|
-
note.volumeEnvelopeNode.disconnect();
|
|
881
|
-
if (note.modulationDepth) {
|
|
882
|
-
note.volumeDepth.disconnect();
|
|
883
|
-
note.modulationDepth.disconnect();
|
|
884
|
-
note.modulationLFO.stop();
|
|
885
|
-
}
|
|
915
|
+
this.disconnectNote(note, scheduledNotes, index);
|
|
886
916
|
resolve();
|
|
887
917
|
};
|
|
888
918
|
note.bufferSource.stop(stopTime);
|
|
@@ -943,17 +973,17 @@ export class MidyGM1 {
|
|
|
943
973
|
console.warn(`Unsupported MIDI message: ${messageType.toString(16)}`);
|
|
944
974
|
}
|
|
945
975
|
}
|
|
946
|
-
handleProgramChange(channelNumber,
|
|
976
|
+
handleProgramChange(channelNumber, programNumber, _scheduleTime) {
|
|
947
977
|
const channel = this.channels[channelNumber];
|
|
948
|
-
channel.
|
|
978
|
+
channel.programNumber = programNumber;
|
|
949
979
|
}
|
|
950
980
|
handlePitchBendMessage(channelNumber, lsb, msb, scheduleTime) {
|
|
951
981
|
const pitchBend = msb * 128 + lsb;
|
|
952
982
|
this.setPitchBend(channelNumber, pitchBend, scheduleTime);
|
|
953
983
|
}
|
|
954
984
|
setPitchBend(channelNumber, value, scheduleTime) {
|
|
955
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
956
985
|
const channel = this.channels[channelNumber];
|
|
986
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
957
987
|
const state = channel.state;
|
|
958
988
|
const prev = state.pitchWheel * 2 - 1;
|
|
959
989
|
const next = (value - 8192) / 8192;
|
|
@@ -1114,8 +1144,8 @@ export class MidyGM1 {
|
|
|
1114
1144
|
});
|
|
1115
1145
|
}
|
|
1116
1146
|
setModulationDepth(channelNumber, modulation, scheduleTime) {
|
|
1117
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1118
1147
|
const channel = this.channels[channelNumber];
|
|
1148
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1119
1149
|
channel.state.modulationDepth = modulation / 127;
|
|
1120
1150
|
this.updateModulation(channel, scheduleTime);
|
|
1121
1151
|
}
|
|
@@ -1160,8 +1190,8 @@ export class MidyGM1 {
|
|
|
1160
1190
|
.setValueAtTime(volume * gainRight, scheduleTime);
|
|
1161
1191
|
}
|
|
1162
1192
|
setSustainPedal(channelNumber, value, scheduleTime) {
|
|
1163
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1164
1193
|
const channel = this.channels[channelNumber];
|
|
1194
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1165
1195
|
channel.state.sustainPedal = value / 127;
|
|
1166
1196
|
if (64 <= value) {
|
|
1167
1197
|
this.processScheduledNotes(channel, (note) => {
|
|
@@ -1232,8 +1262,8 @@ export class MidyGM1 {
|
|
|
1232
1262
|
this.setPitchBendRange(channelNumber, pitchBendRange, scheduleTime);
|
|
1233
1263
|
}
|
|
1234
1264
|
setPitchBendRange(channelNumber, value, scheduleTime) {
|
|
1235
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1236
1265
|
const channel = this.channels[channelNumber];
|
|
1266
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1237
1267
|
const state = channel.state;
|
|
1238
1268
|
const prev = state.pitchWheelSensitivity;
|
|
1239
1269
|
const next = value / 128;
|
|
@@ -1249,8 +1279,8 @@ export class MidyGM1 {
|
|
|
1249
1279
|
this.setFineTuning(channelNumber, fineTuning, scheduleTime);
|
|
1250
1280
|
}
|
|
1251
1281
|
setFineTuning(channelNumber, value, scheduleTime) {
|
|
1252
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1253
1282
|
const channel = this.channels[channelNumber];
|
|
1283
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1254
1284
|
const prev = channel.fineTuning;
|
|
1255
1285
|
const next = (value - 8192) / 8.192; // cent
|
|
1256
1286
|
channel.fineTuning = next;
|
|
@@ -1264,8 +1294,8 @@ export class MidyGM1 {
|
|
|
1264
1294
|
this.setCoarseTuning(channelNumber, coarseTuning, scheduleTime);
|
|
1265
1295
|
}
|
|
1266
1296
|
setCoarseTuning(channelNumber, value, scheduleTime) {
|
|
1267
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1268
1297
|
const channel = this.channels[channelNumber];
|
|
1298
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1269
1299
|
const prev = channel.coarseTuning;
|
|
1270
1300
|
const next = (value - 64) * 100; // cent
|
|
1271
1301
|
channel.coarseTuning = next;
|
|
@@ -1276,12 +1306,24 @@ export class MidyGM1 {
|
|
|
1276
1306
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1277
1307
|
return this.stopChannelNotes(channelNumber, 0, true, scheduleTime);
|
|
1278
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
|
|
1279
1321
|
resetAllControllers(channelNumber) {
|
|
1280
1322
|
const stateTypes = [
|
|
1323
|
+
"pitchWheel",
|
|
1281
1324
|
"expression",
|
|
1282
1325
|
"modulationDepth",
|
|
1283
1326
|
"sustainPedal",
|
|
1284
|
-
"pitchWheelSensitivity",
|
|
1285
1327
|
];
|
|
1286
1328
|
const channel = this.channels[channelNumber];
|
|
1287
1329
|
const state = channel.state;
|
|
@@ -1302,12 +1344,12 @@ export class MidyGM1 {
|
|
|
1302
1344
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1303
1345
|
return this.stopChannelNotes(channelNumber, 0, false, scheduleTime);
|
|
1304
1346
|
}
|
|
1305
|
-
handleUniversalNonRealTimeExclusiveMessage(data,
|
|
1347
|
+
handleUniversalNonRealTimeExclusiveMessage(data, scheduleTime) {
|
|
1306
1348
|
switch (data[2]) {
|
|
1307
1349
|
case 9:
|
|
1308
1350
|
switch (data[3]) {
|
|
1309
1351
|
case 1:
|
|
1310
|
-
this.GM1SystemOn();
|
|
1352
|
+
this.GM1SystemOn(scheduleTime);
|
|
1311
1353
|
break;
|
|
1312
1354
|
case 2: // GM System Off
|
|
1313
1355
|
break;
|
|
@@ -1319,12 +1361,17 @@ export class MidyGM1 {
|
|
|
1319
1361
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1320
1362
|
}
|
|
1321
1363
|
}
|
|
1322
|
-
GM1SystemOn() {
|
|
1364
|
+
GM1SystemOn(scheduleTime) {
|
|
1365
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1366
|
+
this.mode = "GM1";
|
|
1323
1367
|
for (let i = 0; i < this.channels.length; i++) {
|
|
1368
|
+
this.allSoundOff(i, 0, scheduleTime);
|
|
1324
1369
|
const channel = this.channels[i];
|
|
1325
1370
|
channel.bank = 0;
|
|
1371
|
+
channel.isDrum = false;
|
|
1326
1372
|
}
|
|
1327
1373
|
this.channels[9].bank = 128;
|
|
1374
|
+
this.channels[9].isDrum = true;
|
|
1328
1375
|
}
|
|
1329
1376
|
handleUniversalRealTimeExclusiveMessage(data, scheduleTime) {
|
|
1330
1377
|
switch (data[2]) {
|
|
@@ -1365,15 +1412,23 @@ export class MidyGM1 {
|
|
|
1365
1412
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1366
1413
|
}
|
|
1367
1414
|
}
|
|
1415
|
+
// https://github.com/marmooo/js-timer-benchmark
|
|
1368
1416
|
scheduleTask(callback, scheduleTime) {
|
|
1369
1417
|
return new Promise((resolve) => {
|
|
1370
|
-
const bufferSource = new AudioBufferSourceNode(this.audioContext
|
|
1418
|
+
const bufferSource = new AudioBufferSourceNode(this.audioContext, {
|
|
1419
|
+
buffer: this.schedulerBuffer,
|
|
1420
|
+
});
|
|
1421
|
+
bufferSource.connect(this.scheduler);
|
|
1371
1422
|
bufferSource.onended = () => {
|
|
1372
|
-
|
|
1373
|
-
|
|
1423
|
+
try {
|
|
1424
|
+
callback();
|
|
1425
|
+
}
|
|
1426
|
+
finally {
|
|
1427
|
+
bufferSource.disconnect();
|
|
1428
|
+
resolve();
|
|
1429
|
+
}
|
|
1374
1430
|
};
|
|
1375
1431
|
bufferSource.start(scheduleTime);
|
|
1376
|
-
bufferSource.stop(scheduleTime);
|
|
1377
1432
|
});
|
|
1378
1433
|
}
|
|
1379
1434
|
}
|
|
@@ -1382,16 +1437,15 @@ Object.defineProperty(MidyGM1, "channelSettings", {
|
|
|
1382
1437
|
configurable: true,
|
|
1383
1438
|
writable: true,
|
|
1384
1439
|
value: {
|
|
1385
|
-
currentBufferSource: null,
|
|
1386
1440
|
detune: 0,
|
|
1387
|
-
|
|
1441
|
+
programNumber: 0,
|
|
1388
1442
|
bank: 0,
|
|
1389
1443
|
dataMSB: 0,
|
|
1390
1444
|
dataLSB: 0,
|
|
1391
1445
|
rpnMSB: 127,
|
|
1392
1446
|
rpnLSB: 127,
|
|
1447
|
+
modulationDepthRange: 50, // cent
|
|
1393
1448
|
fineTuning: 0, // cb
|
|
1394
1449
|
coarseTuning: 0, // cb
|
|
1395
|
-
modulationDepthRange: 50, // cent
|
|
1396
1450
|
}
|
|
1397
1451
|
});
|
package/esm/midy-GM2.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export class MidyGM2 {
|
|
2
2
|
static channelSettings: {
|
|
3
|
-
currentBufferSource: null;
|
|
4
3
|
detune: number;
|
|
5
|
-
|
|
4
|
+
programNumber: number;
|
|
6
5
|
bank: number;
|
|
7
6
|
bankMSB: number;
|
|
8
7
|
bankLSB: number;
|
|
@@ -11,9 +10,9 @@ export class MidyGM2 {
|
|
|
11
10
|
rpnMSB: number;
|
|
12
11
|
rpnLSB: number;
|
|
13
12
|
mono: boolean;
|
|
13
|
+
modulationDepthRange: number;
|
|
14
14
|
fineTuning: number;
|
|
15
15
|
coarseTuning: number;
|
|
16
|
-
modulationDepthRange: number;
|
|
17
16
|
};
|
|
18
17
|
constructor(audioContext: any, options?: {
|
|
19
18
|
reverbAlgorithm: (audioContext: any) => {
|
|
@@ -21,8 +20,7 @@ export class MidyGM2 {
|
|
|
21
20
|
output: any;
|
|
22
21
|
};
|
|
23
22
|
});
|
|
24
|
-
|
|
25
|
-
totalTime: number;
|
|
23
|
+
mode: string;
|
|
26
24
|
masterFineTuning: number;
|
|
27
25
|
masterCoarseTuning: number;
|
|
28
26
|
reverb: {
|
|
@@ -36,6 +34,9 @@ export class MidyGM2 {
|
|
|
36
34
|
sendToReverb: number;
|
|
37
35
|
delayTimes: any[];
|
|
38
36
|
};
|
|
37
|
+
numChannels: number;
|
|
38
|
+
ticksPerBeat: number;
|
|
39
|
+
totalTime: number;
|
|
39
40
|
noteCheckInterval: number;
|
|
40
41
|
lookAhead: number;
|
|
41
42
|
startDelay: number;
|
|
@@ -53,7 +54,8 @@ export class MidyGM2 {
|
|
|
53
54
|
timeline: any[];
|
|
54
55
|
instruments: any[];
|
|
55
56
|
notePromises: any[];
|
|
56
|
-
|
|
57
|
+
exclusiveClassNotes: any[];
|
|
58
|
+
drumExclusiveClassNotes: any[];
|
|
57
59
|
defaultOptions: {
|
|
58
60
|
reverbAlgorithm: (audioContext: any) => {
|
|
59
61
|
input: any;
|
|
@@ -68,6 +70,8 @@ export class MidyGM2 {
|
|
|
68
70
|
};
|
|
69
71
|
};
|
|
70
72
|
masterVolume: any;
|
|
73
|
+
scheduler: any;
|
|
74
|
+
schedulerBuffer: any;
|
|
71
75
|
voiceParamsHandlers: {
|
|
72
76
|
modLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
|
|
73
77
|
vibLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
|
|
@@ -93,7 +97,7 @@ export class MidyGM2 {
|
|
|
93
97
|
64: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
94
98
|
65: (channelNumber: any, value: any) => void;
|
|
95
99
|
66: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
96
|
-
67: (channelNumber: any, softPedal: any,
|
|
100
|
+
67: (channelNumber: any, softPedal: any, scheduleTime: any) => void;
|
|
97
101
|
91: (channelNumber: any, reverbSendLevel: any, scheduleTime: any) => void;
|
|
98
102
|
93: (channelNumber: any, chorusSendLevel: any, scheduleTime: any) => void;
|
|
99
103
|
100: (channelNumber: any, value: any) => void;
|
|
@@ -131,7 +135,7 @@ export class MidyGM2 {
|
|
|
131
135
|
};
|
|
132
136
|
createChannels(audioContext: any): any[];
|
|
133
137
|
createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
|
|
134
|
-
|
|
138
|
+
createBufferSource(voiceParams: any, audioBuffer: any): any;
|
|
135
139
|
findPortamentoTarget(queueIndex: any): any;
|
|
136
140
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
137
141
|
getQueueIndex(second: any): number;
|
|
@@ -194,18 +198,22 @@ export class MidyGM2 {
|
|
|
194
198
|
setFilterEnvelope(channel: any, note: any, scheduleTime: any): void;
|
|
195
199
|
startModulation(channel: any, note: any, scheduleTime: any): void;
|
|
196
200
|
startVibrato(channel: any, note: any, scheduleTime: any): void;
|
|
197
|
-
getAudioBuffer(
|
|
201
|
+
getAudioBuffer(programNumber: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
|
|
198
202
|
createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
|
|
199
|
-
calcBank(channel: any
|
|
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;
|
|
200
207
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
|
|
201
208
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
|
|
209
|
+
disconnectNote(note: any, scheduledNotes: any, index: any): void;
|
|
202
210
|
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
203
211
|
scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any, portamentoNoteNumber: any): Promise<any> | undefined;
|
|
204
212
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
|
|
205
213
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
|
|
206
214
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): any[];
|
|
207
215
|
handleMIDIMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
|
|
208
|
-
handleProgramChange(channelNumber: any,
|
|
216
|
+
handleProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
|
|
209
217
|
handleChannelPressure(channelNumber: any, value: any, scheduleTime: any): void;
|
|
210
218
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
|
|
211
219
|
setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
|
|
@@ -245,7 +253,7 @@ export class MidyGM2 {
|
|
|
245
253
|
64: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
246
254
|
65: (channelNumber: any, value: any) => void;
|
|
247
255
|
66: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
248
|
-
67: (channelNumber: any, softPedal: any,
|
|
256
|
+
67: (channelNumber: any, softPedal: any, scheduleTime: any) => void;
|
|
249
257
|
91: (channelNumber: any, reverbSendLevel: any, scheduleTime: any) => void;
|
|
250
258
|
93: (channelNumber: any, chorusSendLevel: any, scheduleTime: any) => void;
|
|
251
259
|
100: (channelNumber: any, value: any) => void;
|
|
@@ -278,7 +286,7 @@ export class MidyGM2 {
|
|
|
278
286
|
setSustainPedal(channelNumber: any, value: any, scheduleTime: any): void;
|
|
279
287
|
setPortamento(channelNumber: any, value: any): void;
|
|
280
288
|
setSostenutoPedal(channelNumber: any, value: any, scheduleTime: any): void;
|
|
281
|
-
setSoftPedal(channelNumber: any, softPedal: any,
|
|
289
|
+
setSoftPedal(channelNumber: any, softPedal: any, scheduleTime: any): void;
|
|
282
290
|
setReverbSendLevel(channelNumber: any, reverbSendLevel: any, scheduleTime: any): void;
|
|
283
291
|
setChorusSendLevel(channelNumber: any, chorusSendLevel: any, scheduleTime: any): void;
|
|
284
292
|
limitData(channel: any, minMSB: any, maxMSB: any, minLSB: any, maxLSB: any): void;
|
|
@@ -296,6 +304,7 @@ export class MidyGM2 {
|
|
|
296
304
|
handleModulationDepthRangeRPN(channelNumber: any, scheduleTime: any): void;
|
|
297
305
|
setModulationDepthRange(channelNumber: any, modulationDepthRange: any, scheduleTime: any): void;
|
|
298
306
|
allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
307
|
+
resetAllStates(channelNumber: any): void;
|
|
299
308
|
resetAllControllers(channelNumber: any): void;
|
|
300
309
|
allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
301
310
|
omniOff(channelNumber: any, value: any, scheduleTime: any): void;
|
|
@@ -303,8 +312,8 @@ export class MidyGM2 {
|
|
|
303
312
|
monoOn(channelNumber: any, value: any, scheduleTime: any): void;
|
|
304
313
|
polyOn(channelNumber: any, value: any, scheduleTime: any): void;
|
|
305
314
|
handleUniversalNonRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
306
|
-
GM1SystemOn(): void;
|
|
307
|
-
GM2SystemOn(): void;
|
|
315
|
+
GM1SystemOn(scheduleTime: any): void;
|
|
316
|
+
GM2SystemOn(scheduleTime: any): void;
|
|
308
317
|
handleUniversalRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
309
318
|
handleMasterVolumeSysEx(data: any, scheduleTime: any): void;
|
|
310
319
|
setMasterVolume(volume: any, scheduleTime: any): void;
|
package/esm/midy-GM2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAgNA;IAwCE;;;;;;;;;;;;;;MAcE;IAgCF;;;;;OAmBC;IAxGD,aAAa;IACb,yBAAqB;IACrB,2BAAuB;IACvB;;;MAGE;IACF;;;;;;MAME;IACF,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;IACrC,+BAEE;IAkBF;;;;;MA4BE;IAGA,kBAAgC;IAChC;;;;;MAAqD;IACrD,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IACjD;;;MAA8D;IAC9D;;;;;;;;MAAyD;IAQ3D,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAkBC;IAED,6DA2BC;IAED,4DASC;IAED,2CAcC;IAED,2EA6DC;IAED,mCAOC;IAED,0BAuDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MAgHC;IAED,mGAiBC;IAED,wEAMC;IAED,uBAKC;IAED,aAMC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,2DASC;IAED,qDAQC;IAED,kFAuBC;IAED;;;;MAWC;IAED,gFAUC;IAED,mFAYC;IAED,sGAcC;IAID;;;MA8BC;IAED;;;;;;;;MA0CC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAYC;IAED,6CAEC;IAED,2DAIC;IAED,+DAMC;IAED,wCAGC;IAED,mFAUC;IAED,oEAgBC;IAED,qDAoBC;IAED,6CAIC;IAED,mFAqBC;IAED,oEA0BC;IAED,kEAoBC;IAED,+DAaC;IAED,+GA0BC;IAED,iIAqEC;IAED,4BAYC;IAED,0EAkBC;IAED,8EAqBC;IAED,+DAKC;IAED,mHA0DC;IAED,6FASC;IAED,iEAuBC;IAED,qFAgBC;IAED,oJAwCC;IAED,yGAUC;IAED,4GAeC;IAED,uFAgBC;IAED,mGA6BC;IAED,sFAcC;IAED,+EAeC;IAED,wFAGC;IAED,sEAWC;IAED,mEAQC;IAED,mEAQC;IAED,sEAMC;IAED,oEAQC;IAED,uFA0BC;IAED,uFA0BC;IAED,mDAMC;IAED,kDAKC;IAED,gEAKC;IAED;;;;;;;;;;;MAiDC;IAED,oFAMC;IAED,6EAmDC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;MA2BC;IAED,kGAYC;IAED,+CAEC;IAED,wDAUC;IAED,iFAMC;IAED,iEAGC;IAED,yDAaC;IAED,oEAMC;IAED;;;MAMC;IAED,sDAiBC;IAED,8DAMC;IAED,4EAKC;IAED,+CAEC;IAED,sEAGC;IAED,2DAUC;IAED,yEAYC;IAED,oDAIC;IAED,2EAUC;IAED,0EAcC;IAED,sFA4BC;IAED,sFA4BC;IAED,kFAeC;IAED,2DAMC;IAED,uDAqBC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAWC;IAED,iEAKC;IAED,uEASC;IAED,mEAKC;IAED,yEASC;IAED,2EASC;IAED,gGAMC;IAED,gFAGC;IAED,yCAYC;IAGD,8CAyBC;IAED,gFAGC;IAED,iEAEC;IAED,gEAEC;IAED,gEAIC;IAED,gEAIC;IAED,+EAgCC;IAED,qCAcC;IAED,qCAcC;IAED,4EAwCC;IAED,4DAGC;IAED,sDASC;IAED,gEAGC;IAED,yDAWC;IAED,kEAGC;IAED,2DAWC;IAED,sEAeC;IAED,4CAOC;IAED,+BAKC;IAED,qDAiBC;IAED,gCAIC;IAED,kCAEC;IA6BD,4CAEC;IAED,+DAaC;IAED,kDAiBC;IAED,2GAKC;IAED,sDAIC;IAED,qCAEC;IAED,uDAMC;IAED,sCAEC;IAED,uDASC;IAED,sCAEC;IAED,2DAqBC;IAED,0CAEC;IAED,mCAeC;IAED,2FAeC;IAED,6CAIC;IAED,0CAIC;IAED,uCAIC;IAED,wCAIC;IAED,2CAIC;IAED,mEASC;IAED,qDAQC;IAED,4CAUC;IAED,2DAOC;IAED,0CASC;IAED,6FAIC;IAED,yEAeC;IAED,gDAYC;IAGD,6DAgBC;CACF;AA3xFD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IAiBE,0FAMC;IAtBD,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,gBAAW;IACX,WAAM;IACN,WAAM;IACN,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IACb,uBAAkB;IAClB,uBAAkB;IAClB,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
|