@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-GM1.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MidyGM1 = 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,43 @@ 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", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(this, "modulationLFO", {
|
|
21
33
|
enumerable: true,
|
|
22
34
|
configurable: true,
|
|
23
35
|
writable: true,
|
|
24
36
|
value: void 0
|
|
25
37
|
});
|
|
26
|
-
Object.defineProperty(this, "
|
|
38
|
+
Object.defineProperty(this, "modulationDepth", {
|
|
27
39
|
enumerable: true,
|
|
28
40
|
configurable: true,
|
|
29
41
|
writable: true,
|
|
30
42
|
value: void 0
|
|
31
43
|
});
|
|
32
|
-
Object.defineProperty(this, "
|
|
44
|
+
Object.defineProperty(this, "vibratoLFO", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
configurable: true,
|
|
47
|
+
writable: true,
|
|
48
|
+
value: void 0
|
|
49
|
+
});
|
|
50
|
+
Object.defineProperty(this, "vibratoDepth", {
|
|
33
51
|
enumerable: true,
|
|
34
52
|
configurable: true,
|
|
35
53
|
writable: true,
|
|
@@ -316,7 +334,7 @@ class MidyGM1 {
|
|
|
316
334
|
const t = this.audioContext.currentTime + offset;
|
|
317
335
|
queueIndex = await this.scheduleTimelineEvents(t, offset, queueIndex);
|
|
318
336
|
if (this.isPausing) {
|
|
319
|
-
await this.stopNotes();
|
|
337
|
+
await this.stopNotes(0, true);
|
|
320
338
|
this.notePromises = [];
|
|
321
339
|
resolve();
|
|
322
340
|
this.isPausing = false;
|
|
@@ -324,7 +342,7 @@ class MidyGM1 {
|
|
|
324
342
|
return;
|
|
325
343
|
}
|
|
326
344
|
else if (this.isStopping) {
|
|
327
|
-
await this.stopNotes();
|
|
345
|
+
await this.stopNotes(0, true);
|
|
328
346
|
this.notePromises = [];
|
|
329
347
|
resolve();
|
|
330
348
|
this.isStopping = false;
|
|
@@ -332,7 +350,7 @@ class MidyGM1 {
|
|
|
332
350
|
return;
|
|
333
351
|
}
|
|
334
352
|
else if (this.isSeeking) {
|
|
335
|
-
this.stopNotes();
|
|
353
|
+
this.stopNotes(0, true);
|
|
336
354
|
this.startTime = this.audioContext.currentTime;
|
|
337
355
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
338
356
|
offset = this.resumeTime - this.startTime;
|
|
@@ -413,21 +431,25 @@ class MidyGM1 {
|
|
|
413
431
|
}
|
|
414
432
|
return { instruments, timeline };
|
|
415
433
|
}
|
|
416
|
-
|
|
434
|
+
async stopChannelNotes(channelNumber, velocity, stopPedal) {
|
|
417
435
|
const now = this.audioContext.currentTime;
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
});
|
|
428
|
-
});
|
|
429
|
-
channel.scheduledNotes.clear();
|
|
436
|
+
const channel = this.channels[channelNumber];
|
|
437
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
438
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
439
|
+
const note = noteList[i];
|
|
440
|
+
if (!note)
|
|
441
|
+
continue;
|
|
442
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
|
|
443
|
+
this.notePromises.push(promise);
|
|
444
|
+
}
|
|
430
445
|
});
|
|
446
|
+
channel.scheduledNotes.clear();
|
|
447
|
+
await Promise.all(this.notePromises);
|
|
448
|
+
}
|
|
449
|
+
stopNotes(velocity, stopPedal) {
|
|
450
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
451
|
+
this.stopChannelNotes(i, velocity, stopPedal);
|
|
452
|
+
}
|
|
431
453
|
return Promise.all(this.notePromises);
|
|
432
454
|
}
|
|
433
455
|
async start() {
|
|
@@ -511,75 +533,111 @@ class MidyGM1 {
|
|
|
511
533
|
}
|
|
512
534
|
setVolumeEnvelope(note) {
|
|
513
535
|
const { instrumentKey, startTime } = note;
|
|
514
|
-
note.gainNode = new GainNode(this.audioContext, { gain: 0 });
|
|
515
536
|
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
516
537
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
517
538
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
518
539
|
const volAttack = volDelay + instrumentKey.volAttack;
|
|
519
540
|
const volHold = volAttack + instrumentKey.volHold;
|
|
520
541
|
const volDecay = volHold + instrumentKey.volDecay;
|
|
521
|
-
note.
|
|
542
|
+
note.volumeNode.gain
|
|
543
|
+
.cancelScheduledValues(startTime)
|
|
544
|
+
.setValueAtTime(0, startTime)
|
|
522
545
|
.setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
|
|
523
546
|
.exponentialRampToValueAtTime(attackVolume, volAttack)
|
|
524
547
|
.setValueAtTime(attackVolume, volHold)
|
|
525
548
|
.linearRampToValueAtTime(sustainVolume, volDecay);
|
|
526
549
|
}
|
|
527
|
-
|
|
528
|
-
const { instrumentKey,
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
const
|
|
535
|
-
const
|
|
536
|
-
|
|
550
|
+
setPitch(note, semitoneOffset) {
|
|
551
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
552
|
+
const modEnvToPitch = instrumentKey.modEnvToPitch / 100;
|
|
553
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
554
|
+
if (modEnvToPitch === 0)
|
|
555
|
+
return;
|
|
556
|
+
const basePitch = note.bufferSource.playbackRate.value;
|
|
557
|
+
const peekPitch = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset + modEnvToPitch);
|
|
558
|
+
const modDelay = startTime + instrumentKey.modDelay;
|
|
559
|
+
const modAttack = modDelay + instrumentKey.modAttack;
|
|
560
|
+
const modHold = modAttack + instrumentKey.modHold;
|
|
561
|
+
const modDecay = modHold + instrumentKey.modDecay;
|
|
562
|
+
note.bufferSource.playbackRate.value
|
|
563
|
+
.setValueAtTime(basePitch, modDelay)
|
|
564
|
+
.exponentialRampToValueAtTime(peekPitch, modAttack)
|
|
565
|
+
.setValueAtTime(peekPitch, modHold)
|
|
566
|
+
.linearRampToValueAtTime(basePitch, modDecay);
|
|
567
|
+
}
|
|
568
|
+
clampCutoffFrequency(frequency) {
|
|
569
|
+
const minFrequency = 20; // min Hz of initialFilterFc
|
|
570
|
+
const maxFrequency = 20000; // max Hz of initialFilterFc
|
|
571
|
+
return Math.max(minFrequency, Math.min(frequency, maxFrequency));
|
|
572
|
+
}
|
|
573
|
+
setFilterEnvelope(note) {
|
|
574
|
+
const { instrumentKey, startTime } = note;
|
|
575
|
+
const baseFreq = this.centToHz(instrumentKey.initialFilterFc);
|
|
576
|
+
const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc);
|
|
577
|
+
const sustainFreq = baseFreq +
|
|
578
|
+
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
|
|
579
|
+
const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
|
|
580
|
+
const adjustedPeekFreq = this.clampCutoffFrequency(peekFreq);
|
|
581
|
+
const adjustedSustainFreq = this.clampCutoffFrequency(sustainFreq);
|
|
537
582
|
const modDelay = startTime + instrumentKey.modDelay;
|
|
538
583
|
const modAttack = modDelay + instrumentKey.modAttack;
|
|
539
584
|
const modHold = modAttack + instrumentKey.modHold;
|
|
540
585
|
const modDecay = modHold + instrumentKey.modDecay;
|
|
541
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
542
|
-
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
543
|
-
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
544
|
-
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
545
|
-
type: "lowpass",
|
|
546
|
-
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
547
|
-
frequency: adjustedBaseFreq,
|
|
548
|
-
});
|
|
549
586
|
note.filterNode.frequency
|
|
587
|
+
.cancelScheduledValues(startTime)
|
|
588
|
+
.setValueAtTime(adjustedBaseFreq, startTime)
|
|
550
589
|
.setValueAtTime(adjustedBaseFreq, modDelay)
|
|
551
590
|
.exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
|
|
552
591
|
.setValueAtTime(adjustedPeekFreq, modHold)
|
|
553
592
|
.linearRampToValueAtTime(adjustedSustainFreq, modDecay);
|
|
554
|
-
note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modEnvToPitch, modDelay);
|
|
555
593
|
}
|
|
556
|
-
startModulation(channel, note,
|
|
594
|
+
startModulation(channel, note, startTime) {
|
|
557
595
|
const { instrumentKey } = note;
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
});
|
|
561
|
-
note.modLFO = new OscillatorNode(this.audioContext, {
|
|
596
|
+
const { modLfoToPitch, modLfoToVolume } = instrumentKey;
|
|
597
|
+
note.modulationLFO = new OscillatorNode(this.audioContext, {
|
|
562
598
|
frequency: this.centToHz(instrumentKey.freqModLFO),
|
|
563
599
|
});
|
|
564
|
-
note.
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
600
|
+
note.filterDepth = new GainNode(this.audioContext, {
|
|
601
|
+
gain: instrumentKey.modLfoToFilterFc,
|
|
602
|
+
});
|
|
603
|
+
const modulationDepth = Math.abs(modLfoToPitch) + channel.modulationDepth;
|
|
604
|
+
const modulationDepthSign = (0 < modLfoToPitch) ? 1 : -1;
|
|
605
|
+
note.modulationDepth = new GainNode(this.audioContext, {
|
|
606
|
+
gain: modulationDepth * modulationDepthSign,
|
|
607
|
+
});
|
|
608
|
+
const volumeDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
|
|
609
|
+
const volumeDepthSign = (0 < modLfoToVolume) ? 1 : -1;
|
|
610
|
+
note.volumeDepth = new GainNode(this.audioContext, {
|
|
611
|
+
gain: volumeDepth * volumeDepthSign,
|
|
612
|
+
});
|
|
613
|
+
note.modulationLFO.start(startTime + instrumentKey.delayModLFO);
|
|
614
|
+
note.modulationLFO.connect(note.filterDepth);
|
|
615
|
+
note.filterDepth.connect(note.filterNode.frequency);
|
|
616
|
+
note.modulationLFO.connect(note.modulationDepth);
|
|
617
|
+
note.modulationDepth.connect(note.bufferSource.detune);
|
|
618
|
+
note.modulationLFO.connect(note.volumeDepth);
|
|
619
|
+
note.volumeDepth.connect(note.volumeNode.gain);
|
|
569
620
|
}
|
|
570
621
|
async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
|
|
571
622
|
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
572
623
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
573
624
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
574
|
-
note.
|
|
625
|
+
note.volumeNode = new GainNode(this.audioContext);
|
|
626
|
+
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
627
|
+
type: "lowpass",
|
|
628
|
+
Q: instrumentKey.initialFilterQ / 10 * channel.filterResonance, // dB
|
|
629
|
+
});
|
|
575
630
|
this.setVolumeEnvelope(note);
|
|
576
|
-
this.setFilterEnvelope(
|
|
577
|
-
if (channel.
|
|
578
|
-
|
|
579
|
-
this.startModulation(channel, note,
|
|
631
|
+
this.setFilterEnvelope(note);
|
|
632
|
+
if (0 < channel.modulationDepth) {
|
|
633
|
+
this.setPitch(note, semitoneOffset);
|
|
634
|
+
this.startModulation(channel, note, startTime);
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
580
638
|
}
|
|
581
639
|
note.bufferSource.connect(note.filterNode);
|
|
582
|
-
note.filterNode.connect(note.
|
|
640
|
+
note.filterNode.connect(note.volumeNode);
|
|
583
641
|
note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
|
|
584
642
|
return note;
|
|
585
643
|
}
|
|
@@ -595,8 +653,8 @@ class MidyGM1 {
|
|
|
595
653
|
if (!instrumentKey)
|
|
596
654
|
return;
|
|
597
655
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
598
|
-
note.
|
|
599
|
-
note.
|
|
656
|
+
note.volumeNode.connect(channel.gainL);
|
|
657
|
+
note.volumeNode.connect(channel.gainR);
|
|
600
658
|
const scheduledNotes = channel.scheduledNotes;
|
|
601
659
|
if (scheduledNotes.has(noteNumber)) {
|
|
602
660
|
scheduledNotes.get(noteNumber).push(note);
|
|
@@ -609,7 +667,7 @@ class MidyGM1 {
|
|
|
609
667
|
const now = this.audioContext.currentTime;
|
|
610
668
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
611
669
|
}
|
|
612
|
-
scheduleNoteRelease(channelNumber, noteNumber,
|
|
670
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, stopPedal = false) {
|
|
613
671
|
const channel = this.channels[channelNumber];
|
|
614
672
|
if (stopPedal && channel.sustainPedal)
|
|
615
673
|
return;
|
|
@@ -622,20 +680,14 @@ class MidyGM1 {
|
|
|
622
680
|
continue;
|
|
623
681
|
if (note.ending)
|
|
624
682
|
continue;
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
note.instrumentKey.volRelease * velocityRate;
|
|
628
|
-
note.gainNode.gain
|
|
683
|
+
const volEndTime = stopTime + note.instrumentKey.volRelease;
|
|
684
|
+
note.volumeNode.gain
|
|
629
685
|
.cancelScheduledValues(stopTime)
|
|
630
686
|
.linearRampToValueAtTime(0, volEndTime);
|
|
631
|
-
const
|
|
632
|
-
const baseFreq = this.centToHz(note.instrumentKey.initialFilterFc);
|
|
633
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
634
|
-
const modEndTime = stopTime +
|
|
635
|
-
note.instrumentKey.modRelease * velocityRate;
|
|
687
|
+
const modRelease = stopTime + note.instrumentKey.modRelease;
|
|
636
688
|
note.filterNode.frequency
|
|
637
689
|
.cancelScheduledValues(stopTime)
|
|
638
|
-
.linearRampToValueAtTime(
|
|
690
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
639
691
|
note.ending = true;
|
|
640
692
|
this.scheduleTask(() => {
|
|
641
693
|
note.bufferSource.loop = false;
|
|
@@ -644,15 +696,17 @@ class MidyGM1 {
|
|
|
644
696
|
note.bufferSource.onended = () => {
|
|
645
697
|
scheduledNotes[i] = null;
|
|
646
698
|
note.bufferSource.disconnect();
|
|
699
|
+
note.volumeNode.disconnect();
|
|
647
700
|
note.filterNode.disconnect();
|
|
648
|
-
note.
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
701
|
+
if (note.volumeDepth)
|
|
702
|
+
note.volumeDepth.disconnect();
|
|
703
|
+
if (note.modulationDepth)
|
|
704
|
+
note.modulationDepth.disconnect();
|
|
705
|
+
if (note.modulationLFO)
|
|
706
|
+
note.modulationLFO.stop();
|
|
653
707
|
resolve();
|
|
654
708
|
};
|
|
655
|
-
bufferSource.stop(volEndTime);
|
|
709
|
+
note.bufferSource.stop(volEndTime);
|
|
656
710
|
});
|
|
657
711
|
}
|
|
658
712
|
}
|
|
@@ -665,14 +719,15 @@ class MidyGM1 {
|
|
|
665
719
|
const channel = this.channels[channelNumber];
|
|
666
720
|
const promises = [];
|
|
667
721
|
channel.sustainPedal = false;
|
|
668
|
-
channel.scheduledNotes.forEach((
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
722
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
723
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
724
|
+
const note = noteList[i];
|
|
725
|
+
if (!note)
|
|
726
|
+
continue;
|
|
727
|
+
const { noteNumber } = note;
|
|
728
|
+
const promise = this.releaseNote(channelNumber, noteNumber, velocity);
|
|
729
|
+
promises.push(promise);
|
|
730
|
+
}
|
|
676
731
|
});
|
|
677
732
|
return promises;
|
|
678
733
|
}
|
|
@@ -713,7 +768,7 @@ class MidyGM1 {
|
|
|
713
768
|
handleControlChange(channelNumber, controller, value) {
|
|
714
769
|
switch (controller) {
|
|
715
770
|
case 1:
|
|
716
|
-
return this.
|
|
771
|
+
return this.setModulationDepth(channelNumber, value);
|
|
717
772
|
case 6:
|
|
718
773
|
return this.dataEntryMSB(channelNumber, value);
|
|
719
774
|
case 7:
|
|
@@ -742,20 +797,25 @@ class MidyGM1 {
|
|
|
742
797
|
}
|
|
743
798
|
updateModulation(channel) {
|
|
744
799
|
const now = this.audioContext.currentTime;
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
800
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
801
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
802
|
+
const note = noteList[i];
|
|
803
|
+
if (!note)
|
|
804
|
+
continue;
|
|
805
|
+
if (note.modulationDepth) {
|
|
806
|
+
note.modulationDepth.gain.setValueAtTime(channel.modulationDepth, now);
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
810
|
+
this.setPitch(note, semitoneOffset);
|
|
811
|
+
this.startModulation(channel, note, now);
|
|
812
|
+
}
|
|
753
813
|
}
|
|
754
814
|
});
|
|
755
815
|
}
|
|
756
|
-
|
|
816
|
+
setModulationDepth(channelNumber, modulation) {
|
|
757
817
|
const channel = this.channels[channelNumber];
|
|
758
|
-
channel.
|
|
818
|
+
channel.modulationDepth = (modulation / 127) * channel.modulationDepthRange;
|
|
759
819
|
this.updateModulation(channel);
|
|
760
820
|
}
|
|
761
821
|
setVolume(channelNumber, volume) {
|
|
@@ -857,13 +917,17 @@ class MidyGM1 {
|
|
|
857
917
|
}
|
|
858
918
|
updateDetune(channel, detuneChange) {
|
|
859
919
|
const now = this.audioContext.currentTime;
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
.
|
|
920
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
921
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
922
|
+
const note = noteList[i];
|
|
923
|
+
if (!note)
|
|
924
|
+
continue;
|
|
925
|
+
const { bufferSource } = note;
|
|
926
|
+
const detune = bufferSource.detune.value + detuneChange;
|
|
927
|
+
bufferSource.detune
|
|
928
|
+
.cancelScheduledValues(now)
|
|
929
|
+
.setValueAtTime(detune, now);
|
|
930
|
+
}
|
|
867
931
|
});
|
|
868
932
|
}
|
|
869
933
|
handlePitchBendRangeRPN(channelNumber) {
|
|
@@ -907,37 +971,13 @@ class MidyGM1 {
|
|
|
907
971
|
this.updateDetune(channel, detuneChange);
|
|
908
972
|
}
|
|
909
973
|
allSoundOff(channelNumber) {
|
|
910
|
-
|
|
911
|
-
const channel = this.channels[channelNumber];
|
|
912
|
-
const velocity = 0;
|
|
913
|
-
const stopPedal = true;
|
|
914
|
-
const promises = [];
|
|
915
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
916
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
917
|
-
if (activeNote) {
|
|
918
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
|
|
919
|
-
promises.push(notePromise);
|
|
920
|
-
}
|
|
921
|
-
});
|
|
922
|
-
return promises;
|
|
974
|
+
return this.stopChannelNotes(channelNumber, 0, true);
|
|
923
975
|
}
|
|
924
976
|
resetAllControllers(channelNumber) {
|
|
925
977
|
Object.assign(this.channels[channelNumber], this.effectSettings);
|
|
926
978
|
}
|
|
927
979
|
allNotesOff(channelNumber) {
|
|
928
|
-
|
|
929
|
-
const channel = this.channels[channelNumber];
|
|
930
|
-
const velocity = 0;
|
|
931
|
-
const stopPedal = false;
|
|
932
|
-
const promises = [];
|
|
933
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
934
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
935
|
-
if (activeNote) {
|
|
936
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
|
|
937
|
-
promises.push(notePromise);
|
|
938
|
-
}
|
|
939
|
-
});
|
|
940
|
-
return promises;
|
|
980
|
+
return this.stopChannelNotes(channelNumber, 0, false);
|
|
941
981
|
}
|
|
942
982
|
handleUniversalNonRealTimeExclusiveMessage(data) {
|
|
943
983
|
switch (data[2]) {
|
|
@@ -1033,7 +1073,7 @@ Object.defineProperty(MidyGM1, "channelSettings", {
|
|
|
1033
1073
|
pitchBend: 0,
|
|
1034
1074
|
fineTuning: 0, // cb
|
|
1035
1075
|
coarseTuning: 0, // cb
|
|
1036
|
-
modulationDepthRange:
|
|
1076
|
+
modulationDepthRange: 50, // cent
|
|
1037
1077
|
}
|
|
1038
1078
|
});
|
|
1039
1079
|
Object.defineProperty(MidyGM1, "effectSettings", {
|
|
@@ -1042,7 +1082,7 @@ Object.defineProperty(MidyGM1, "effectSettings", {
|
|
|
1042
1082
|
writable: true,
|
|
1043
1083
|
value: {
|
|
1044
1084
|
expression: 1,
|
|
1045
|
-
|
|
1085
|
+
modulationDepth: 0,
|
|
1046
1086
|
sustainPedal: false,
|
|
1047
1087
|
rpnMSB: 127,
|
|
1048
1088
|
rpnLSB: 127,
|
package/script/midy-GM2.d.ts
CHANGED
|
@@ -6,6 +6,9 @@ export class MidyGM2 {
|
|
|
6
6
|
portamentoTime: number;
|
|
7
7
|
reverbSendLevel: number;
|
|
8
8
|
chorusSendLevel: number;
|
|
9
|
+
vibratoRate: number;
|
|
10
|
+
vibratoDepth: number;
|
|
11
|
+
vibratoDelay: number;
|
|
9
12
|
bank: number;
|
|
10
13
|
bankMSB: number;
|
|
11
14
|
bankLSB: number;
|
|
@@ -19,7 +22,7 @@ export class MidyGM2 {
|
|
|
19
22
|
};
|
|
20
23
|
static effectSettings: {
|
|
21
24
|
expression: number;
|
|
22
|
-
|
|
25
|
+
modulationDepth: number;
|
|
23
26
|
sustainPedal: boolean;
|
|
24
27
|
portamento: boolean;
|
|
25
28
|
sostenutoPedal: boolean;
|
|
@@ -125,7 +128,8 @@ export class MidyGM2 {
|
|
|
125
128
|
instruments: Set<any>;
|
|
126
129
|
timeline: any[];
|
|
127
130
|
};
|
|
128
|
-
|
|
131
|
+
stopChannelNotes(channelNumber: any, velocity: any, stopPedal: any): Promise<void>;
|
|
132
|
+
stopNotes(velocity: any, stopPedal: any): Promise<any[]>;
|
|
129
133
|
start(): Promise<void>;
|
|
130
134
|
stop(): void;
|
|
131
135
|
pause(): void;
|
|
@@ -162,25 +166,28 @@ export class MidyGM2 {
|
|
|
162
166
|
calcSemitoneOffset(channel: any): any;
|
|
163
167
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
164
168
|
setVolumeEnvelope(note: any): void;
|
|
169
|
+
setPitch(note: any, semitoneOffset: any): void;
|
|
170
|
+
clampCutoffFrequency(frequency: any): number;
|
|
165
171
|
setFilterEnvelope(channel: any, note: any): void;
|
|
166
|
-
startModulation(channel: any, note: any,
|
|
172
|
+
startModulation(channel: any, note: any, startTime: any): void;
|
|
173
|
+
startVibrato(channel: any, note: any, startTime: any): void;
|
|
167
174
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
168
175
|
calcBank(channel: any, channelNumber: any): any;
|
|
169
176
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
170
177
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
171
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any,
|
|
178
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
|
|
172
179
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
173
180
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
174
181
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
|
|
175
|
-
handleMIDIMessage(statusByte: any, data1: any, data2: any): void |
|
|
182
|
+
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
176
183
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
177
184
|
handleChannelPressure(channelNumber: any, pressure: any): void;
|
|
178
185
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
179
186
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
180
|
-
handleControlChange(channelNumber: any, controller: any, value: any): void |
|
|
187
|
+
handleControlChange(channelNumber: any, controller: any, value: any): void | Promise<void>;
|
|
181
188
|
setBankMSB(channelNumber: any, msb: any): void;
|
|
182
189
|
updateModulation(channel: any): void;
|
|
183
|
-
|
|
190
|
+
setModulationDepth(channelNumber: any, modulation: any): void;
|
|
184
191
|
setPortamentoTime(channelNumber: any, portamentoTime: any): void;
|
|
185
192
|
setVolume(channelNumber: any, volume: any): void;
|
|
186
193
|
panToGain(pan: any): {
|
|
@@ -213,9 +220,9 @@ export class MidyGM2 {
|
|
|
213
220
|
setCoarseTuning(channelNumber: any, coarseTuning: any): void;
|
|
214
221
|
handleModulationDepthRangeRPN(channelNumber: any): void;
|
|
215
222
|
setModulationDepthRange(channelNumber: any, modulationDepthRange: any): void;
|
|
216
|
-
allSoundOff(channelNumber: any):
|
|
223
|
+
allSoundOff(channelNumber: any): Promise<void>;
|
|
217
224
|
resetAllControllers(channelNumber: any): void;
|
|
218
|
-
allNotesOff(channelNumber: any):
|
|
225
|
+
allNotesOff(channelNumber: any): Promise<void>;
|
|
219
226
|
omniOff(): void;
|
|
220
227
|
omniOn(): void;
|
|
221
228
|
monoOn(): void;
|
|
@@ -255,12 +262,13 @@ export class MidyGM2 {
|
|
|
255
262
|
declare class Note {
|
|
256
263
|
constructor(noteNumber: any, velocity: any, startTime: any, instrumentKey: any);
|
|
257
264
|
bufferSource: any;
|
|
258
|
-
gainNode: any;
|
|
259
265
|
filterNode: any;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
266
|
+
volumeNode: any;
|
|
267
|
+
volumeDepth: any;
|
|
268
|
+
modulationLFO: any;
|
|
269
|
+
modulationDepth: any;
|
|
270
|
+
vibratoLFO: any;
|
|
271
|
+
vibratoDepth: any;
|
|
264
272
|
noteNumber: any;
|
|
265
273
|
velocity: any;
|
|
266
274
|
startTime: any;
|
package/script/midy-GM2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}
|