@marmooo/midy 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts +153 -0
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts.map +1 -0
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.2 → soundfont-parser@0.0.4}/+esm.js +73 -66
- package/esm/midy-GM1.d.ts +19 -13
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +171 -131
- package/esm/midy-GM2.d.ts +22 -14
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +186 -133
- package/esm/midy-GMLite.d.ts +17 -13
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +159 -131
- package/esm/midy.d.ts +30 -16
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +266 -166
- package/package.json +1 -1
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts +153 -0
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts.map +1 -0
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.2 → soundfont-parser@0.0.4}/+esm.js +75 -68
- package/script/midy-GM1.d.ts +19 -13
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +171 -131
- package/script/midy-GM2.d.ts +22 -14
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +186 -133
- package/script/midy-GMLite.d.ts +17 -13
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +159 -131
- package/script/midy.d.ts +30 -16
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +266 -166
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts +0 -135
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts.map +0 -1
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts +0 -135
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts.map +0 -1
package/script/midy-GMLite.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MidyGMLite = void 0;
|
|
4
4
|
const _esm_js_1 = require("./deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.js");
|
|
5
|
-
const _esm_js_2 = require("./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.
|
|
5
|
+
const _esm_js_2 = require("./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.js");
|
|
6
6
|
class Note {
|
|
7
7
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
8
8
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -11,25 +11,31 @@ class Note {
|
|
|
11
11
|
writable: true,
|
|
12
12
|
value: void 0
|
|
13
13
|
});
|
|
14
|
-
Object.defineProperty(this, "
|
|
14
|
+
Object.defineProperty(this, "filterNode", {
|
|
15
15
|
enumerable: true,
|
|
16
16
|
configurable: true,
|
|
17
17
|
writable: true,
|
|
18
18
|
value: void 0
|
|
19
19
|
});
|
|
20
|
-
Object.defineProperty(this, "
|
|
20
|
+
Object.defineProperty(this, "volumeNode", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
writable: true,
|
|
24
|
+
value: void 0
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(this, "volumeDepth", {
|
|
21
27
|
enumerable: true,
|
|
22
28
|
configurable: true,
|
|
23
29
|
writable: true,
|
|
24
30
|
value: void 0
|
|
25
31
|
});
|
|
26
|
-
Object.defineProperty(this, "
|
|
32
|
+
Object.defineProperty(this, "modulationLFO", {
|
|
27
33
|
enumerable: true,
|
|
28
34
|
configurable: true,
|
|
29
35
|
writable: true,
|
|
30
36
|
value: void 0
|
|
31
37
|
});
|
|
32
|
-
Object.defineProperty(this, "
|
|
38
|
+
Object.defineProperty(this, "modulationDepth", {
|
|
33
39
|
enumerable: true,
|
|
34
40
|
configurable: true,
|
|
35
41
|
writable: true,
|
|
@@ -316,7 +322,7 @@ class MidyGMLite {
|
|
|
316
322
|
const t = this.audioContext.currentTime + offset;
|
|
317
323
|
queueIndex = await this.scheduleTimelineEvents(t, offset, queueIndex);
|
|
318
324
|
if (this.isPausing) {
|
|
319
|
-
await this.stopNotes();
|
|
325
|
+
await this.stopNotes(0, true);
|
|
320
326
|
this.notePromises = [];
|
|
321
327
|
resolve();
|
|
322
328
|
this.isPausing = false;
|
|
@@ -324,7 +330,7 @@ class MidyGMLite {
|
|
|
324
330
|
return;
|
|
325
331
|
}
|
|
326
332
|
else if (this.isStopping) {
|
|
327
|
-
await this.stopNotes();
|
|
333
|
+
await this.stopNotes(0, true);
|
|
328
334
|
this.notePromises = [];
|
|
329
335
|
resolve();
|
|
330
336
|
this.isStopping = false;
|
|
@@ -332,7 +338,7 @@ class MidyGMLite {
|
|
|
332
338
|
return;
|
|
333
339
|
}
|
|
334
340
|
else if (this.isSeeking) {
|
|
335
|
-
this.stopNotes();
|
|
341
|
+
this.stopNotes(0, true);
|
|
336
342
|
this.startTime = this.audioContext.currentTime;
|
|
337
343
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
338
344
|
offset = this.resumeTime - this.startTime;
|
|
@@ -413,21 +419,25 @@ class MidyGMLite {
|
|
|
413
419
|
}
|
|
414
420
|
return { instruments, timeline };
|
|
415
421
|
}
|
|
416
|
-
|
|
422
|
+
async stopChannelNotes(channelNumber, velocity, stopPedal) {
|
|
417
423
|
const now = this.audioContext.currentTime;
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
});
|
|
428
|
-
});
|
|
429
|
-
channel.scheduledNotes.clear();
|
|
424
|
+
const channel = this.channels[channelNumber];
|
|
425
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
426
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
427
|
+
const note = noteList[i];
|
|
428
|
+
if (!note)
|
|
429
|
+
continue;
|
|
430
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
|
|
431
|
+
this.notePromises.push(promise);
|
|
432
|
+
}
|
|
430
433
|
});
|
|
434
|
+
channel.scheduledNotes.clear();
|
|
435
|
+
await Promise.all(this.notePromises);
|
|
436
|
+
}
|
|
437
|
+
stopNotes(velocity, stopPedal) {
|
|
438
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
439
|
+
this.stopChannelNotes(i, velocity, stopPedal);
|
|
440
|
+
}
|
|
431
441
|
return Promise.all(this.notePromises);
|
|
432
442
|
}
|
|
433
443
|
async start() {
|
|
@@ -510,75 +520,111 @@ class MidyGMLite {
|
|
|
510
520
|
}
|
|
511
521
|
setVolumeEnvelope(note) {
|
|
512
522
|
const { instrumentKey, startTime } = note;
|
|
513
|
-
note.gainNode = new GainNode(this.audioContext, { gain: 0 });
|
|
514
523
|
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
515
524
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
516
525
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
517
526
|
const volAttack = volDelay + instrumentKey.volAttack;
|
|
518
527
|
const volHold = volAttack + instrumentKey.volHold;
|
|
519
528
|
const volDecay = volHold + instrumentKey.volDecay;
|
|
520
|
-
note.
|
|
529
|
+
note.volumeNode.gain
|
|
530
|
+
.cancelScheduledValues(startTime)
|
|
531
|
+
.setValueAtTime(0, startTime)
|
|
521
532
|
.setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
|
|
522
533
|
.exponentialRampToValueAtTime(attackVolume, volAttack)
|
|
523
534
|
.setValueAtTime(attackVolume, volHold)
|
|
524
535
|
.linearRampToValueAtTime(sustainVolume, volDecay);
|
|
525
536
|
}
|
|
526
|
-
|
|
527
|
-
const { instrumentKey,
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
const
|
|
534
|
-
const
|
|
535
|
-
|
|
537
|
+
setPitch(note, semitoneOffset) {
|
|
538
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
539
|
+
const modEnvToPitch = instrumentKey.modEnvToPitch / 100;
|
|
540
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
541
|
+
if (modEnvToPitch === 0)
|
|
542
|
+
return;
|
|
543
|
+
const basePitch = note.bufferSource.playbackRate.value;
|
|
544
|
+
const peekPitch = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset + modEnvToPitch);
|
|
545
|
+
const modDelay = startTime + instrumentKey.modDelay;
|
|
546
|
+
const modAttack = modDelay + instrumentKey.modAttack;
|
|
547
|
+
const modHold = modAttack + instrumentKey.modHold;
|
|
548
|
+
const modDecay = modHold + instrumentKey.modDecay;
|
|
549
|
+
note.bufferSource.playbackRate.value
|
|
550
|
+
.setValueAtTime(basePitch, modDelay)
|
|
551
|
+
.exponentialRampToValueAtTime(peekPitch, modAttack)
|
|
552
|
+
.setValueAtTime(peekPitch, modHold)
|
|
553
|
+
.linearRampToValueAtTime(basePitch, modDecay);
|
|
554
|
+
}
|
|
555
|
+
clampCutoffFrequency(frequency) {
|
|
556
|
+
const minFrequency = 20; // min Hz of initialFilterFc
|
|
557
|
+
const maxFrequency = 20000; // max Hz of initialFilterFc
|
|
558
|
+
return Math.max(minFrequency, Math.min(frequency, maxFrequency));
|
|
559
|
+
}
|
|
560
|
+
setFilterEnvelope(note) {
|
|
561
|
+
const { instrumentKey, startTime } = note;
|
|
562
|
+
const baseFreq = this.centToHz(instrumentKey.initialFilterFc);
|
|
563
|
+
const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc);
|
|
564
|
+
const sustainFreq = baseFreq +
|
|
565
|
+
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
|
|
566
|
+
const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
|
|
567
|
+
const adjustedPeekFreq = this.clampCutoffFrequency(peekFreq);
|
|
568
|
+
const adjustedSustainFreq = this.clampCutoffFrequency(sustainFreq);
|
|
536
569
|
const modDelay = startTime + instrumentKey.modDelay;
|
|
537
570
|
const modAttack = modDelay + instrumentKey.modAttack;
|
|
538
571
|
const modHold = modAttack + instrumentKey.modHold;
|
|
539
572
|
const modDecay = modHold + instrumentKey.modDecay;
|
|
540
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
541
|
-
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
542
|
-
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
543
|
-
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
544
|
-
type: "lowpass",
|
|
545
|
-
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
546
|
-
frequency: adjustedBaseFreq,
|
|
547
|
-
});
|
|
548
573
|
note.filterNode.frequency
|
|
574
|
+
.cancelScheduledValues(startTime)
|
|
575
|
+
.setValueAtTime(adjustedBaseFreq, startTime)
|
|
549
576
|
.setValueAtTime(adjustedBaseFreq, modDelay)
|
|
550
577
|
.exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
|
|
551
578
|
.setValueAtTime(adjustedPeekFreq, modHold)
|
|
552
579
|
.linearRampToValueAtTime(adjustedSustainFreq, modDecay);
|
|
553
|
-
note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modEnvToPitch, modDelay);
|
|
554
580
|
}
|
|
555
|
-
startModulation(channel, note,
|
|
581
|
+
startModulation(channel, note, startTime) {
|
|
556
582
|
const { instrumentKey } = note;
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
});
|
|
560
|
-
note.modLFO = new OscillatorNode(this.audioContext, {
|
|
583
|
+
const { modLfoToPitch, modLfoToVolume } = instrumentKey;
|
|
584
|
+
note.modulationLFO = new OscillatorNode(this.audioContext, {
|
|
561
585
|
frequency: this.centToHz(instrumentKey.freqModLFO),
|
|
562
586
|
});
|
|
563
|
-
note.
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
587
|
+
note.filterDepth = new GainNode(this.audioContext, {
|
|
588
|
+
gain: instrumentKey.modLfoToFilterFc,
|
|
589
|
+
});
|
|
590
|
+
const modulationDepth = Math.abs(modLfoToPitch) + channel.modulationDepth;
|
|
591
|
+
const modulationDepthSign = (0 < modLfoToPitch) ? 1 : -1;
|
|
592
|
+
note.modulationDepth = new GainNode(this.audioContext, {
|
|
593
|
+
gain: modulationDepth * modulationDepthSign,
|
|
594
|
+
});
|
|
595
|
+
const volumeDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
|
|
596
|
+
const volumeDepthSign = (0 < modLfoToVolume) ? 1 : -1;
|
|
597
|
+
note.volumeDepth = new GainNode(this.audioContext, {
|
|
598
|
+
gain: volumeDepth * volumeDepthSign,
|
|
599
|
+
});
|
|
600
|
+
note.modulationLFO.start(startTime + instrumentKey.delayModLFO);
|
|
601
|
+
note.modulationLFO.connect(note.filterDepth);
|
|
602
|
+
note.filterDepth.connect(note.filterNode.frequency);
|
|
603
|
+
note.modulationLFO.connect(note.modulationDepth);
|
|
604
|
+
note.modulationDepth.connect(note.bufferSource.detune);
|
|
605
|
+
note.modulationLFO.connect(note.volumeDepth);
|
|
606
|
+
note.volumeDepth.connect(note.volumeNode.gain);
|
|
568
607
|
}
|
|
569
608
|
async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
|
|
570
609
|
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
571
610
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
572
611
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
573
|
-
note.
|
|
612
|
+
note.volumeNode = new GainNode(this.audioContext);
|
|
613
|
+
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
614
|
+
type: "lowpass",
|
|
615
|
+
Q: instrumentKey.initialFilterQ / 10 * channel.filterResonance, // dB
|
|
616
|
+
});
|
|
574
617
|
this.setVolumeEnvelope(note);
|
|
575
|
-
this.setFilterEnvelope(
|
|
576
|
-
if (channel.
|
|
577
|
-
|
|
578
|
-
this.startModulation(channel, note,
|
|
618
|
+
this.setFilterEnvelope(note);
|
|
619
|
+
if (0 < channel.modulationDepth) {
|
|
620
|
+
this.setPitch(note, semitoneOffset);
|
|
621
|
+
this.startModulation(channel, note, startTime);
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
579
625
|
}
|
|
580
626
|
note.bufferSource.connect(note.filterNode);
|
|
581
|
-
note.filterNode.connect(note.
|
|
627
|
+
note.filterNode.connect(note.volumeNode);
|
|
582
628
|
note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
|
|
583
629
|
return note;
|
|
584
630
|
}
|
|
@@ -594,8 +640,8 @@ class MidyGMLite {
|
|
|
594
640
|
if (!instrumentKey)
|
|
595
641
|
return;
|
|
596
642
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
597
|
-
note.
|
|
598
|
-
note.
|
|
643
|
+
note.volumeNode.connect(channel.gainL);
|
|
644
|
+
note.volumeNode.connect(channel.gainR);
|
|
599
645
|
const scheduledNotes = channel.scheduledNotes;
|
|
600
646
|
if (scheduledNotes.has(noteNumber)) {
|
|
601
647
|
scheduledNotes.get(noteNumber).push(note);
|
|
@@ -608,7 +654,7 @@ class MidyGMLite {
|
|
|
608
654
|
const now = this.audioContext.currentTime;
|
|
609
655
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
610
656
|
}
|
|
611
|
-
scheduleNoteRelease(channelNumber, noteNumber,
|
|
657
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, stopPedal = false) {
|
|
612
658
|
const channel = this.channels[channelNumber];
|
|
613
659
|
if (stopPedal && channel.sustainPedal)
|
|
614
660
|
return;
|
|
@@ -621,20 +667,14 @@ class MidyGMLite {
|
|
|
621
667
|
continue;
|
|
622
668
|
if (note.ending)
|
|
623
669
|
continue;
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
note.instrumentKey.volRelease * velocityRate;
|
|
627
|
-
note.gainNode.gain
|
|
670
|
+
const volEndTime = stopTime + note.instrumentKey.volRelease;
|
|
671
|
+
note.volumeNode.gain
|
|
628
672
|
.cancelScheduledValues(stopTime)
|
|
629
673
|
.linearRampToValueAtTime(0, volEndTime);
|
|
630
|
-
const
|
|
631
|
-
const baseFreq = this.centToHz(note.instrumentKey.initialFilterFc);
|
|
632
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
633
|
-
const modEndTime = stopTime +
|
|
634
|
-
note.instrumentKey.modRelease * velocityRate;
|
|
674
|
+
const modRelease = stopTime + note.instrumentKey.modRelease;
|
|
635
675
|
note.filterNode.frequency
|
|
636
676
|
.cancelScheduledValues(stopTime)
|
|
637
|
-
.linearRampToValueAtTime(
|
|
677
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
638
678
|
note.ending = true;
|
|
639
679
|
this.scheduleTask(() => {
|
|
640
680
|
note.bufferSource.loop = false;
|
|
@@ -643,15 +683,17 @@ class MidyGMLite {
|
|
|
643
683
|
note.bufferSource.onended = () => {
|
|
644
684
|
scheduledNotes[i] = null;
|
|
645
685
|
note.bufferSource.disconnect();
|
|
686
|
+
note.volumeNode.disconnect();
|
|
646
687
|
note.filterNode.disconnect();
|
|
647
|
-
note.
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
688
|
+
if (note.volumeDepth)
|
|
689
|
+
note.volumeDepth.disconnect();
|
|
690
|
+
if (note.modulationDepth)
|
|
691
|
+
note.modulationDepth.disconnect();
|
|
692
|
+
if (note.modulationLFO)
|
|
693
|
+
note.modulationLFO.stop();
|
|
652
694
|
resolve();
|
|
653
695
|
};
|
|
654
|
-
bufferSource.stop(volEndTime);
|
|
696
|
+
note.bufferSource.stop(volEndTime);
|
|
655
697
|
});
|
|
656
698
|
}
|
|
657
699
|
}
|
|
@@ -664,14 +706,15 @@ class MidyGMLite {
|
|
|
664
706
|
const channel = this.channels[channelNumber];
|
|
665
707
|
const promises = [];
|
|
666
708
|
channel.sustainPedal = false;
|
|
667
|
-
channel.scheduledNotes.forEach((
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
709
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
710
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
711
|
+
const note = noteList[i];
|
|
712
|
+
if (!note)
|
|
713
|
+
continue;
|
|
714
|
+
const { noteNumber } = note;
|
|
715
|
+
const promise = this.releaseNote(channelNumber, noteNumber, velocity);
|
|
716
|
+
promises.push(promise);
|
|
717
|
+
}
|
|
675
718
|
});
|
|
676
719
|
return promises;
|
|
677
720
|
}
|
|
@@ -712,7 +755,7 @@ class MidyGMLite {
|
|
|
712
755
|
handleControlChange(channelNumber, controller, value) {
|
|
713
756
|
switch (controller) {
|
|
714
757
|
case 1:
|
|
715
|
-
return this.
|
|
758
|
+
return this.setModulationDepth(channelNumber, value);
|
|
716
759
|
case 6:
|
|
717
760
|
return this.dataEntryMSB(channelNumber, value);
|
|
718
761
|
case 7:
|
|
@@ -741,20 +784,25 @@ class MidyGMLite {
|
|
|
741
784
|
}
|
|
742
785
|
updateModulation(channel) {
|
|
743
786
|
const now = this.audioContext.currentTime;
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
787
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
788
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
789
|
+
const note = noteList[i];
|
|
790
|
+
if (!note)
|
|
791
|
+
continue;
|
|
792
|
+
if (note.modulationDepth) {
|
|
793
|
+
note.modulationDepth.gain.setValueAtTime(channel.modulationDepth, now);
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
797
|
+
this.setPitch(note, semitoneOffset);
|
|
798
|
+
this.startModulation(channel, note, now);
|
|
799
|
+
}
|
|
752
800
|
}
|
|
753
801
|
});
|
|
754
802
|
}
|
|
755
|
-
|
|
803
|
+
setModulationDepth(channelNumber, modulation) {
|
|
756
804
|
const channel = this.channels[channelNumber];
|
|
757
|
-
channel.
|
|
805
|
+
channel.modulationDepth = (modulation / 127) * channel.modulationDepthRange;
|
|
758
806
|
this.updateModulation(channel);
|
|
759
807
|
}
|
|
760
808
|
setVolume(channelNumber, volume) {
|
|
@@ -824,13 +872,17 @@ class MidyGMLite {
|
|
|
824
872
|
}
|
|
825
873
|
updateDetune(channel, detuneChange) {
|
|
826
874
|
const now = this.audioContext.currentTime;
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
.
|
|
875
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
876
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
877
|
+
const note = noteList[i];
|
|
878
|
+
if (!note)
|
|
879
|
+
continue;
|
|
880
|
+
const { bufferSource } = note;
|
|
881
|
+
const detune = bufferSource.detune.value + detuneChange;
|
|
882
|
+
bufferSource.detune
|
|
883
|
+
.cancelScheduledValues(now)
|
|
884
|
+
.setValueAtTime(detune, now);
|
|
885
|
+
}
|
|
834
886
|
});
|
|
835
887
|
}
|
|
836
888
|
handlePitchBendRangeRPN(channelNumber) {
|
|
@@ -848,37 +900,13 @@ class MidyGMLite {
|
|
|
848
900
|
this.updateDetune(channel, detuneChange);
|
|
849
901
|
}
|
|
850
902
|
allSoundOff(channelNumber) {
|
|
851
|
-
|
|
852
|
-
const channel = this.channels[channelNumber];
|
|
853
|
-
const velocity = 0;
|
|
854
|
-
const stopPedal = true;
|
|
855
|
-
const promises = [];
|
|
856
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
857
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
858
|
-
if (activeNote) {
|
|
859
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
|
|
860
|
-
promises.push(notePromise);
|
|
861
|
-
}
|
|
862
|
-
});
|
|
863
|
-
return promises;
|
|
903
|
+
return this.stopChannelNotes(channelNumber, 0, true);
|
|
864
904
|
}
|
|
865
905
|
resetAllControllers(channelNumber) {
|
|
866
906
|
Object.assign(this.channels[channelNumber], this.effectSettings);
|
|
867
907
|
}
|
|
868
908
|
allNotesOff(channelNumber) {
|
|
869
|
-
|
|
870
|
-
const channel = this.channels[channelNumber];
|
|
871
|
-
const velocity = 0;
|
|
872
|
-
const stopPedal = false;
|
|
873
|
-
const promises = [];
|
|
874
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
875
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
876
|
-
if (activeNote) {
|
|
877
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
|
|
878
|
-
promises.push(notePromise);
|
|
879
|
-
}
|
|
880
|
-
});
|
|
881
|
-
return promises;
|
|
909
|
+
return this.stopChannelNotes(channelNumber, 0, false);
|
|
882
910
|
}
|
|
883
911
|
handleUniversalNonRealTimeExclusiveMessage(data) {
|
|
884
912
|
switch (data[2]) {
|
|
@@ -972,7 +1000,7 @@ Object.defineProperty(MidyGMLite, "channelSettings", {
|
|
|
972
1000
|
dataLSB: 0,
|
|
973
1001
|
program: 0,
|
|
974
1002
|
pitchBend: 0,
|
|
975
|
-
modulationDepthRange:
|
|
1003
|
+
modulationDepthRange: 50, // cent
|
|
976
1004
|
}
|
|
977
1005
|
});
|
|
978
1006
|
Object.defineProperty(MidyGMLite, "effectSettings", {
|
|
@@ -981,7 +1009,7 @@ Object.defineProperty(MidyGMLite, "effectSettings", {
|
|
|
981
1009
|
writable: true,
|
|
982
1010
|
value: {
|
|
983
1011
|
expression: 1,
|
|
984
|
-
|
|
1012
|
+
modulationDepth: 0,
|
|
985
1013
|
sustainPedal: false,
|
|
986
1014
|
rpnMSB: 127,
|
|
987
1015
|
rpnLSB: 127,
|
package/script/midy.d.ts
CHANGED
|
@@ -4,6 +4,11 @@ export class Midy {
|
|
|
4
4
|
volume: number;
|
|
5
5
|
pan: number;
|
|
6
6
|
portamentoTime: number;
|
|
7
|
+
filterResonance: number;
|
|
8
|
+
releaseTime: number;
|
|
9
|
+
attackTime: number;
|
|
10
|
+
brightness: number;
|
|
11
|
+
decayTime: number;
|
|
7
12
|
reverbSendLevel: number;
|
|
8
13
|
chorusSendLevel: number;
|
|
9
14
|
vibratoRate: number;
|
|
@@ -22,7 +27,7 @@ export class Midy {
|
|
|
22
27
|
};
|
|
23
28
|
static effectSettings: {
|
|
24
29
|
expression: number;
|
|
25
|
-
|
|
30
|
+
modulationDepth: number;
|
|
26
31
|
sustainPedal: boolean;
|
|
27
32
|
portamento: boolean;
|
|
28
33
|
sostenutoPedal: boolean;
|
|
@@ -128,7 +133,8 @@ export class Midy {
|
|
|
128
133
|
instruments: Set<any>;
|
|
129
134
|
timeline: any[];
|
|
130
135
|
};
|
|
131
|
-
|
|
136
|
+
stopChannelNotes(channelNumber: any, velocity: any, stopPedal: any): Promise<void>;
|
|
137
|
+
stopNotes(velocity: any, stopPedal: any): Promise<any[]>;
|
|
132
138
|
start(): Promise<void>;
|
|
133
139
|
stop(): void;
|
|
134
140
|
pause(): void;
|
|
@@ -164,28 +170,30 @@ export class Midy {
|
|
|
164
170
|
centToHz(cent: any): number;
|
|
165
171
|
calcSemitoneOffset(channel: any): any;
|
|
166
172
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
167
|
-
setVolumeEnvelope(note: any): void;
|
|
173
|
+
setVolumeEnvelope(channel: any, note: any): void;
|
|
174
|
+
setPitch(note: any, semitoneOffset: any): void;
|
|
175
|
+
clampCutoffFrequency(frequency: any): number;
|
|
168
176
|
setFilterEnvelope(channel: any, note: any): void;
|
|
169
|
-
startModulation(channel: any, note: any,
|
|
170
|
-
startVibrato(channel: any, note: any,
|
|
177
|
+
startModulation(channel: any, note: any, startTime: any): void;
|
|
178
|
+
startVibrato(channel: any, note: any, startTime: any): void;
|
|
171
179
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
172
180
|
calcBank(channel: any, channelNumber: any): any;
|
|
173
181
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
174
182
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
175
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any,
|
|
183
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
|
|
176
184
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
177
185
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
178
186
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
|
|
179
|
-
handleMIDIMessage(statusByte: any, data1: any, data2: any): void |
|
|
187
|
+
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
180
188
|
handlePolyphonicKeyPressure(channelNumber: any, noteNumber: any, pressure: any): void;
|
|
181
189
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
182
190
|
handleChannelPressure(channelNumber: any, pressure: any): void;
|
|
183
191
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
184
192
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
185
|
-
handleControlChange(channelNumber: any, controller: any, value: any): void |
|
|
193
|
+
handleControlChange(channelNumber: any, controller: any, value: any): void | Promise<void>;
|
|
186
194
|
setBankMSB(channelNumber: any, msb: any): void;
|
|
187
195
|
updateModulation(channel: any): void;
|
|
188
|
-
|
|
196
|
+
setModulationDepth(channelNumber: any, modulation: any): void;
|
|
189
197
|
setPortamentoTime(channelNumber: any, portamentoTime: any): void;
|
|
190
198
|
setVolume(channelNumber: any, volume: any): void;
|
|
191
199
|
panToGain(pan: any): {
|
|
@@ -203,6 +211,11 @@ export class Midy {
|
|
|
203
211
|
setChorusSendLevel(channelNumber: any, chorusSendLevel: any): void;
|
|
204
212
|
setSostenutoPedal(channelNumber: any, value: any): void;
|
|
205
213
|
setSoftPedal(channelNumber: any, softPedal: any): void;
|
|
214
|
+
setFilterResonance(channelNumber: any, filterResonance: any): void;
|
|
215
|
+
setReleaseTime(channelNumber: any, releaseTime: any): void;
|
|
216
|
+
setAttackTime(channelNumber: any, attackTime: any): void;
|
|
217
|
+
setBrightness(channelNumber: any, brightness: any): void;
|
|
218
|
+
setDecayTime(channelNumber: any, dacayTime: any): void;
|
|
206
219
|
setVibratoRate(channelNumber: any, vibratoRate: any): void;
|
|
207
220
|
setVibratoDepth(channelNumber: any, vibratoDepth: any): void;
|
|
208
221
|
setVibratoDelay(channelNumber: any, vibratoDelay: any): void;
|
|
@@ -223,9 +236,9 @@ export class Midy {
|
|
|
223
236
|
setCoarseTuning(channelNumber: any, coarseTuning: any): void;
|
|
224
237
|
handleModulationDepthRangeRPN(channelNumber: any): void;
|
|
225
238
|
setModulationDepthRange(channelNumber: any, modulationDepthRange: any): void;
|
|
226
|
-
allSoundOff(channelNumber: any):
|
|
239
|
+
allSoundOff(channelNumber: any): Promise<void>;
|
|
227
240
|
resetAllControllers(channelNumber: any): void;
|
|
228
|
-
allNotesOff(channelNumber: any):
|
|
241
|
+
allNotesOff(channelNumber: any): Promise<void>;
|
|
229
242
|
omniOff(): void;
|
|
230
243
|
omniOn(): void;
|
|
231
244
|
monoOn(): void;
|
|
@@ -265,12 +278,13 @@ export class Midy {
|
|
|
265
278
|
declare class Note {
|
|
266
279
|
constructor(noteNumber: any, velocity: any, startTime: any, instrumentKey: any);
|
|
267
280
|
bufferSource: any;
|
|
268
|
-
gainNode: any;
|
|
269
281
|
filterNode: any;
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
282
|
+
volumeNode: any;
|
|
283
|
+
volumeDepth: any;
|
|
284
|
+
modulationLFO: any;
|
|
285
|
+
modulationDepth: any;
|
|
286
|
+
vibratoLFO: any;
|
|
287
|
+
vibratoDepth: any;
|
|
274
288
|
noteNumber: any;
|
|
275
289
|
velocity: any;
|
|
276
290
|
startTime: any;
|
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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"}
|