@marmooo/midy 0.3.0 → 0.3.1
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/README.md +2 -1
- package/esm/midy-GM1.d.ts +4 -2
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +52 -29
- package/esm/midy-GM2.d.ts +4 -2
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +73 -49
- package/esm/midy-GMLite.d.ts +4 -2
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +55 -32
- package/esm/midy.d.ts +7 -5
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +79 -54
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +4 -2
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +52 -29
- package/script/midy-GM2.d.ts +4 -2
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +73 -49
- package/script/midy-GMLite.d.ts +4 -2
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +55 -32
- package/script/midy.d.ts +7 -5
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +79 -54
package/esm/midy-GMLite.js
CHANGED
|
@@ -446,7 +446,7 @@ export class MidyGMLite {
|
|
|
446
446
|
const startTime = event.startTime + this.startDelay - offset;
|
|
447
447
|
switch (event.type) {
|
|
448
448
|
case "noteOn":
|
|
449
|
-
if (event.velocity
|
|
449
|
+
if (0 < event.velocity) {
|
|
450
450
|
await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, startTime);
|
|
451
451
|
break;
|
|
452
452
|
}
|
|
@@ -494,7 +494,7 @@ export class MidyGMLite {
|
|
|
494
494
|
if (queueIndex >= this.timeline.length) {
|
|
495
495
|
await Promise.all(this.notePromises);
|
|
496
496
|
this.notePromises = [];
|
|
497
|
-
this.exclusiveClassNotes.
|
|
497
|
+
this.exclusiveClassNotes.fill(undefined);
|
|
498
498
|
this.audioBufferCache.clear();
|
|
499
499
|
resolve();
|
|
500
500
|
return;
|
|
@@ -613,6 +613,17 @@ export class MidyGMLite {
|
|
|
613
613
|
}
|
|
614
614
|
return { instruments, timeline };
|
|
615
615
|
}
|
|
616
|
+
stopActiveNotes(channelNumber, velocity, force, scheduleTime) {
|
|
617
|
+
const channel = this.channels[channelNumber];
|
|
618
|
+
const promises = [];
|
|
619
|
+
const activeNotes = this.getActiveNotes(channel, scheduleTime);
|
|
620
|
+
activeNotes.forEach((note) => {
|
|
621
|
+
const promise = this.scheduleNoteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force, undefined);
|
|
622
|
+
this.notePromises.push(promise);
|
|
623
|
+
promises.push(promise);
|
|
624
|
+
});
|
|
625
|
+
return Promise.all(promises);
|
|
626
|
+
}
|
|
616
627
|
stopChannelNotes(channelNumber, velocity, force, scheduleTime) {
|
|
617
628
|
const channel = this.channels[channelNumber];
|
|
618
629
|
const promises = [];
|
|
@@ -684,6 +695,8 @@ export class MidyGMLite {
|
|
|
684
695
|
const note = noteList[i];
|
|
685
696
|
if (!note)
|
|
686
697
|
continue;
|
|
698
|
+
if (note.ending)
|
|
699
|
+
continue;
|
|
687
700
|
callback(note);
|
|
688
701
|
}
|
|
689
702
|
});
|
|
@@ -911,20 +924,21 @@ export class MidyGMLite {
|
|
|
911
924
|
this.handleExclusiveClass(note, channelNumber, startTime);
|
|
912
925
|
this.handleDrumExclusiveClass(note, channelNumber, startTime);
|
|
913
926
|
const scheduledNotes = channel.scheduledNotes;
|
|
914
|
-
let
|
|
915
|
-
if (
|
|
916
|
-
|
|
927
|
+
let noteList = scheduledNotes.get(noteNumber);
|
|
928
|
+
if (noteList) {
|
|
929
|
+
noteList.push(note);
|
|
917
930
|
}
|
|
918
931
|
else {
|
|
919
|
-
|
|
920
|
-
scheduledNotes.set(noteNumber,
|
|
932
|
+
noteList = [note];
|
|
933
|
+
scheduledNotes.set(noteNumber, noteList);
|
|
921
934
|
}
|
|
922
|
-
if (
|
|
935
|
+
if (channel.isDrum) {
|
|
923
936
|
const stopTime = startTime + note.bufferSource.buffer.duration;
|
|
924
|
-
const index =
|
|
937
|
+
const index = noteList.length - 1;
|
|
925
938
|
const promise = new Promise((resolve) => {
|
|
926
939
|
note.bufferSource.onended = () => {
|
|
927
|
-
|
|
940
|
+
noteList[index] = undefined;
|
|
941
|
+
this.disconnectNote(note);
|
|
928
942
|
resolve();
|
|
929
943
|
};
|
|
930
944
|
note.bufferSource.stop(stopTime);
|
|
@@ -936,8 +950,7 @@ export class MidyGMLite {
|
|
|
936
950
|
scheduleTime ??= this.audioContext.currentTime;
|
|
937
951
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime);
|
|
938
952
|
}
|
|
939
|
-
disconnectNote(note
|
|
940
|
-
scheduledNotes[index] = null;
|
|
953
|
+
disconnectNote(note) {
|
|
941
954
|
note.bufferSource.disconnect();
|
|
942
955
|
note.filterNode.disconnect();
|
|
943
956
|
note.volumeEnvelopeNode.disconnect();
|
|
@@ -947,8 +960,8 @@ export class MidyGMLite {
|
|
|
947
960
|
note.modulationLFO.stop();
|
|
948
961
|
}
|
|
949
962
|
}
|
|
950
|
-
stopNote(endTime, stopTime,
|
|
951
|
-
const note =
|
|
963
|
+
stopNote(endTime, stopTime, noteList, index) {
|
|
964
|
+
const note = noteList[index];
|
|
952
965
|
note.volumeEnvelopeNode.gain
|
|
953
966
|
.cancelScheduledValues(endTime)
|
|
954
967
|
.linearRampToValueAtTime(0, stopTime);
|
|
@@ -958,12 +971,23 @@ export class MidyGMLite {
|
|
|
958
971
|
}, stopTime);
|
|
959
972
|
return new Promise((resolve) => {
|
|
960
973
|
note.bufferSource.onended = () => {
|
|
961
|
-
|
|
974
|
+
noteList[index] = undefined;
|
|
975
|
+
this.disconnectNote(note);
|
|
962
976
|
resolve();
|
|
963
977
|
};
|
|
964
978
|
note.bufferSource.stop(stopTime);
|
|
965
979
|
});
|
|
966
980
|
}
|
|
981
|
+
findNoteOffTarget(noteList) {
|
|
982
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
983
|
+
const note = noteList[i];
|
|
984
|
+
if (!note)
|
|
985
|
+
continue;
|
|
986
|
+
if (note.ending)
|
|
987
|
+
continue;
|
|
988
|
+
return [note, i];
|
|
989
|
+
}
|
|
990
|
+
}
|
|
967
991
|
scheduleNoteOff(channelNumber, noteNumber, _velocity, endTime, force) {
|
|
968
992
|
const channel = this.channels[channelNumber];
|
|
969
993
|
if (channel.isDrum)
|
|
@@ -972,21 +996,20 @@ export class MidyGMLite {
|
|
|
972
996
|
return;
|
|
973
997
|
if (!channel.scheduledNotes.has(noteNumber))
|
|
974
998
|
return;
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
}
|
|
999
|
+
const noteList = channel.scheduledNotes.get(noteNumber);
|
|
1000
|
+
if (!noteList)
|
|
1001
|
+
return; // be careful with drum channel
|
|
1002
|
+
const noteOffTarget = this.findNoteOffTarget(noteList, endTime);
|
|
1003
|
+
if (!noteOffTarget)
|
|
1004
|
+
return;
|
|
1005
|
+
const [note, i] = noteOffTarget;
|
|
1006
|
+
const volRelease = endTime + note.voiceParams.volRelease;
|
|
1007
|
+
const modRelease = endTime + note.voiceParams.modRelease;
|
|
1008
|
+
note.filterNode.frequency
|
|
1009
|
+
.cancelScheduledValues(endTime)
|
|
1010
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
1011
|
+
const stopTime = Math.min(volRelease, modRelease);
|
|
1012
|
+
return this.stopNote(endTime, stopTime, noteList, i);
|
|
990
1013
|
}
|
|
991
1014
|
noteOff(channelNumber, noteNumber, velocity, scheduleTime) {
|
|
992
1015
|
scheduleTime ??= this.audioContext.currentTime;
|
|
@@ -1308,7 +1331,7 @@ export class MidyGMLite {
|
|
|
1308
1331
|
}
|
|
1309
1332
|
allSoundOff(channelNumber, _value, scheduleTime) {
|
|
1310
1333
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1311
|
-
return this.
|
|
1334
|
+
return this.stopActiveNotes(channelNumber, 0, true, scheduleTime);
|
|
1312
1335
|
}
|
|
1313
1336
|
resetAllStates(channelNumber) {
|
|
1314
1337
|
const channel = this.channels[channelNumber];
|
|
@@ -1346,7 +1369,7 @@ export class MidyGMLite {
|
|
|
1346
1369
|
}
|
|
1347
1370
|
allNotesOff(channelNumber, _value, scheduleTime) {
|
|
1348
1371
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1349
|
-
return this.
|
|
1372
|
+
return this.stopActiveNotes(channelNumber, 0, false, scheduleTime);
|
|
1350
1373
|
}
|
|
1351
1374
|
handleUniversalNonRealTimeExclusiveMessage(data, scheduleTime) {
|
|
1352
1375
|
switch (data[2]) {
|
package/esm/midy.d.ts
CHANGED
|
@@ -99,7 +99,7 @@ export class Midy {
|
|
|
99
99
|
66: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
100
100
|
67: (channelNumber: any, softPedal: any, scheduleTime: any) => void;
|
|
101
101
|
71: (channelNumber: any, filterResonance: any, scheduleTime: any) => void;
|
|
102
|
-
72: (channelNumber: any, releaseTime: any,
|
|
102
|
+
72: (channelNumber: any, releaseTime: any, scheduleTime: any) => void;
|
|
103
103
|
73: (channelNumber: any, attackTime: any, scheduleTime: any) => void;
|
|
104
104
|
74: (channelNumber: any, brightness: any, scheduleTime: any) => void;
|
|
105
105
|
75: (channelNumber: any, dacayTime: any, scheduleTime: any) => void;
|
|
@@ -157,6 +157,7 @@ export class Midy {
|
|
|
157
157
|
instruments: Set<any>;
|
|
158
158
|
timeline: any[];
|
|
159
159
|
};
|
|
160
|
+
stopActiveNotes(channelNumber: any, velocity: any, force: any, scheduleTime: any): Promise<any[]>;
|
|
160
161
|
stopChannelNotes(channelNumber: any, velocity: any, force: any, scheduleTime: any): Promise<any[]>;
|
|
161
162
|
stopNotes(velocity: any, force: any, scheduleTime: any): Promise<any[]>;
|
|
162
163
|
start(): Promise<void>;
|
|
@@ -216,8 +217,9 @@ export class Midy {
|
|
|
216
217
|
isDrumNoteOffException(channel: any, noteNumber: any): boolean;
|
|
217
218
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
|
|
218
219
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
|
|
219
|
-
disconnectNote(note: any
|
|
220
|
-
stopNote(endTime: any, stopTime: any,
|
|
220
|
+
disconnectNote(note: any): void;
|
|
221
|
+
stopNote(endTime: any, stopTime: any, noteList: any, index: any): Promise<any>;
|
|
222
|
+
findNoteOffTarget(noteList: any): any[] | undefined;
|
|
221
223
|
scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any, portamentoNoteNumber: any): Promise<any> | undefined;
|
|
222
224
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
|
|
223
225
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
|
|
@@ -266,7 +268,7 @@ export class Midy {
|
|
|
266
268
|
66: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
267
269
|
67: (channelNumber: any, softPedal: any, scheduleTime: any) => void;
|
|
268
270
|
71: (channelNumber: any, filterResonance: any, scheduleTime: any) => void;
|
|
269
|
-
72: (channelNumber: any, releaseTime: any,
|
|
271
|
+
72: (channelNumber: any, releaseTime: any, scheduleTime: any) => void;
|
|
270
272
|
73: (channelNumber: any, attackTime: any, scheduleTime: any) => void;
|
|
271
273
|
74: (channelNumber: any, brightness: any, scheduleTime: any) => void;
|
|
272
274
|
75: (channelNumber: any, dacayTime: any, scheduleTime: any) => void;
|
|
@@ -309,7 +311,7 @@ export class Midy {
|
|
|
309
311
|
setSostenutoPedal(channelNumber: any, value: any, scheduleTime: any): void;
|
|
310
312
|
setSoftPedal(channelNumber: any, softPedal: any, scheduleTime: any): void;
|
|
311
313
|
setFilterResonance(channelNumber: any, filterResonance: any, scheduleTime: any): void;
|
|
312
|
-
setReleaseTime(channelNumber: any, releaseTime: any,
|
|
314
|
+
setReleaseTime(channelNumber: any, releaseTime: any, scheduleTime: any): void;
|
|
313
315
|
setAttackTime(channelNumber: any, attackTime: any, scheduleTime: any): void;
|
|
314
316
|
setBrightness(channelNumber: any, brightness: any, scheduleTime: any): void;
|
|
315
317
|
setDecayTime(channelNumber: any, dacayTime: any, scheduleTime: any): void;
|
package/esm/midy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"AAkNA;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,yCAmBC;IAED,6DA2BC;IAED,4DASC;IAED,2CAcC;IAED,2EAqEC;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,
|
|
1
|
+
{"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"AAkNA;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,yCAmBC;IAED,6DA2BC;IAED,4DASC;IAED,2CAcC;IAED,2EAqEC;IAED,mCAOC;IAED,0BAuDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MAgHC;IAED,kGAiBC;IAED,mGAiBC;IAED,wEAMC;IAED,uBAKC;IAED,aAMC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDASC;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,+DAOC;IAED,wCAGC;IAED,mFAUC;IAED,oEAiBC;IAED,qDAoBC;IAED,6CAIC;IAED,mFAsBC;IAED,oEA2BC;IAED,kEAoBC;IAED,+DAaC;IAED,+GA0BC;IAED,iIAqEC;IAED,4BAYC;IAED,0EAkBC;IAED,8EAqBC;IAED,+DAKC;IAED,mHA2DC;IAED,6FASC;IAED,gCAsBC;IAED,+EAiBC;IAED,oDAOC;IAED,oJAuCC;IAED,yGAUC;IAED,4GAeC;IAED,uFAgBC;IAED,mGAoCC;IAED,yGAeC;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,oFAQC;IAED,6EAmDC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAqCC;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,0EAeC;IAED,sFAUC;IAED,8EAKC;IAED,4EASC;IAED,4EAaC;IAED,0EAQC;IAED,8EASC;IAED,gFAeC;IAED,6DAUC;IAED,sFA4BC;IAED,sFA4BC;IAED,kFAeC;IAED,2DAMC;IAED,mEAyBC;IAGD,wCAEC;IAGD,wCAEC;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,8CA0BC;IAED,gFAGC;IAED,iEAEC;IAED,gEAEC;IAED,gEAIC;IAED,gEAIC;IAED,+EAuCC;IAED,qCAcC;IAED,qCAcC;IAED,4EA6DC;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,2FAgBC;IAED,2FAoBC;IAED,iDAIC;IAED,wDAMC;IAED,qDAMC;IAED,kDAMC;IAED,mDAMC;IAED,sDAMC;IAED,mEASC;IAED,qDAUC;IAED,4CAUC;IAED,2DAOC;IAED,0CAWC;IAED,6FAIC;IAED,yEAiBC;IAED,gDAYC;IAGD,6DAgBC;CACF;AAniGD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IAkBE,0FAMC;IAvBD,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;IACX,iBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
|
package/esm/midy.js
CHANGED
|
@@ -626,7 +626,7 @@ export class Midy {
|
|
|
626
626
|
const startTime = event.startTime + this.startDelay - offset;
|
|
627
627
|
switch (event.type) {
|
|
628
628
|
case "noteOn":
|
|
629
|
-
if (event.velocity
|
|
629
|
+
if (0 < event.velocity) {
|
|
630
630
|
await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, startTime, event.portamento);
|
|
631
631
|
break;
|
|
632
632
|
}
|
|
@@ -842,6 +842,17 @@ export class Midy {
|
|
|
842
842
|
}
|
|
843
843
|
return { instruments, timeline };
|
|
844
844
|
}
|
|
845
|
+
stopActiveNotes(channelNumber, velocity, force, scheduleTime) {
|
|
846
|
+
const channel = this.channels[channelNumber];
|
|
847
|
+
const promises = [];
|
|
848
|
+
const activeNotes = this.getActiveNotes(channel, scheduleTime);
|
|
849
|
+
activeNotes.forEach((note) => {
|
|
850
|
+
const promise = this.scheduleNoteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force, undefined);
|
|
851
|
+
this.notePromises.push(promise);
|
|
852
|
+
promises.push(promise);
|
|
853
|
+
});
|
|
854
|
+
return Promise.all(promises);
|
|
855
|
+
}
|
|
845
856
|
stopChannelNotes(channelNumber, velocity, force, scheduleTime) {
|
|
846
857
|
const channel = this.channels[channelNumber];
|
|
847
858
|
const promises = [];
|
|
@@ -913,6 +924,8 @@ export class Midy {
|
|
|
913
924
|
const note = noteList[i];
|
|
914
925
|
if (!note)
|
|
915
926
|
continue;
|
|
927
|
+
if (note.ending)
|
|
928
|
+
continue;
|
|
916
929
|
callback(note);
|
|
917
930
|
}
|
|
918
931
|
});
|
|
@@ -1282,7 +1295,7 @@ export class Midy {
|
|
|
1282
1295
|
type: "lowpass",
|
|
1283
1296
|
Q: voiceParams.initialFilterQ / 5 * state.filterResonance, // dB
|
|
1284
1297
|
});
|
|
1285
|
-
if (portamento) {
|
|
1298
|
+
if (0.5 <= state.portamento && portamento) {
|
|
1286
1299
|
note.portamento = true;
|
|
1287
1300
|
this.setPortamentoStartVolumeEnvelope(channel, note, now);
|
|
1288
1301
|
this.setPortamentoStartFilterEnvelope(channel, note, now);
|
|
@@ -1372,8 +1385,8 @@ export class Midy {
|
|
|
1372
1385
|
if (!channel.isDrum)
|
|
1373
1386
|
return false;
|
|
1374
1387
|
const programNumber = channel.programNumber;
|
|
1375
|
-
return (programNumber === 48 && noteNumber === 88) ||
|
|
1376
|
-
(programNumber === 56 && 47 <= noteNumber && noteNumber <= 84);
|
|
1388
|
+
return !((programNumber === 48 && noteNumber === 88) ||
|
|
1389
|
+
(programNumber === 56 && 47 <= noteNumber && noteNumber <= 84));
|
|
1377
1390
|
}
|
|
1378
1391
|
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime, portamento) {
|
|
1379
1392
|
const channel = this.channels[channelNumber];
|
|
@@ -1395,20 +1408,21 @@ export class Midy {
|
|
|
1395
1408
|
this.handleExclusiveClass(note, channelNumber, startTime);
|
|
1396
1409
|
this.handleDrumExclusiveClass(note, channelNumber, startTime);
|
|
1397
1410
|
const scheduledNotes = channel.scheduledNotes;
|
|
1398
|
-
let
|
|
1399
|
-
if (
|
|
1400
|
-
|
|
1411
|
+
let noteList = scheduledNotes.get(noteNumber);
|
|
1412
|
+
if (noteList) {
|
|
1413
|
+
noteList.push(note);
|
|
1401
1414
|
}
|
|
1402
1415
|
else {
|
|
1403
|
-
|
|
1404
|
-
scheduledNotes.set(noteNumber,
|
|
1416
|
+
noteList = [note];
|
|
1417
|
+
scheduledNotes.set(noteNumber, noteList);
|
|
1405
1418
|
}
|
|
1406
1419
|
if (this.isDrumNoteOffException(channel, noteNumber)) {
|
|
1407
1420
|
const stopTime = startTime + note.bufferSource.buffer.duration;
|
|
1408
|
-
const index =
|
|
1421
|
+
const index = noteList.length - 1;
|
|
1409
1422
|
const promise = new Promise((resolve) => {
|
|
1410
1423
|
note.bufferSource.onended = () => {
|
|
1411
|
-
|
|
1424
|
+
noteList[index] = undefined;
|
|
1425
|
+
this.disconnectNote(note);
|
|
1412
1426
|
resolve();
|
|
1413
1427
|
};
|
|
1414
1428
|
note.bufferSource.stop(stopTime);
|
|
@@ -1420,8 +1434,7 @@ export class Midy {
|
|
|
1420
1434
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1421
1435
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime, false);
|
|
1422
1436
|
}
|
|
1423
|
-
disconnectNote(note
|
|
1424
|
-
scheduledNotes[index] = null;
|
|
1437
|
+
disconnectNote(note) {
|
|
1425
1438
|
note.bufferSource.disconnect();
|
|
1426
1439
|
note.filterNode.disconnect();
|
|
1427
1440
|
note.volumeEnvelopeNode.disconnect();
|
|
@@ -1444,8 +1457,8 @@ export class Midy {
|
|
|
1444
1457
|
note.chorusEffectsSend.disconnect();
|
|
1445
1458
|
}
|
|
1446
1459
|
}
|
|
1447
|
-
stopNote(endTime, stopTime,
|
|
1448
|
-
const note =
|
|
1460
|
+
stopNote(endTime, stopTime, noteList, index) {
|
|
1461
|
+
const note = noteList[index];
|
|
1449
1462
|
note.volumeEnvelopeNode.gain
|
|
1450
1463
|
.cancelScheduledValues(endTime)
|
|
1451
1464
|
.linearRampToValueAtTime(0, stopTime);
|
|
@@ -1455,12 +1468,23 @@ export class Midy {
|
|
|
1455
1468
|
}, stopTime);
|
|
1456
1469
|
return new Promise((resolve) => {
|
|
1457
1470
|
note.bufferSource.onended = () => {
|
|
1458
|
-
|
|
1471
|
+
noteList[index] = undefined;
|
|
1472
|
+
this.disconnectNote(note);
|
|
1459
1473
|
resolve();
|
|
1460
1474
|
};
|
|
1461
1475
|
note.bufferSource.stop(stopTime);
|
|
1462
1476
|
});
|
|
1463
1477
|
}
|
|
1478
|
+
findNoteOffTarget(noteList) {
|
|
1479
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1480
|
+
const note = noteList[i];
|
|
1481
|
+
if (!note)
|
|
1482
|
+
continue;
|
|
1483
|
+
if (note.ending)
|
|
1484
|
+
continue;
|
|
1485
|
+
return [note, i];
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1464
1488
|
scheduleNoteOff(channelNumber, noteNumber, _velocity, endTime, force, portamentoNoteNumber) {
|
|
1465
1489
|
const channel = this.channels[channelNumber];
|
|
1466
1490
|
if (this.isDrumNoteOffException(channel, noteNumber))
|
|
@@ -1472,35 +1496,32 @@ export class Midy {
|
|
|
1472
1496
|
if (channel.sostenutoNotes.has(noteNumber))
|
|
1473
1497
|
return;
|
|
1474
1498
|
}
|
|
1475
|
-
|
|
1499
|
+
const noteList = channel.scheduledNotes.get(noteNumber);
|
|
1500
|
+
if (!noteList)
|
|
1501
|
+
return; // be careful with drum channel
|
|
1502
|
+
const noteOffTarget = this.findNoteOffTarget(noteList, endTime);
|
|
1503
|
+
if (!noteOffTarget)
|
|
1476
1504
|
return;
|
|
1477
|
-
const
|
|
1478
|
-
|
|
1479
|
-
const
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
const baseRate = note.voiceParams.playbackRate;
|
|
1498
|
-
const targetRate = baseRate * Math.pow(2, deltaNote / 12);
|
|
1499
|
-
note.bufferSource.playbackRate
|
|
1500
|
-
.cancelScheduledValues(endTime)
|
|
1501
|
-
.linearRampToValueAtTime(targetRate, portamentoTime);
|
|
1502
|
-
return this.stopNote(endTime, portamentoTime, scheduledNotes, i);
|
|
1503
|
-
}
|
|
1505
|
+
const [note, i] = noteOffTarget;
|
|
1506
|
+
if (0.5 <= state.portamento && portamentoNoteNumber !== undefined) {
|
|
1507
|
+
const portamentoTime = endTime + this.getPortamentoTime(channel);
|
|
1508
|
+
const deltaNote = portamentoNoteNumber - noteNumber;
|
|
1509
|
+
const baseRate = note.voiceParams.playbackRate;
|
|
1510
|
+
const targetRate = baseRate * Math.pow(2, deltaNote / 12);
|
|
1511
|
+
note.bufferSource.playbackRate
|
|
1512
|
+
.cancelScheduledValues(endTime)
|
|
1513
|
+
.linearRampToValueAtTime(targetRate, portamentoTime);
|
|
1514
|
+
return this.stopNote(endTime, portamentoTime, noteList, i);
|
|
1515
|
+
}
|
|
1516
|
+
else {
|
|
1517
|
+
const volRelease = endTime +
|
|
1518
|
+
note.voiceParams.volRelease * state.releaseTime * 2;
|
|
1519
|
+
const modRelease = endTime + note.voiceParams.modRelease;
|
|
1520
|
+
note.filterNode.frequency
|
|
1521
|
+
.cancelScheduledValues(endTime)
|
|
1522
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
1523
|
+
const stopTime = Math.min(volRelease, modRelease);
|
|
1524
|
+
return this.stopNote(endTime, stopTime, noteList, i);
|
|
1504
1525
|
}
|
|
1505
1526
|
}
|
|
1506
1527
|
noteOff(channelNumber, noteNumber, velocity, scheduleTime) {
|
|
@@ -1562,7 +1583,7 @@ export class Midy {
|
|
|
1562
1583
|
const note = activeNotes.get(noteNumber);
|
|
1563
1584
|
this.setControllerParameters(channel, note, table);
|
|
1564
1585
|
}
|
|
1565
|
-
|
|
1586
|
+
this.applyVoiceParams(channel, 10);
|
|
1566
1587
|
}
|
|
1567
1588
|
handleProgramChange(channelNumber, programNumber, _scheduleTime) {
|
|
1568
1589
|
const channel = this.channels[channelNumber];
|
|
@@ -1594,7 +1615,7 @@ export class Midy {
|
|
|
1594
1615
|
this.getActiveNotes(channel, scheduleTime).forEach((note) => {
|
|
1595
1616
|
this.setControllerParameters(channel, note, table);
|
|
1596
1617
|
});
|
|
1597
|
-
|
|
1618
|
+
this.applyVoiceParams(channel, 13);
|
|
1598
1619
|
}
|
|
1599
1620
|
handlePitchBendMessage(channelNumber, lsb, msb, scheduleTime) {
|
|
1600
1621
|
const pitchBend = msb * 128 + lsb;
|
|
@@ -1771,6 +1792,8 @@ export class Midy {
|
|
|
1771
1792
|
state.set(channel.state.array);
|
|
1772
1793
|
state[2] = velocity / 127;
|
|
1773
1794
|
state[3] = noteNumber / 127;
|
|
1795
|
+
state[10] = state.polyphonicKeyPressure / 127;
|
|
1796
|
+
state[13] = state.channelPressure / 127;
|
|
1774
1797
|
return state;
|
|
1775
1798
|
}
|
|
1776
1799
|
applyVoiceParams(channel, controllerType, scheduleTime) {
|
|
@@ -1797,7 +1820,7 @@ export class Midy {
|
|
|
1797
1820
|
if (key in voiceParams)
|
|
1798
1821
|
noteVoiceParams[key] = voiceParams[key];
|
|
1799
1822
|
}
|
|
1800
|
-
if (note.portamento) {
|
|
1823
|
+
if (0.5 <= channel.state.portamento && note.portamento) {
|
|
1801
1824
|
this.setPortamentoStartFilterEnvelope(channel, note, scheduleTime);
|
|
1802
1825
|
}
|
|
1803
1826
|
else {
|
|
@@ -2004,10 +2027,11 @@ export class Midy {
|
|
|
2004
2027
|
const channel = this.channels[channelNumber];
|
|
2005
2028
|
if (channel.isDrum)
|
|
2006
2029
|
return;
|
|
2030
|
+
const state = channel.state;
|
|
2007
2031
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2008
|
-
|
|
2032
|
+
state.softPedal = softPedal / 127;
|
|
2009
2033
|
this.processScheduledNotes(channel, (note) => {
|
|
2010
|
-
if (note.portamento) {
|
|
2034
|
+
if (0.5 <= state.portamento && note.portamento) {
|
|
2011
2035
|
this.setPortamentoStartVolumeEnvelope(channel, note, scheduleTime);
|
|
2012
2036
|
this.setPortamentoStartFilterEnvelope(channel, note, scheduleTime);
|
|
2013
2037
|
}
|
|
@@ -2029,7 +2053,7 @@ export class Midy {
|
|
|
2029
2053
|
note.filterNode.Q.setValueAtTime(Q, scheduleTime);
|
|
2030
2054
|
});
|
|
2031
2055
|
}
|
|
2032
|
-
setReleaseTime(channelNumber, releaseTime,
|
|
2056
|
+
setReleaseTime(channelNumber, releaseTime, scheduleTime) {
|
|
2033
2057
|
const channel = this.channels[channelNumber];
|
|
2034
2058
|
if (channel.isDrum)
|
|
2035
2059
|
return;
|
|
@@ -2052,10 +2076,11 @@ export class Midy {
|
|
|
2052
2076
|
const channel = this.channels[channelNumber];
|
|
2053
2077
|
if (channel.isDrum)
|
|
2054
2078
|
return;
|
|
2079
|
+
const state = channel.state;
|
|
2055
2080
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2056
|
-
|
|
2081
|
+
state.brightness = brightness / 64;
|
|
2057
2082
|
this.processScheduledNotes(channel, (note) => {
|
|
2058
|
-
if (note.portamento) {
|
|
2083
|
+
if (0.5 <= state.portamento && note.portamento) {
|
|
2059
2084
|
this.setPortamentoStartFilterEnvelope(channel, note, scheduleTime);
|
|
2060
2085
|
}
|
|
2061
2086
|
else {
|
|
@@ -2316,7 +2341,7 @@ export class Midy {
|
|
|
2316
2341
|
}
|
|
2317
2342
|
allSoundOff(channelNumber, _value, scheduleTime) {
|
|
2318
2343
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2319
|
-
return this.
|
|
2344
|
+
return this.stopActiveNotes(channelNumber, 0, true, scheduleTime);
|
|
2320
2345
|
}
|
|
2321
2346
|
resetAllStates(channelNumber) {
|
|
2322
2347
|
const channel = this.channels[channelNumber];
|
|
@@ -2361,7 +2386,7 @@ export class Midy {
|
|
|
2361
2386
|
}
|
|
2362
2387
|
allNotesOff(channelNumber, _value, scheduleTime) {
|
|
2363
2388
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2364
|
-
return this.
|
|
2389
|
+
return this.stopActiveNotes(channelNumber, 0, false, scheduleTime);
|
|
2365
2390
|
}
|
|
2366
2391
|
omniOff(channelNumber, value, scheduleTime) {
|
|
2367
2392
|
this.allNotesOff(channelNumber, value, scheduleTime);
|
package/package.json
CHANGED
package/script/midy-GM1.d.ts
CHANGED
|
@@ -87,6 +87,7 @@ export class MidyGM1 {
|
|
|
87
87
|
instruments: Set<any>;
|
|
88
88
|
timeline: any[];
|
|
89
89
|
};
|
|
90
|
+
stopActiveNotes(channelNumber: any, velocity: any, force: any, scheduleTime: any): Promise<any[]>;
|
|
90
91
|
stopChannelNotes(channelNumber: any, velocity: any, force: any, scheduleTime: any): Promise<any[]>;
|
|
91
92
|
stopNotes(velocity: any, force: any, scheduleTime: any): Promise<any[]>;
|
|
92
93
|
start(): Promise<void>;
|
|
@@ -116,8 +117,9 @@ export class MidyGM1 {
|
|
|
116
117
|
handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
117
118
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
118
119
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
|
|
119
|
-
disconnectNote(note: any
|
|
120
|
-
stopNote(endTime: any, stopTime: any,
|
|
120
|
+
disconnectNote(note: any): void;
|
|
121
|
+
stopNote(endTime: any, stopTime: any, noteList: any, index: any): Promise<any>;
|
|
122
|
+
findNoteOffTarget(noteList: any): any[] | undefined;
|
|
121
123
|
scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): Promise<any> | undefined;
|
|
122
124
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
|
|
123
125
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
|
package/script/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;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,
|
|
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,kGAiBC;IAED,mGAgBC;IAED,wEAMC;IAED,uBAKC;IAED,aAMC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDASC;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,kGAsCC;IAED,6FAQC;IAED,gCASC;IAED,+EAiBC;IAED,oDAOC;IAED,yHAsBC;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;AA3/CD;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"}
|