@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/script/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;
|
|
@@ -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/script/midy-GMLite.js
CHANGED
|
@@ -29,12 +29,6 @@ class Note {
|
|
|
29
29
|
writable: true,
|
|
30
30
|
value: false
|
|
31
31
|
});
|
|
32
|
-
Object.defineProperty(this, "pending", {
|
|
33
|
-
enumerable: true,
|
|
34
|
-
configurable: true,
|
|
35
|
-
writable: true,
|
|
36
|
-
value: true
|
|
37
|
-
});
|
|
38
32
|
Object.defineProperty(this, "bufferSource", {
|
|
39
33
|
enumerable: true,
|
|
40
34
|
configurable: true,
|
|
@@ -80,6 +74,9 @@ class Note {
|
|
|
80
74
|
this.noteNumber = noteNumber;
|
|
81
75
|
this.velocity = velocity;
|
|
82
76
|
this.startTime = startTime;
|
|
77
|
+
this.ready = new Promise((resolve) => {
|
|
78
|
+
this.resolveReady = resolve;
|
|
79
|
+
});
|
|
83
80
|
}
|
|
84
81
|
}
|
|
85
82
|
const drumExclusiveClasses = new Uint8Array(128);
|
|
@@ -102,11 +99,11 @@ const defaultControllerState = {
|
|
|
102
99
|
pitchWheel: { type: 14, defaultValue: 8192 / 16383 },
|
|
103
100
|
pitchWheelSensitivity: { type: 16, defaultValue: 2 / 128 },
|
|
104
101
|
link: { type: 127, defaultValue: 0 },
|
|
105
|
-
|
|
102
|
+
modulationDepthMSB: { type: 128 + 1, defaultValue: 0 },
|
|
106
103
|
// dataMSB: { type: 128 + 6, defaultValue: 0, },
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
volumeMSB: { type: 128 + 7, defaultValue: 100 / 127 },
|
|
105
|
+
panMSB: { type: 128 + 10, defaultValue: 64 / 127 },
|
|
106
|
+
expressionMSB: { type: 128 + 11, defaultValue: 1 },
|
|
110
107
|
// dataLSB: { type: 128 + 38, defaultValue: 0, },
|
|
111
108
|
sustainPedal: { type: 128 + 64, defaultValue: 0 },
|
|
112
109
|
// rpnLSB: { type: 128 + 100, defaultValue: 127 },
|
|
@@ -166,8 +163,9 @@ const pitchEnvelopeKeys = [
|
|
|
166
163
|
"playbackRate",
|
|
167
164
|
];
|
|
168
165
|
const pitchEnvelopeKeySet = new Set(pitchEnvelopeKeys);
|
|
169
|
-
class MidyGMLite {
|
|
166
|
+
class MidyGMLite extends EventTarget {
|
|
170
167
|
constructor(audioContext) {
|
|
168
|
+
super();
|
|
171
169
|
Object.defineProperty(this, "mode", {
|
|
172
170
|
enumerable: true,
|
|
173
171
|
configurable: true,
|
|
@@ -282,6 +280,12 @@ class MidyGMLite {
|
|
|
282
280
|
writable: true,
|
|
283
281
|
value: false
|
|
284
282
|
});
|
|
283
|
+
Object.defineProperty(this, "loop", {
|
|
284
|
+
enumerable: true,
|
|
285
|
+
configurable: true,
|
|
286
|
+
writable: true,
|
|
287
|
+
value: false
|
|
288
|
+
});
|
|
285
289
|
Object.defineProperty(this, "playPromise", {
|
|
286
290
|
enumerable: true,
|
|
287
291
|
configurable: true,
|
|
@@ -432,7 +436,7 @@ class MidyGMLite {
|
|
|
432
436
|
return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
|
|
433
437
|
}
|
|
434
438
|
createChannelAudioNodes(audioContext) {
|
|
435
|
-
const { gainLeft, gainRight } = this.panToGain(defaultControllerState.
|
|
439
|
+
const { gainLeft, gainRight } = this.panToGain(defaultControllerState.panMSB.defaultValue);
|
|
436
440
|
const gainL = new GainNode(audioContext, { gain: gainLeft });
|
|
437
441
|
const gainR = new GainNode(audioContext, { gain: gainRight });
|
|
438
442
|
const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
|
|
@@ -460,10 +464,9 @@ class MidyGMLite {
|
|
|
460
464
|
return channels;
|
|
461
465
|
}
|
|
462
466
|
async createAudioBuffer(voiceParams) {
|
|
463
|
-
const sample = voiceParams
|
|
464
|
-
const
|
|
465
|
-
const
|
|
466
|
-
const audioBuffer = await sample.toAudioBuffer(this.audioContext, sampleStart, sampleEnd);
|
|
467
|
+
const { sample, start, end } = voiceParams;
|
|
468
|
+
const sampleEnd = sample.data.length + end;
|
|
469
|
+
const audioBuffer = await sample.toAudioBuffer(this.audioContext, start, sampleEnd);
|
|
467
470
|
return audioBuffer;
|
|
468
471
|
}
|
|
469
472
|
createBufferSource(channel, voiceParams, audioBuffer) {
|
|
@@ -478,7 +481,7 @@ class MidyGMLite {
|
|
|
478
481
|
}
|
|
479
482
|
return bufferSource;
|
|
480
483
|
}
|
|
481
|
-
|
|
484
|
+
scheduleTimelineEvents(scheduleTime, queueIndex) {
|
|
482
485
|
const timeOffset = this.resumeTime - this.startTime;
|
|
483
486
|
const lookAheadCheckTime = scheduleTime + timeOffset + this.lookAhead;
|
|
484
487
|
const schedulingOffset = this.startDelay - timeOffset;
|
|
@@ -490,12 +493,10 @@ class MidyGMLite {
|
|
|
490
493
|
const startTime = event.startTime + schedulingOffset;
|
|
491
494
|
switch (event.type) {
|
|
492
495
|
case "noteOn":
|
|
493
|
-
|
|
496
|
+
this.noteOn(event.channel, event.noteNumber, event.velocity, startTime);
|
|
494
497
|
break;
|
|
495
498
|
case "noteOff": {
|
|
496
|
-
|
|
497
|
-
if (notePromise)
|
|
498
|
-
this.notePromises.push(notePromise);
|
|
499
|
+
this.noteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
|
|
499
500
|
break;
|
|
500
501
|
}
|
|
501
502
|
case "controller":
|
|
@@ -533,22 +534,23 @@ class MidyGMLite {
|
|
|
533
534
|
}
|
|
534
535
|
}
|
|
535
536
|
updateStates(queueIndex, nextQueueIndex) {
|
|
537
|
+
const now = this.audioContext.currentTime;
|
|
536
538
|
if (nextQueueIndex < queueIndex)
|
|
537
539
|
queueIndex = 0;
|
|
538
540
|
for (let i = queueIndex; i < nextQueueIndex; i++) {
|
|
539
541
|
const event = this.timeline[i];
|
|
540
542
|
switch (event.type) {
|
|
541
543
|
case "controller":
|
|
542
|
-
this.setControlChange(event.channel, event.controllerType, event.value,
|
|
544
|
+
this.setControlChange(event.channel, event.controllerType, event.value, now - this.resumeTime + event.startTime);
|
|
543
545
|
break;
|
|
544
546
|
case "programChange":
|
|
545
|
-
this.setProgramChange(event.channel, event.programNumber,
|
|
547
|
+
this.setProgramChange(event.channel, event.programNumber, now - this.resumeTime + event.startTime);
|
|
546
548
|
break;
|
|
547
549
|
case "pitchBend":
|
|
548
|
-
this.setPitchBend(event.channel, event.value + 8192,
|
|
550
|
+
this.setPitchBend(event.channel, event.value + 8192, now - this.resumeTime + event.startTime);
|
|
549
551
|
break;
|
|
550
552
|
case "sysEx":
|
|
551
|
-
this.handleSysEx(event.data,
|
|
553
|
+
this.handleSysEx(event.data, now - this.resumeTime + event.startTime);
|
|
552
554
|
}
|
|
553
555
|
}
|
|
554
556
|
}
|
|
@@ -556,44 +558,80 @@ class MidyGMLite {
|
|
|
556
558
|
if (this.audioContext.state === "suspended") {
|
|
557
559
|
await this.audioContext.resume();
|
|
558
560
|
}
|
|
561
|
+
const paused = this.isPaused;
|
|
559
562
|
this.isPlaying = true;
|
|
560
563
|
this.isPaused = false;
|
|
561
564
|
this.startTime = this.audioContext.currentTime;
|
|
565
|
+
if (paused) {
|
|
566
|
+
this.dispatchEvent(new Event("resumed"));
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
this.dispatchEvent(new Event("started"));
|
|
570
|
+
}
|
|
562
571
|
let queueIndex = this.getQueueIndex(this.resumeTime);
|
|
563
|
-
let
|
|
572
|
+
let exitReason;
|
|
564
573
|
this.notePromises = [];
|
|
565
|
-
while (
|
|
574
|
+
while (true) {
|
|
566
575
|
const now = this.audioContext.currentTime;
|
|
576
|
+
if (this.timeline.length <= queueIndex) {
|
|
577
|
+
await this.stopNotes(0, true, now);
|
|
578
|
+
if (this.loop) {
|
|
579
|
+
this.notePromises = [];
|
|
580
|
+
this.resetAllStates();
|
|
581
|
+
this.startTime = this.audioContext.currentTime;
|
|
582
|
+
this.resumeTime = 0;
|
|
583
|
+
queueIndex = 0;
|
|
584
|
+
this.dispatchEvent(new Event("looped"));
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
await this.audioContext.suspend();
|
|
589
|
+
exitReason = "ended";
|
|
590
|
+
break;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
567
593
|
if (this.isPausing) {
|
|
568
594
|
await this.stopNotes(0, true, now);
|
|
569
595
|
await this.audioContext.suspend();
|
|
570
596
|
this.notePromises = [];
|
|
597
|
+
this.isPausing = false;
|
|
598
|
+
exitReason = "paused";
|
|
571
599
|
break;
|
|
572
600
|
}
|
|
573
601
|
else if (this.isStopping) {
|
|
574
602
|
await this.stopNotes(0, true, now);
|
|
575
603
|
await this.audioContext.suspend();
|
|
576
|
-
|
|
604
|
+
this.isStopping = false;
|
|
605
|
+
exitReason = "stopped";
|
|
577
606
|
break;
|
|
578
607
|
}
|
|
579
608
|
else if (this.isSeeking) {
|
|
580
|
-
|
|
609
|
+
this.stopNotes(0, true, now);
|
|
581
610
|
this.startTime = this.audioContext.currentTime;
|
|
582
611
|
const nextQueueIndex = this.getQueueIndex(this.resumeTime);
|
|
583
612
|
this.updateStates(queueIndex, nextQueueIndex);
|
|
584
613
|
queueIndex = nextQueueIndex;
|
|
585
614
|
this.isSeeking = false;
|
|
615
|
+
this.dispatchEvent(new Event("seeked"));
|
|
586
616
|
continue;
|
|
587
617
|
}
|
|
588
|
-
queueIndex =
|
|
618
|
+
queueIndex = this.scheduleTimelineEvents(now, queueIndex);
|
|
589
619
|
const waitTime = now + this.noteCheckInterval;
|
|
590
620
|
await this.scheduleTask(() => { }, waitTime);
|
|
591
621
|
}
|
|
592
|
-
if (
|
|
622
|
+
if (exitReason !== "paused") {
|
|
593
623
|
this.notePromises = [];
|
|
594
624
|
this.resetAllStates();
|
|
595
625
|
}
|
|
596
626
|
this.isPlaying = false;
|
|
627
|
+
if (exitReason === "paused") {
|
|
628
|
+
this.isPaused = true;
|
|
629
|
+
this.dispatchEvent(new Event("paused"));
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
this.isPaused = false;
|
|
633
|
+
this.dispatchEvent(new Event(exitReason));
|
|
634
|
+
}
|
|
597
635
|
}
|
|
598
636
|
ticksToSecond(ticks, secondsPerBeat) {
|
|
599
637
|
return ticks * secondsPerBeat / this.ticksPerBeat;
|
|
@@ -700,24 +738,20 @@ class MidyGMLite {
|
|
|
700
738
|
return;
|
|
701
739
|
this.isStopping = true;
|
|
702
740
|
await this.playPromise;
|
|
703
|
-
this.isStopping = false;
|
|
704
741
|
}
|
|
705
742
|
async pause() {
|
|
706
743
|
if (!this.isPlaying || this.isPaused)
|
|
707
744
|
return;
|
|
708
745
|
const now = this.audioContext.currentTime;
|
|
709
|
-
this.resumeTime = now
|
|
746
|
+
this.resumeTime = now + this.resumeTime - this.startTime;
|
|
710
747
|
this.isPausing = true;
|
|
711
748
|
await this.playPromise;
|
|
712
|
-
this.isPausing = false;
|
|
713
|
-
this.isPaused = true;
|
|
714
749
|
}
|
|
715
750
|
async resume() {
|
|
716
751
|
if (!this.isPaused)
|
|
717
752
|
return;
|
|
718
753
|
this.playPromise = this.playNotes();
|
|
719
754
|
await this.playPromise;
|
|
720
|
-
this.isPaused = false;
|
|
721
755
|
}
|
|
722
756
|
seekTo(second) {
|
|
723
757
|
this.resumeTime = second;
|
|
@@ -740,19 +774,23 @@ class MidyGMLite {
|
|
|
740
774
|
const now = this.audioContext.currentTime;
|
|
741
775
|
return now + this.resumeTime - this.startTime;
|
|
742
776
|
}
|
|
743
|
-
processScheduledNotes(channel, callback) {
|
|
777
|
+
async processScheduledNotes(channel, callback) {
|
|
744
778
|
const scheduledNotes = channel.scheduledNotes;
|
|
779
|
+
const tasks = [];
|
|
745
780
|
for (let i = channel.scheduleIndex; i < scheduledNotes.length; i++) {
|
|
746
781
|
const note = scheduledNotes[i];
|
|
747
782
|
if (!note)
|
|
748
783
|
continue;
|
|
749
784
|
if (note.ending)
|
|
750
785
|
continue;
|
|
751
|
-
callback(note);
|
|
786
|
+
const task = note.ready.then(() => callback(note));
|
|
787
|
+
tasks.push(task);
|
|
752
788
|
}
|
|
789
|
+
await Promise.all(tasks);
|
|
753
790
|
}
|
|
754
|
-
processActiveNotes(channel, scheduleTime, callback) {
|
|
791
|
+
async processActiveNotes(channel, scheduleTime, callback) {
|
|
755
792
|
const scheduledNotes = channel.scheduledNotes;
|
|
793
|
+
const tasks = [];
|
|
756
794
|
for (let i = channel.scheduleIndex; i < scheduledNotes.length; i++) {
|
|
757
795
|
const note = scheduledNotes[i];
|
|
758
796
|
if (!note)
|
|
@@ -761,8 +799,10 @@ class MidyGMLite {
|
|
|
761
799
|
continue;
|
|
762
800
|
if (scheduleTime < note.startTime)
|
|
763
801
|
break;
|
|
764
|
-
callback(note);
|
|
802
|
+
const task = note.ready.then(() => callback(note));
|
|
803
|
+
tasks.push(task);
|
|
765
804
|
}
|
|
805
|
+
await Promise.all(tasks);
|
|
766
806
|
}
|
|
767
807
|
cbToRatio(cb) {
|
|
768
808
|
return Math.pow(10, cb / 200);
|
|
@@ -921,12 +961,18 @@ class MidyGMLite {
|
|
|
921
961
|
this.setFilterEnvelope(note, now);
|
|
922
962
|
this.setPitchEnvelope(note, now);
|
|
923
963
|
this.updateDetune(channel, note, now);
|
|
924
|
-
if (0 < state.
|
|
964
|
+
if (0 < state.modulationDepthMSB) {
|
|
925
965
|
this.startModulation(channel, note, now);
|
|
926
966
|
}
|
|
927
967
|
note.bufferSource.connect(note.filterNode);
|
|
928
968
|
note.filterNode.connect(note.volumeEnvelopeNode);
|
|
929
|
-
|
|
969
|
+
if (voiceParams.sample.type === "compressed") {
|
|
970
|
+
const offset = voiceParams.start / audioBuffer.sampleRate;
|
|
971
|
+
note.bufferSource.start(startTime, offset);
|
|
972
|
+
}
|
|
973
|
+
else {
|
|
974
|
+
note.bufferSource.start(startTime);
|
|
975
|
+
}
|
|
930
976
|
return note;
|
|
931
977
|
}
|
|
932
978
|
handleExclusiveClass(note, channelNumber, startTime) {
|
|
@@ -992,11 +1038,7 @@ class MidyGMLite {
|
|
|
992
1038
|
return;
|
|
993
1039
|
await this.setNoteAudioNode(channel, note, realtime);
|
|
994
1040
|
this.setNoteRouting(channelNumber, note, startTime);
|
|
995
|
-
note.
|
|
996
|
-
const off = note.offEvent;
|
|
997
|
-
if (off) {
|
|
998
|
-
this.noteOff(channelNumber, noteNumber, off.velocity, off.startTime);
|
|
999
|
-
}
|
|
1041
|
+
note.resolveReady();
|
|
1000
1042
|
}
|
|
1001
1043
|
disconnectNote(note) {
|
|
1002
1044
|
note.bufferSource.disconnect();
|
|
@@ -1030,7 +1072,7 @@ class MidyGMLite {
|
|
|
1030
1072
|
}, stopTime);
|
|
1031
1073
|
});
|
|
1032
1074
|
}
|
|
1033
|
-
noteOff(channelNumber, noteNumber,
|
|
1075
|
+
async noteOff(channelNumber, noteNumber, _velocity, endTime, force) {
|
|
1034
1076
|
const channel = this.channels[channelNumber];
|
|
1035
1077
|
if (!force) {
|
|
1036
1078
|
if (channel.isDrum)
|
|
@@ -1042,13 +1084,13 @@ class MidyGMLite {
|
|
|
1042
1084
|
if (index < 0)
|
|
1043
1085
|
return;
|
|
1044
1086
|
const note = channel.scheduledNotes[index];
|
|
1045
|
-
if (note.pending) {
|
|
1046
|
-
note.offEvent = { velocity, startTime: endTime };
|
|
1047
|
-
return;
|
|
1048
|
-
}
|
|
1049
1087
|
note.ending = true;
|
|
1050
1088
|
this.setNoteIndex(channel, index);
|
|
1051
|
-
|
|
1089
|
+
const promise = note.ready.then(() => {
|
|
1090
|
+
return this.releaseNote(channel, note, endTime);
|
|
1091
|
+
});
|
|
1092
|
+
this.notePromises.push(promise);
|
|
1093
|
+
return promise;
|
|
1052
1094
|
}
|
|
1053
1095
|
setNoteIndex(channel, index) {
|
|
1054
1096
|
let allEnds = true;
|
|
@@ -1134,7 +1176,8 @@ class MidyGMLite {
|
|
|
1134
1176
|
}
|
|
1135
1177
|
setPitchBend(channelNumber, value, scheduleTime) {
|
|
1136
1178
|
const channel = this.channels[channelNumber];
|
|
1137
|
-
|
|
1179
|
+
if (!(0 <= scheduleTime))
|
|
1180
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1138
1181
|
const state = channel.state;
|
|
1139
1182
|
const prev = state.pitchWheel * 2 - 1;
|
|
1140
1183
|
const next = (value - 8192) / 8192;
|
|
@@ -1146,11 +1189,12 @@ class MidyGMLite {
|
|
|
1146
1189
|
setModLfoToPitch(channel, note, scheduleTime) {
|
|
1147
1190
|
if (note.modulationDepth) {
|
|
1148
1191
|
const modLfoToPitch = note.voiceParams.modLfoToPitch;
|
|
1149
|
-
const baseDepth = Math.abs(modLfoToPitch) +
|
|
1150
|
-
|
|
1192
|
+
const baseDepth = Math.abs(modLfoToPitch) +
|
|
1193
|
+
channel.state.modulationDepthMSB;
|
|
1194
|
+
const depth = baseDepth * Math.sign(modLfoToPitch);
|
|
1151
1195
|
note.modulationDepth.gain
|
|
1152
1196
|
.cancelScheduledValues(scheduleTime)
|
|
1153
|
-
.setValueAtTime(
|
|
1197
|
+
.setValueAtTime(depth, scheduleTime);
|
|
1154
1198
|
}
|
|
1155
1199
|
else {
|
|
1156
1200
|
this.startModulation(channel, note, scheduleTime);
|
|
@@ -1187,18 +1231,18 @@ class MidyGMLite {
|
|
|
1187
1231
|
createVoiceParamsHandlers() {
|
|
1188
1232
|
return {
|
|
1189
1233
|
modLfoToPitch: (channel, note, scheduleTime) => {
|
|
1190
|
-
if (0 < channel.state.
|
|
1234
|
+
if (0 < channel.state.modulationDepthMSB) {
|
|
1191
1235
|
this.setModLfoToPitch(channel, note, scheduleTime);
|
|
1192
1236
|
}
|
|
1193
1237
|
},
|
|
1194
1238
|
vibLfoToPitch: (_channel, _note, _scheduleTime) => { },
|
|
1195
1239
|
modLfoToFilterFc: (channel, note, scheduleTime) => {
|
|
1196
|
-
if (0 < channel.state.
|
|
1240
|
+
if (0 < channel.state.modulationDepthMSB) {
|
|
1197
1241
|
this.setModLfoToFilterFc(note, scheduleTime);
|
|
1198
1242
|
}
|
|
1199
1243
|
},
|
|
1200
1244
|
modLfoToVolume: (channel, note, scheduleTime) => {
|
|
1201
|
-
if (0 < channel.state.
|
|
1245
|
+
if (0 < channel.state.modulationDepthMSB) {
|
|
1202
1246
|
this.setModLfoToVolume(note, scheduleTime);
|
|
1203
1247
|
}
|
|
1204
1248
|
},
|
|
@@ -1297,12 +1341,14 @@ class MidyGMLite {
|
|
|
1297
1341
|
}
|
|
1298
1342
|
setModulationDepth(channelNumber, modulation, scheduleTime) {
|
|
1299
1343
|
const channel = this.channels[channelNumber];
|
|
1300
|
-
|
|
1344
|
+
if (!(0 <= scheduleTime))
|
|
1345
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1301
1346
|
channel.state.modulationDepth = modulation / 127;
|
|
1302
1347
|
this.updateModulation(channel, scheduleTime);
|
|
1303
1348
|
}
|
|
1304
1349
|
setVolume(channelNumber, volume, scheduleTime) {
|
|
1305
|
-
|
|
1350
|
+
if (!(0 <= scheduleTime))
|
|
1351
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1306
1352
|
const channel = this.channels[channelNumber];
|
|
1307
1353
|
channel.state.volume = volume / 127;
|
|
1308
1354
|
this.updateChannelVolume(channel, scheduleTime);
|
|
@@ -1315,13 +1361,15 @@ class MidyGMLite {
|
|
|
1315
1361
|
};
|
|
1316
1362
|
}
|
|
1317
1363
|
setPan(channelNumber, pan, scheduleTime) {
|
|
1318
|
-
|
|
1364
|
+
if (!(0 <= scheduleTime))
|
|
1365
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1319
1366
|
const channel = this.channels[channelNumber];
|
|
1320
1367
|
channel.state.pan = pan / 127;
|
|
1321
1368
|
this.updateChannelVolume(channel, scheduleTime);
|
|
1322
1369
|
}
|
|
1323
1370
|
setExpression(channelNumber, expression, scheduleTime) {
|
|
1324
|
-
|
|
1371
|
+
if (!(0 <= scheduleTime))
|
|
1372
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1325
1373
|
const channel = this.channels[channelNumber];
|
|
1326
1374
|
channel.state.expression = expression / 127;
|
|
1327
1375
|
this.updateChannelVolume(channel, scheduleTime);
|
|
@@ -1343,7 +1391,8 @@ class MidyGMLite {
|
|
|
1343
1391
|
}
|
|
1344
1392
|
setSustainPedal(channelNumber, value, scheduleTime) {
|
|
1345
1393
|
const channel = this.channels[channelNumber];
|
|
1346
|
-
|
|
1394
|
+
if (!(0 <= scheduleTime))
|
|
1395
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1347
1396
|
channel.state.sustainPedal = value / 127;
|
|
1348
1397
|
if (64 <= value) {
|
|
1349
1398
|
this.processScheduledNotes(channel, (note) => {
|
|
@@ -1401,7 +1450,8 @@ class MidyGMLite {
|
|
|
1401
1450
|
}
|
|
1402
1451
|
setPitchBendRange(channelNumber, value, scheduleTime) {
|
|
1403
1452
|
const channel = this.channels[channelNumber];
|
|
1404
|
-
|
|
1453
|
+
if (!(0 <= scheduleTime))
|
|
1454
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1405
1455
|
const state = channel.state;
|
|
1406
1456
|
const prev = state.pitchWheelSensitivity;
|
|
1407
1457
|
const next = value / 12800;
|
|
@@ -1411,7 +1461,8 @@ class MidyGMLite {
|
|
|
1411
1461
|
this.applyVoiceParams(channel, 16, scheduleTime);
|
|
1412
1462
|
}
|
|
1413
1463
|
allSoundOff(channelNumber, _value, scheduleTime) {
|
|
1414
|
-
|
|
1464
|
+
if (!(0 <= scheduleTime))
|
|
1465
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1415
1466
|
return this.stopActiveNotes(channelNumber, 0, true, scheduleTime);
|
|
1416
1467
|
}
|
|
1417
1468
|
resetChannelStates(channelNumber) {
|
|
@@ -1436,8 +1487,8 @@ class MidyGMLite {
|
|
|
1436
1487
|
resetAllControllers(channelNumber, _value, scheduleTime) {
|
|
1437
1488
|
const keys = [
|
|
1438
1489
|
"pitchWheel",
|
|
1439
|
-
"
|
|
1440
|
-
"
|
|
1490
|
+
"expressionMSB",
|
|
1491
|
+
"modulationDepthMSB",
|
|
1441
1492
|
"sustainPedal",
|
|
1442
1493
|
];
|
|
1443
1494
|
const channel = this.channels[channelNumber];
|
|
@@ -1463,7 +1514,8 @@ class MidyGMLite {
|
|
|
1463
1514
|
}
|
|
1464
1515
|
}
|
|
1465
1516
|
allNotesOff(channelNumber, _value, scheduleTime) {
|
|
1466
|
-
|
|
1517
|
+
if (!(0 <= scheduleTime))
|
|
1518
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1467
1519
|
return this.stopActiveNotes(channelNumber, 0, false, scheduleTime);
|
|
1468
1520
|
}
|
|
1469
1521
|
handleUniversalNonRealTimeExclusiveMessage(data, scheduleTime) {
|
|
@@ -1484,7 +1536,8 @@ class MidyGMLite {
|
|
|
1484
1536
|
}
|
|
1485
1537
|
}
|
|
1486
1538
|
GM1SystemOn(scheduleTime) {
|
|
1487
|
-
|
|
1539
|
+
if (!(0 <= scheduleTime))
|
|
1540
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1488
1541
|
this.mode = "GM1";
|
|
1489
1542
|
for (let i = 0; i < this.channels.length; i++) {
|
|
1490
1543
|
this.allSoundOff(i, 0, scheduleTime);
|
|
@@ -1512,7 +1565,8 @@ class MidyGMLite {
|
|
|
1512
1565
|
this.setMasterVolume(volume, scheduleTime);
|
|
1513
1566
|
}
|
|
1514
1567
|
setMasterVolume(value, scheduleTime) {
|
|
1515
|
-
|
|
1568
|
+
if (!(0 <= scheduleTime))
|
|
1569
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1516
1570
|
this.masterVolume.gain
|
|
1517
1571
|
.cancelScheduledValues(scheduleTime)
|
|
1518
1572
|
.setValueAtTime(value * value, scheduleTime);
|
package/script/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/script/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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"}
|