@marmooo/midy 0.4.0 → 0.4.2
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 +14 -1
- package/esm/midy-GM1.d.ts +8 -7
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +138 -81
- package/esm/midy-GM2.d.ts +8 -7
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +161 -96
- package/esm/midy-GMLite.d.ts +8 -7
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +126 -72
- package/esm/midy.d.ts +17 -12
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +275 -123
- package/package.json +2 -2
- package/script/midy-GM1.d.ts +8 -7
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +138 -81
- package/script/midy-GM2.d.ts +8 -7
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +161 -96
- package/script/midy-GMLite.d.ts +8 -7
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +126 -72
- package/script/midy.d.ts +17 -12
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +275 -123
package/esm/midy-GMLite.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export class MidyGMLite {
|
|
1
|
+
export class MidyGMLite extends EventTarget {
|
|
2
2
|
static channelSettings: {
|
|
3
3
|
scheduleIndex: number;
|
|
4
4
|
detune: number;
|
|
@@ -29,6 +29,7 @@ export class MidyGMLite {
|
|
|
29
29
|
isPaused: boolean;
|
|
30
30
|
isStopping: boolean;
|
|
31
31
|
isSeeking: boolean;
|
|
32
|
+
loop: boolean;
|
|
32
33
|
playPromise: any;
|
|
33
34
|
timeline: any[];
|
|
34
35
|
notePromises: any[];
|
|
@@ -68,7 +69,7 @@ export class MidyGMLite {
|
|
|
68
69
|
createChannels(audioContext: any): any[];
|
|
69
70
|
createAudioBuffer(voiceParams: any): Promise<any>;
|
|
70
71
|
createBufferSource(channel: any, voiceParams: any, audioBuffer: any): any;
|
|
71
|
-
scheduleTimelineEvents(scheduleTime: any, queueIndex: any):
|
|
72
|
+
scheduleTimelineEvents(scheduleTime: any, queueIndex: any): any;
|
|
72
73
|
getQueueIndex(second: any): number;
|
|
73
74
|
resetAllStates(): void;
|
|
74
75
|
updateStates(queueIndex: any, nextQueueIndex: any): void;
|
|
@@ -90,8 +91,8 @@ export class MidyGMLite {
|
|
|
90
91
|
seekTo(second: any): void;
|
|
91
92
|
calcTotalTime(): number;
|
|
92
93
|
currentTime(): number;
|
|
93
|
-
processScheduledNotes(channel: any, callback: any): void
|
|
94
|
-
processActiveNotes(channel: any, scheduleTime: any, callback: any): void
|
|
94
|
+
processScheduledNotes(channel: any, callback: any): Promise<void>;
|
|
95
|
+
processActiveNotes(channel: any, scheduleTime: any, callback: any): Promise<void>;
|
|
95
96
|
cbToRatio(cb: any): number;
|
|
96
97
|
rateToCent(rate: any): number;
|
|
97
98
|
centToRate(cent: any): number;
|
|
@@ -112,13 +113,13 @@ export class MidyGMLite {
|
|
|
112
113
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
113
114
|
disconnectNote(note: any): void;
|
|
114
115
|
releaseNote(channel: any, note: any, endTime: any): Promise<any>;
|
|
115
|
-
noteOff(channelNumber: any, noteNumber: any,
|
|
116
|
+
noteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): Promise<any>;
|
|
116
117
|
setNoteIndex(channel: any, index: any): void;
|
|
117
118
|
findNoteOffIndex(channel: any, noteNumber: any): any;
|
|
118
|
-
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any):
|
|
119
|
+
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): Promise<any>[];
|
|
119
120
|
createMessageHandlers(): any[];
|
|
120
121
|
handleMessage(data: any, scheduleTime: any): void;
|
|
121
|
-
handleChannelMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<
|
|
122
|
+
handleChannelMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
|
|
122
123
|
setProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
|
|
123
124
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
|
|
124
125
|
setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
|
package/esm/midy-GMLite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AA6GA;IA8BE;;;;;;;;;MASE;IAEF,+BAgBC;IAxDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,0BAAuD;IACvD,4BAAyB;IACzB,0BAAuB;IACvB,kCAA+B;IAC/B,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,cAAa;IACb,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IACrC,+BAEE;IAeA,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF,uBAAmD;IACnD;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,gBAAiD;IAMnD,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAWC;IAED;;;;MAeC;IAED,yCAaC;IAED,kDASC;IAED,0EAUC;IAED,gEAoDC;IAED,mCAOC;IAED,uBASC;IAED,yDAgCC;IAED,2BAyEC;IAED,uDAEC;IAED,wDAEC;IAED,qCAKC;IAED;;;MAwDC;IAED,kGAeC;IAED,mGAeC;IAED,wEAMC;IAED,uBAMC;IAED,sBAIC;IAED,uBAMC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAIC;IAED,kEAWC;IAED,kFAYC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,wCAIC;IAED,2DAIC;IAED,+DAIC;IAED,sDAeC;IAED,qDAoBC;IAED,6CAIC;IAED,sDAsBC;IAED,kEAoBC;IAED,4GAkCC;IAED,uEA4CC;IAED,0EAiBC;IAED,8EAiBC;IAED,oEAUC;IAED,0FAoBC;IAED,gCASC;IAED,iEAqBC;IAED,qGAsBC;IAED,6CAUC;IAED,qDAUC;IAED,8FAeC;IAED,+BAmBC;IAED,kDAOC;IAED,sGA2BC;IAED,mFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAYC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MAiCC;IAED,oFAMC;IAED,6EA2BC;IAED,qCAeC;IAED,+FAWC;IAED,wDASC;IAED,iFAKC;IAED,oEAKC;IAED;;;MAMC;IAED,8DAKC;IAED,4EAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAWC;IAED,kFAeC;IAED,uDAYC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAUC;IAED,gFAGC;IAED,6CAqBC;IAGD,8EAgCC;IAED,gFAGC;IAED,+EAgBC;IAED,qCASC;IAED,4EAaC;IAED,4DAGC;IAED,qDAKC;IAED,gDAYC;IAGD,6DAgBC;CACF"}
|
package/esm/midy-GMLite.js
CHANGED
|
@@ -26,12 +26,6 @@ class Note {
|
|
|
26
26
|
writable: true,
|
|
27
27
|
value: false
|
|
28
28
|
});
|
|
29
|
-
Object.defineProperty(this, "pending", {
|
|
30
|
-
enumerable: true,
|
|
31
|
-
configurable: true,
|
|
32
|
-
writable: true,
|
|
33
|
-
value: true
|
|
34
|
-
});
|
|
35
29
|
Object.defineProperty(this, "bufferSource", {
|
|
36
30
|
enumerable: true,
|
|
37
31
|
configurable: true,
|
|
@@ -77,6 +71,9 @@ class Note {
|
|
|
77
71
|
this.noteNumber = noteNumber;
|
|
78
72
|
this.velocity = velocity;
|
|
79
73
|
this.startTime = startTime;
|
|
74
|
+
this.ready = new Promise((resolve) => {
|
|
75
|
+
this.resolveReady = resolve;
|
|
76
|
+
});
|
|
80
77
|
}
|
|
81
78
|
}
|
|
82
79
|
const drumExclusiveClasses = new Uint8Array(128);
|
|
@@ -99,11 +96,11 @@ const defaultControllerState = {
|
|
|
99
96
|
pitchWheel: { type: 14, defaultValue: 8192 / 16383 },
|
|
100
97
|
pitchWheelSensitivity: { type: 16, defaultValue: 2 / 128 },
|
|
101
98
|
link: { type: 127, defaultValue: 0 },
|
|
102
|
-
|
|
99
|
+
modulationDepthMSB: { type: 128 + 1, defaultValue: 0 },
|
|
103
100
|
// dataMSB: { type: 128 + 6, defaultValue: 0, },
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
volumeMSB: { type: 128 + 7, defaultValue: 100 / 127 },
|
|
102
|
+
panMSB: { type: 128 + 10, defaultValue: 64 / 127 },
|
|
103
|
+
expressionMSB: { type: 128 + 11, defaultValue: 1 },
|
|
107
104
|
// dataLSB: { type: 128 + 38, defaultValue: 0, },
|
|
108
105
|
sustainPedal: { type: 128 + 64, defaultValue: 0 },
|
|
109
106
|
// rpnLSB: { type: 128 + 100, defaultValue: 127 },
|
|
@@ -163,8 +160,9 @@ const pitchEnvelopeKeys = [
|
|
|
163
160
|
"playbackRate",
|
|
164
161
|
];
|
|
165
162
|
const pitchEnvelopeKeySet = new Set(pitchEnvelopeKeys);
|
|
166
|
-
export class MidyGMLite {
|
|
163
|
+
export class MidyGMLite extends EventTarget {
|
|
167
164
|
constructor(audioContext) {
|
|
165
|
+
super();
|
|
168
166
|
Object.defineProperty(this, "mode", {
|
|
169
167
|
enumerable: true,
|
|
170
168
|
configurable: true,
|
|
@@ -279,6 +277,12 @@ export class MidyGMLite {
|
|
|
279
277
|
writable: true,
|
|
280
278
|
value: false
|
|
281
279
|
});
|
|
280
|
+
Object.defineProperty(this, "loop", {
|
|
281
|
+
enumerable: true,
|
|
282
|
+
configurable: true,
|
|
283
|
+
writable: true,
|
|
284
|
+
value: false
|
|
285
|
+
});
|
|
282
286
|
Object.defineProperty(this, "playPromise", {
|
|
283
287
|
enumerable: true,
|
|
284
288
|
configurable: true,
|
|
@@ -429,7 +433,7 @@ export class MidyGMLite {
|
|
|
429
433
|
return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
|
|
430
434
|
}
|
|
431
435
|
createChannelAudioNodes(audioContext) {
|
|
432
|
-
const { gainLeft, gainRight } = this.panToGain(defaultControllerState.
|
|
436
|
+
const { gainLeft, gainRight } = this.panToGain(defaultControllerState.panMSB.defaultValue);
|
|
433
437
|
const gainL = new GainNode(audioContext, { gain: gainLeft });
|
|
434
438
|
const gainR = new GainNode(audioContext, { gain: gainRight });
|
|
435
439
|
const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
|
|
@@ -457,10 +461,9 @@ export class MidyGMLite {
|
|
|
457
461
|
return channels;
|
|
458
462
|
}
|
|
459
463
|
async createAudioBuffer(voiceParams) {
|
|
460
|
-
const sample = voiceParams
|
|
461
|
-
const
|
|
462
|
-
const
|
|
463
|
-
const audioBuffer = await sample.toAudioBuffer(this.audioContext, sampleStart, sampleEnd);
|
|
464
|
+
const { sample, start, end } = voiceParams;
|
|
465
|
+
const sampleEnd = sample.data.length + end;
|
|
466
|
+
const audioBuffer = await sample.toAudioBuffer(this.audioContext, start, sampleEnd);
|
|
464
467
|
return audioBuffer;
|
|
465
468
|
}
|
|
466
469
|
createBufferSource(channel, voiceParams, audioBuffer) {
|
|
@@ -475,7 +478,7 @@ export class MidyGMLite {
|
|
|
475
478
|
}
|
|
476
479
|
return bufferSource;
|
|
477
480
|
}
|
|
478
|
-
|
|
481
|
+
scheduleTimelineEvents(scheduleTime, queueIndex) {
|
|
479
482
|
const timeOffset = this.resumeTime - this.startTime;
|
|
480
483
|
const lookAheadCheckTime = scheduleTime + timeOffset + this.lookAhead;
|
|
481
484
|
const schedulingOffset = this.startDelay - timeOffset;
|
|
@@ -487,12 +490,10 @@ export class MidyGMLite {
|
|
|
487
490
|
const startTime = event.startTime + schedulingOffset;
|
|
488
491
|
switch (event.type) {
|
|
489
492
|
case "noteOn":
|
|
490
|
-
|
|
493
|
+
this.noteOn(event.channel, event.noteNumber, event.velocity, startTime);
|
|
491
494
|
break;
|
|
492
495
|
case "noteOff": {
|
|
493
|
-
|
|
494
|
-
if (notePromise)
|
|
495
|
-
this.notePromises.push(notePromise);
|
|
496
|
+
this.noteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
|
|
496
497
|
break;
|
|
497
498
|
}
|
|
498
499
|
case "controller":
|
|
@@ -530,22 +531,23 @@ export class MidyGMLite {
|
|
|
530
531
|
}
|
|
531
532
|
}
|
|
532
533
|
updateStates(queueIndex, nextQueueIndex) {
|
|
534
|
+
const now = this.audioContext.currentTime;
|
|
533
535
|
if (nextQueueIndex < queueIndex)
|
|
534
536
|
queueIndex = 0;
|
|
535
537
|
for (let i = queueIndex; i < nextQueueIndex; i++) {
|
|
536
538
|
const event = this.timeline[i];
|
|
537
539
|
switch (event.type) {
|
|
538
540
|
case "controller":
|
|
539
|
-
this.setControlChange(event.channel, event.controllerType, event.value,
|
|
541
|
+
this.setControlChange(event.channel, event.controllerType, event.value, now - this.resumeTime + event.startTime);
|
|
540
542
|
break;
|
|
541
543
|
case "programChange":
|
|
542
|
-
this.setProgramChange(event.channel, event.programNumber,
|
|
544
|
+
this.setProgramChange(event.channel, event.programNumber, now - this.resumeTime + event.startTime);
|
|
543
545
|
break;
|
|
544
546
|
case "pitchBend":
|
|
545
|
-
this.setPitchBend(event.channel, event.value + 8192,
|
|
547
|
+
this.setPitchBend(event.channel, event.value + 8192, now - this.resumeTime + event.startTime);
|
|
546
548
|
break;
|
|
547
549
|
case "sysEx":
|
|
548
|
-
this.handleSysEx(event.data,
|
|
550
|
+
this.handleSysEx(event.data, now - this.resumeTime + event.startTime);
|
|
549
551
|
}
|
|
550
552
|
}
|
|
551
553
|
}
|
|
@@ -553,44 +555,80 @@ export class MidyGMLite {
|
|
|
553
555
|
if (this.audioContext.state === "suspended") {
|
|
554
556
|
await this.audioContext.resume();
|
|
555
557
|
}
|
|
558
|
+
const paused = this.isPaused;
|
|
556
559
|
this.isPlaying = true;
|
|
557
560
|
this.isPaused = false;
|
|
558
561
|
this.startTime = this.audioContext.currentTime;
|
|
562
|
+
if (paused) {
|
|
563
|
+
this.dispatchEvent(new Event("resumed"));
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
this.dispatchEvent(new Event("started"));
|
|
567
|
+
}
|
|
559
568
|
let queueIndex = this.getQueueIndex(this.resumeTime);
|
|
560
|
-
let
|
|
569
|
+
let exitReason;
|
|
561
570
|
this.notePromises = [];
|
|
562
|
-
while (
|
|
571
|
+
while (true) {
|
|
563
572
|
const now = this.audioContext.currentTime;
|
|
573
|
+
if (this.timeline.length <= queueIndex) {
|
|
574
|
+
await this.stopNotes(0, true, now);
|
|
575
|
+
if (this.loop) {
|
|
576
|
+
this.notePromises = [];
|
|
577
|
+
this.resetAllStates();
|
|
578
|
+
this.startTime = this.audioContext.currentTime;
|
|
579
|
+
this.resumeTime = 0;
|
|
580
|
+
queueIndex = 0;
|
|
581
|
+
this.dispatchEvent(new Event("looped"));
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
await this.audioContext.suspend();
|
|
586
|
+
exitReason = "ended";
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
564
590
|
if (this.isPausing) {
|
|
565
591
|
await this.stopNotes(0, true, now);
|
|
566
592
|
await this.audioContext.suspend();
|
|
567
593
|
this.notePromises = [];
|
|
594
|
+
this.isPausing = false;
|
|
595
|
+
exitReason = "paused";
|
|
568
596
|
break;
|
|
569
597
|
}
|
|
570
598
|
else if (this.isStopping) {
|
|
571
599
|
await this.stopNotes(0, true, now);
|
|
572
600
|
await this.audioContext.suspend();
|
|
573
|
-
|
|
601
|
+
this.isStopping = false;
|
|
602
|
+
exitReason = "stopped";
|
|
574
603
|
break;
|
|
575
604
|
}
|
|
576
605
|
else if (this.isSeeking) {
|
|
577
|
-
|
|
606
|
+
this.stopNotes(0, true, now);
|
|
578
607
|
this.startTime = this.audioContext.currentTime;
|
|
579
608
|
const nextQueueIndex = this.getQueueIndex(this.resumeTime);
|
|
580
609
|
this.updateStates(queueIndex, nextQueueIndex);
|
|
581
610
|
queueIndex = nextQueueIndex;
|
|
582
611
|
this.isSeeking = false;
|
|
612
|
+
this.dispatchEvent(new Event("seeked"));
|
|
583
613
|
continue;
|
|
584
614
|
}
|
|
585
|
-
queueIndex =
|
|
615
|
+
queueIndex = this.scheduleTimelineEvents(now, queueIndex);
|
|
586
616
|
const waitTime = now + this.noteCheckInterval;
|
|
587
617
|
await this.scheduleTask(() => { }, waitTime);
|
|
588
618
|
}
|
|
589
|
-
if (
|
|
619
|
+
if (exitReason !== "paused") {
|
|
590
620
|
this.notePromises = [];
|
|
591
621
|
this.resetAllStates();
|
|
592
622
|
}
|
|
593
623
|
this.isPlaying = false;
|
|
624
|
+
if (exitReason === "paused") {
|
|
625
|
+
this.isPaused = true;
|
|
626
|
+
this.dispatchEvent(new Event("paused"));
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
this.isPaused = false;
|
|
630
|
+
this.dispatchEvent(new Event(exitReason));
|
|
631
|
+
}
|
|
594
632
|
}
|
|
595
633
|
ticksToSecond(ticks, secondsPerBeat) {
|
|
596
634
|
return ticks * secondsPerBeat / this.ticksPerBeat;
|
|
@@ -697,24 +735,20 @@ export class MidyGMLite {
|
|
|
697
735
|
return;
|
|
698
736
|
this.isStopping = true;
|
|
699
737
|
await this.playPromise;
|
|
700
|
-
this.isStopping = false;
|
|
701
738
|
}
|
|
702
739
|
async pause() {
|
|
703
740
|
if (!this.isPlaying || this.isPaused)
|
|
704
741
|
return;
|
|
705
742
|
const now = this.audioContext.currentTime;
|
|
706
|
-
this.resumeTime = now
|
|
743
|
+
this.resumeTime = now + this.resumeTime - this.startTime;
|
|
707
744
|
this.isPausing = true;
|
|
708
745
|
await this.playPromise;
|
|
709
|
-
this.isPausing = false;
|
|
710
|
-
this.isPaused = true;
|
|
711
746
|
}
|
|
712
747
|
async resume() {
|
|
713
748
|
if (!this.isPaused)
|
|
714
749
|
return;
|
|
715
750
|
this.playPromise = this.playNotes();
|
|
716
751
|
await this.playPromise;
|
|
717
|
-
this.isPaused = false;
|
|
718
752
|
}
|
|
719
753
|
seekTo(second) {
|
|
720
754
|
this.resumeTime = second;
|
|
@@ -737,19 +771,23 @@ export class MidyGMLite {
|
|
|
737
771
|
const now = this.audioContext.currentTime;
|
|
738
772
|
return now + this.resumeTime - this.startTime;
|
|
739
773
|
}
|
|
740
|
-
processScheduledNotes(channel, callback) {
|
|
774
|
+
async processScheduledNotes(channel, callback) {
|
|
741
775
|
const scheduledNotes = channel.scheduledNotes;
|
|
776
|
+
const tasks = [];
|
|
742
777
|
for (let i = channel.scheduleIndex; i < scheduledNotes.length; i++) {
|
|
743
778
|
const note = scheduledNotes[i];
|
|
744
779
|
if (!note)
|
|
745
780
|
continue;
|
|
746
781
|
if (note.ending)
|
|
747
782
|
continue;
|
|
748
|
-
callback(note);
|
|
783
|
+
const task = note.ready.then(() => callback(note));
|
|
784
|
+
tasks.push(task);
|
|
749
785
|
}
|
|
786
|
+
await Promise.all(tasks);
|
|
750
787
|
}
|
|
751
|
-
processActiveNotes(channel, scheduleTime, callback) {
|
|
788
|
+
async processActiveNotes(channel, scheduleTime, callback) {
|
|
752
789
|
const scheduledNotes = channel.scheduledNotes;
|
|
790
|
+
const tasks = [];
|
|
753
791
|
for (let i = channel.scheduleIndex; i < scheduledNotes.length; i++) {
|
|
754
792
|
const note = scheduledNotes[i];
|
|
755
793
|
if (!note)
|
|
@@ -758,8 +796,10 @@ export class MidyGMLite {
|
|
|
758
796
|
continue;
|
|
759
797
|
if (scheduleTime < note.startTime)
|
|
760
798
|
break;
|
|
761
|
-
callback(note);
|
|
799
|
+
const task = note.ready.then(() => callback(note));
|
|
800
|
+
tasks.push(task);
|
|
762
801
|
}
|
|
802
|
+
await Promise.all(tasks);
|
|
763
803
|
}
|
|
764
804
|
cbToRatio(cb) {
|
|
765
805
|
return Math.pow(10, cb / 200);
|
|
@@ -918,12 +958,18 @@ export class MidyGMLite {
|
|
|
918
958
|
this.setFilterEnvelope(note, now);
|
|
919
959
|
this.setPitchEnvelope(note, now);
|
|
920
960
|
this.updateDetune(channel, note, now);
|
|
921
|
-
if (0 < state.
|
|
961
|
+
if (0 < state.modulationDepthMSB) {
|
|
922
962
|
this.startModulation(channel, note, now);
|
|
923
963
|
}
|
|
924
964
|
note.bufferSource.connect(note.filterNode);
|
|
925
965
|
note.filterNode.connect(note.volumeEnvelopeNode);
|
|
926
|
-
|
|
966
|
+
if (voiceParams.sample.type === "compressed") {
|
|
967
|
+
const offset = voiceParams.start / audioBuffer.sampleRate;
|
|
968
|
+
note.bufferSource.start(startTime, offset);
|
|
969
|
+
}
|
|
970
|
+
else {
|
|
971
|
+
note.bufferSource.start(startTime);
|
|
972
|
+
}
|
|
927
973
|
return note;
|
|
928
974
|
}
|
|
929
975
|
handleExclusiveClass(note, channelNumber, startTime) {
|
|
@@ -989,11 +1035,7 @@ export class MidyGMLite {
|
|
|
989
1035
|
return;
|
|
990
1036
|
await this.setNoteAudioNode(channel, note, realtime);
|
|
991
1037
|
this.setNoteRouting(channelNumber, note, startTime);
|
|
992
|
-
note.
|
|
993
|
-
const off = note.offEvent;
|
|
994
|
-
if (off) {
|
|
995
|
-
this.noteOff(channelNumber, noteNumber, off.velocity, off.startTime);
|
|
996
|
-
}
|
|
1038
|
+
note.resolveReady();
|
|
997
1039
|
}
|
|
998
1040
|
disconnectNote(note) {
|
|
999
1041
|
note.bufferSource.disconnect();
|
|
@@ -1027,7 +1069,7 @@ export class MidyGMLite {
|
|
|
1027
1069
|
}, stopTime);
|
|
1028
1070
|
});
|
|
1029
1071
|
}
|
|
1030
|
-
noteOff(channelNumber, noteNumber,
|
|
1072
|
+
async noteOff(channelNumber, noteNumber, _velocity, endTime, force) {
|
|
1031
1073
|
const channel = this.channels[channelNumber];
|
|
1032
1074
|
if (!force) {
|
|
1033
1075
|
if (channel.isDrum)
|
|
@@ -1039,13 +1081,13 @@ export class MidyGMLite {
|
|
|
1039
1081
|
if (index < 0)
|
|
1040
1082
|
return;
|
|
1041
1083
|
const note = channel.scheduledNotes[index];
|
|
1042
|
-
if (note.pending) {
|
|
1043
|
-
note.offEvent = { velocity, startTime: endTime };
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
1084
|
note.ending = true;
|
|
1047
1085
|
this.setNoteIndex(channel, index);
|
|
1048
|
-
|
|
1086
|
+
const promise = note.ready.then(() => {
|
|
1087
|
+
return this.releaseNote(channel, note, endTime);
|
|
1088
|
+
});
|
|
1089
|
+
this.notePromises.push(promise);
|
|
1090
|
+
return promise;
|
|
1049
1091
|
}
|
|
1050
1092
|
setNoteIndex(channel, index) {
|
|
1051
1093
|
let allEnds = true;
|
|
@@ -1131,7 +1173,8 @@ export class MidyGMLite {
|
|
|
1131
1173
|
}
|
|
1132
1174
|
setPitchBend(channelNumber, value, scheduleTime) {
|
|
1133
1175
|
const channel = this.channels[channelNumber];
|
|
1134
|
-
|
|
1176
|
+
if (!(0 <= scheduleTime))
|
|
1177
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1135
1178
|
const state = channel.state;
|
|
1136
1179
|
const prev = state.pitchWheel * 2 - 1;
|
|
1137
1180
|
const next = (value - 8192) / 8192;
|
|
@@ -1143,11 +1186,12 @@ export class MidyGMLite {
|
|
|
1143
1186
|
setModLfoToPitch(channel, note, scheduleTime) {
|
|
1144
1187
|
if (note.modulationDepth) {
|
|
1145
1188
|
const modLfoToPitch = note.voiceParams.modLfoToPitch;
|
|
1146
|
-
const baseDepth = Math.abs(modLfoToPitch) +
|
|
1147
|
-
|
|
1189
|
+
const baseDepth = Math.abs(modLfoToPitch) +
|
|
1190
|
+
channel.state.modulationDepthMSB;
|
|
1191
|
+
const depth = baseDepth * Math.sign(modLfoToPitch);
|
|
1148
1192
|
note.modulationDepth.gain
|
|
1149
1193
|
.cancelScheduledValues(scheduleTime)
|
|
1150
|
-
.setValueAtTime(
|
|
1194
|
+
.setValueAtTime(depth, scheduleTime);
|
|
1151
1195
|
}
|
|
1152
1196
|
else {
|
|
1153
1197
|
this.startModulation(channel, note, scheduleTime);
|
|
@@ -1184,18 +1228,18 @@ export class MidyGMLite {
|
|
|
1184
1228
|
createVoiceParamsHandlers() {
|
|
1185
1229
|
return {
|
|
1186
1230
|
modLfoToPitch: (channel, note, scheduleTime) => {
|
|
1187
|
-
if (0 < channel.state.
|
|
1231
|
+
if (0 < channel.state.modulationDepthMSB) {
|
|
1188
1232
|
this.setModLfoToPitch(channel, note, scheduleTime);
|
|
1189
1233
|
}
|
|
1190
1234
|
},
|
|
1191
1235
|
vibLfoToPitch: (_channel, _note, _scheduleTime) => { },
|
|
1192
1236
|
modLfoToFilterFc: (channel, note, scheduleTime) => {
|
|
1193
|
-
if (0 < channel.state.
|
|
1237
|
+
if (0 < channel.state.modulationDepthMSB) {
|
|
1194
1238
|
this.setModLfoToFilterFc(note, scheduleTime);
|
|
1195
1239
|
}
|
|
1196
1240
|
},
|
|
1197
1241
|
modLfoToVolume: (channel, note, scheduleTime) => {
|
|
1198
|
-
if (0 < channel.state.
|
|
1242
|
+
if (0 < channel.state.modulationDepthMSB) {
|
|
1199
1243
|
this.setModLfoToVolume(note, scheduleTime);
|
|
1200
1244
|
}
|
|
1201
1245
|
},
|
|
@@ -1294,12 +1338,14 @@ export class MidyGMLite {
|
|
|
1294
1338
|
}
|
|
1295
1339
|
setModulationDepth(channelNumber, modulation, scheduleTime) {
|
|
1296
1340
|
const channel = this.channels[channelNumber];
|
|
1297
|
-
|
|
1341
|
+
if (!(0 <= scheduleTime))
|
|
1342
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1298
1343
|
channel.state.modulationDepth = modulation / 127;
|
|
1299
1344
|
this.updateModulation(channel, scheduleTime);
|
|
1300
1345
|
}
|
|
1301
1346
|
setVolume(channelNumber, volume, scheduleTime) {
|
|
1302
|
-
|
|
1347
|
+
if (!(0 <= scheduleTime))
|
|
1348
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1303
1349
|
const channel = this.channels[channelNumber];
|
|
1304
1350
|
channel.state.volume = volume / 127;
|
|
1305
1351
|
this.updateChannelVolume(channel, scheduleTime);
|
|
@@ -1312,13 +1358,15 @@ export class MidyGMLite {
|
|
|
1312
1358
|
};
|
|
1313
1359
|
}
|
|
1314
1360
|
setPan(channelNumber, pan, scheduleTime) {
|
|
1315
|
-
|
|
1361
|
+
if (!(0 <= scheduleTime))
|
|
1362
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1316
1363
|
const channel = this.channels[channelNumber];
|
|
1317
1364
|
channel.state.pan = pan / 127;
|
|
1318
1365
|
this.updateChannelVolume(channel, scheduleTime);
|
|
1319
1366
|
}
|
|
1320
1367
|
setExpression(channelNumber, expression, scheduleTime) {
|
|
1321
|
-
|
|
1368
|
+
if (!(0 <= scheduleTime))
|
|
1369
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1322
1370
|
const channel = this.channels[channelNumber];
|
|
1323
1371
|
channel.state.expression = expression / 127;
|
|
1324
1372
|
this.updateChannelVolume(channel, scheduleTime);
|
|
@@ -1340,7 +1388,8 @@ export class MidyGMLite {
|
|
|
1340
1388
|
}
|
|
1341
1389
|
setSustainPedal(channelNumber, value, scheduleTime) {
|
|
1342
1390
|
const channel = this.channels[channelNumber];
|
|
1343
|
-
|
|
1391
|
+
if (!(0 <= scheduleTime))
|
|
1392
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1344
1393
|
channel.state.sustainPedal = value / 127;
|
|
1345
1394
|
if (64 <= value) {
|
|
1346
1395
|
this.processScheduledNotes(channel, (note) => {
|
|
@@ -1398,7 +1447,8 @@ export class MidyGMLite {
|
|
|
1398
1447
|
}
|
|
1399
1448
|
setPitchBendRange(channelNumber, value, scheduleTime) {
|
|
1400
1449
|
const channel = this.channels[channelNumber];
|
|
1401
|
-
|
|
1450
|
+
if (!(0 <= scheduleTime))
|
|
1451
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1402
1452
|
const state = channel.state;
|
|
1403
1453
|
const prev = state.pitchWheelSensitivity;
|
|
1404
1454
|
const next = value / 12800;
|
|
@@ -1408,7 +1458,8 @@ export class MidyGMLite {
|
|
|
1408
1458
|
this.applyVoiceParams(channel, 16, scheduleTime);
|
|
1409
1459
|
}
|
|
1410
1460
|
allSoundOff(channelNumber, _value, scheduleTime) {
|
|
1411
|
-
|
|
1461
|
+
if (!(0 <= scheduleTime))
|
|
1462
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1412
1463
|
return this.stopActiveNotes(channelNumber, 0, true, scheduleTime);
|
|
1413
1464
|
}
|
|
1414
1465
|
resetChannelStates(channelNumber) {
|
|
@@ -1433,8 +1484,8 @@ export class MidyGMLite {
|
|
|
1433
1484
|
resetAllControllers(channelNumber, _value, scheduleTime) {
|
|
1434
1485
|
const keys = [
|
|
1435
1486
|
"pitchWheel",
|
|
1436
|
-
"
|
|
1437
|
-
"
|
|
1487
|
+
"expressionMSB",
|
|
1488
|
+
"modulationDepthMSB",
|
|
1438
1489
|
"sustainPedal",
|
|
1439
1490
|
];
|
|
1440
1491
|
const channel = this.channels[channelNumber];
|
|
@@ -1460,7 +1511,8 @@ export class MidyGMLite {
|
|
|
1460
1511
|
}
|
|
1461
1512
|
}
|
|
1462
1513
|
allNotesOff(channelNumber, _value, scheduleTime) {
|
|
1463
|
-
|
|
1514
|
+
if (!(0 <= scheduleTime))
|
|
1515
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1464
1516
|
return this.stopActiveNotes(channelNumber, 0, false, scheduleTime);
|
|
1465
1517
|
}
|
|
1466
1518
|
handleUniversalNonRealTimeExclusiveMessage(data, scheduleTime) {
|
|
@@ -1481,7 +1533,8 @@ export class MidyGMLite {
|
|
|
1481
1533
|
}
|
|
1482
1534
|
}
|
|
1483
1535
|
GM1SystemOn(scheduleTime) {
|
|
1484
|
-
|
|
1536
|
+
if (!(0 <= scheduleTime))
|
|
1537
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1485
1538
|
this.mode = "GM1";
|
|
1486
1539
|
for (let i = 0; i < this.channels.length; i++) {
|
|
1487
1540
|
this.allSoundOff(i, 0, scheduleTime);
|
|
@@ -1509,7 +1562,8 @@ export class MidyGMLite {
|
|
|
1509
1562
|
this.setMasterVolume(volume, scheduleTime);
|
|
1510
1563
|
}
|
|
1511
1564
|
setMasterVolume(value, scheduleTime) {
|
|
1512
|
-
|
|
1565
|
+
if (!(0 <= scheduleTime))
|
|
1566
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1513
1567
|
this.masterVolume.gain
|
|
1514
1568
|
.cancelScheduledValues(scheduleTime)
|
|
1515
1569
|
.setValueAtTime(value * value, scheduleTime);
|
package/esm/midy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export class Midy {
|
|
1
|
+
export class Midy extends EventTarget {
|
|
2
2
|
static channelSettings: {
|
|
3
3
|
scheduleIndex: number;
|
|
4
4
|
detune: number;
|
|
@@ -13,6 +13,7 @@ export class Midy {
|
|
|
13
13
|
modulationDepthRange: number;
|
|
14
14
|
fineTuning: number;
|
|
15
15
|
coarseTuning: number;
|
|
16
|
+
portamentoControl: boolean;
|
|
16
17
|
};
|
|
17
18
|
constructor(audioContext: any);
|
|
18
19
|
mode: string;
|
|
@@ -50,6 +51,8 @@ export class Midy {
|
|
|
50
51
|
isPaused: boolean;
|
|
51
52
|
isStopping: boolean;
|
|
52
53
|
isSeeking: boolean;
|
|
54
|
+
loop: boolean;
|
|
55
|
+
loopStart: number;
|
|
53
56
|
playPromise: any;
|
|
54
57
|
timeline: any[];
|
|
55
58
|
notePromises: any[];
|
|
@@ -105,7 +108,7 @@ export class Midy {
|
|
|
105
108
|
createAudioBuffer(voiceParams: any): Promise<any>;
|
|
106
109
|
isLoopDrum(channel: any, noteNumber: any): boolean;
|
|
107
110
|
createBufferSource(channel: any, noteNumber: any, voiceParams: any, audioBuffer: any): any;
|
|
108
|
-
scheduleTimelineEvents(scheduleTime: any, queueIndex: any):
|
|
111
|
+
scheduleTimelineEvents(scheduleTime: any, queueIndex: any): any;
|
|
109
112
|
getQueueIndex(second: any): number;
|
|
110
113
|
resetAllStates(): void;
|
|
111
114
|
updateStates(queueIndex: any, nextQueueIndex: any): void;
|
|
@@ -127,8 +130,8 @@ export class Midy {
|
|
|
127
130
|
seekTo(second: any): void;
|
|
128
131
|
calcTotalTime(): number;
|
|
129
132
|
currentTime(): number;
|
|
130
|
-
processScheduledNotes(channel: any, callback: any): void
|
|
131
|
-
processActiveNotes(channel: any, scheduleTime: any, callback: any): void
|
|
133
|
+
processScheduledNotes(channel: any, callback: any): Promise<void>;
|
|
134
|
+
processActiveNotes(channel: any, scheduleTime: any, callback: any): Promise<void>;
|
|
132
135
|
createConvolutionReverbImpulse(audioContext: any, decay: any, preDecay: any): any;
|
|
133
136
|
createConvolutionReverb(audioContext: any, impulse: any): {
|
|
134
137
|
input: any;
|
|
@@ -182,11 +185,11 @@ export class Midy {
|
|
|
182
185
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
183
186
|
disconnectNote(note: any): void;
|
|
184
187
|
releaseNote(channel: any, note: any, endTime: any): Promise<any>;
|
|
185
|
-
noteOff(channelNumber: any, noteNumber: any,
|
|
188
|
+
noteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): any;
|
|
186
189
|
setNoteIndex(channel: any, index: any): void;
|
|
187
190
|
findNoteOffIndex(channel: any, noteNumber: any): any;
|
|
188
|
-
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any):
|
|
189
|
-
releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any):
|
|
191
|
+
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): any[];
|
|
192
|
+
releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): any[];
|
|
190
193
|
createMessageHandlers(): any[];
|
|
191
194
|
handleMessage(data: any, scheduleTime: any): void;
|
|
192
195
|
activeSensing(): void;
|
|
@@ -223,16 +226,16 @@ export class Midy {
|
|
|
223
226
|
setControlChange(channelNumber: any, controllerType: any, value: any, scheduleTime: any): void;
|
|
224
227
|
setBankMSB(channelNumber: any, msb: any): void;
|
|
225
228
|
updateModulation(channel: any, scheduleTime: any): void;
|
|
226
|
-
setModulationDepth(channelNumber: any,
|
|
229
|
+
setModulationDepth(channelNumber: any, value: any, scheduleTime: any): void;
|
|
227
230
|
updatePortamento(channel: any, scheduleTime: any): void;
|
|
228
|
-
setPortamentoTime(channelNumber: any,
|
|
229
|
-
setVolume(channelNumber: any,
|
|
231
|
+
setPortamentoTime(channelNumber: any, value: any, scheduleTime: any): void;
|
|
232
|
+
setVolume(channelNumber: any, value: any, scheduleTime: any): void;
|
|
230
233
|
panToGain(pan: any): {
|
|
231
234
|
gainLeft: number;
|
|
232
235
|
gainRight: number;
|
|
233
236
|
};
|
|
234
|
-
setPan(channelNumber: any,
|
|
235
|
-
setExpression(channelNumber: any,
|
|
237
|
+
setPan(channelNumber: any, value: any, scheduleTime: any): void;
|
|
238
|
+
setExpression(channelNumber: any, value: any, scheduleTime: any): void;
|
|
236
239
|
setBankLSB(channelNumber: any, lsb: any): void;
|
|
237
240
|
dataEntryLSB(channelNumber: any, value: any, scheduleTime: any): void;
|
|
238
241
|
updateChannelVolume(channel: any, scheduleTime: any): void;
|
|
@@ -252,6 +255,7 @@ export class Midy {
|
|
|
252
255
|
setVibratoRate(channelNumber: any, vibratoRate: any, scheduleTime: any): void;
|
|
253
256
|
setVibratoDepth(channelNumber: any, vibratoDepth: any, scheduleTime: any): void;
|
|
254
257
|
setVibratoDelay(channelNumber: any, vibratoDelay: any, scheduleTime: any): void;
|
|
258
|
+
setPortamentoNoteNumber(channelNumber: any, value: any, scheduleTime: any): void;
|
|
255
259
|
setReverbSendLevel(channelNumber: any, reverbSendLevel: any, scheduleTime: any): void;
|
|
256
260
|
setChorusSendLevel(channelNumber: any, chorusSendLevel: any, scheduleTime: any): void;
|
|
257
261
|
limitData(channel: any, minMSB: any, maxMSB: any, minLSB: any, maxLSB: any): void;
|
|
@@ -270,6 +274,7 @@ export class Midy {
|
|
|
270
274
|
setCoarseTuning(channelNumber: any, value: any, scheduleTime: any): void;
|
|
271
275
|
handleModulationDepthRangeRPN(channelNumber: any, scheduleTime: any): void;
|
|
272
276
|
setModulationDepthRange(channelNumber: any, value: any, scheduleTime: any): void;
|
|
277
|
+
setRPGMakerLoop(_channelNumber: any, _value: any, scheduleTime: any): void;
|
|
273
278
|
allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
274
279
|
resetChannelStates(channelNumber: any): void;
|
|
275
280
|
resetAllControllers(channelNumber: any, _value: 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":"
|
|
1
|
+
{"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}
|