@marmooo/midy 0.1.2 → 0.1.3
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 +17 -12
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +125 -96
- package/esm/midy-GM2.d.ts +21 -14
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +146 -107
- package/esm/midy-GMLite.d.ts +15 -12
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +115 -98
- package/esm/midy.d.ts +18 -15
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +147 -134
- 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 +17 -12
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +125 -96
- package/script/midy-GM2.d.ts +21 -14
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +146 -107
- package/script/midy-GMLite.d.ts +15 -12
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +115 -98
- package/script/midy.d.ts +18 -15
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +147 -134
- 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-GM2.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MidyGM2 = 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,37 +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", {
|
|
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,
|
|
36
42
|
value: void 0
|
|
37
43
|
});
|
|
38
|
-
Object.defineProperty(this, "
|
|
44
|
+
Object.defineProperty(this, "vibratoLFO", {
|
|
39
45
|
enumerable: true,
|
|
40
46
|
configurable: true,
|
|
41
47
|
writable: true,
|
|
42
48
|
value: void 0
|
|
43
49
|
});
|
|
44
|
-
Object.defineProperty(this, "
|
|
50
|
+
Object.defineProperty(this, "vibratoDepth", {
|
|
45
51
|
enumerable: true,
|
|
46
52
|
configurable: true,
|
|
47
53
|
writable: true,
|
|
@@ -407,7 +413,7 @@ class MidyGM2 {
|
|
|
407
413
|
const t = this.audioContext.currentTime + offset;
|
|
408
414
|
queueIndex = await this.scheduleTimelineEvents(t, offset, queueIndex);
|
|
409
415
|
if (this.isPausing) {
|
|
410
|
-
await this.stopNotes();
|
|
416
|
+
await this.stopNotes(0, true);
|
|
411
417
|
this.notePromises = [];
|
|
412
418
|
resolve();
|
|
413
419
|
this.isPausing = false;
|
|
@@ -415,7 +421,7 @@ class MidyGM2 {
|
|
|
415
421
|
return;
|
|
416
422
|
}
|
|
417
423
|
else if (this.isStopping) {
|
|
418
|
-
await this.stopNotes();
|
|
424
|
+
await this.stopNotes(0, true);
|
|
419
425
|
this.notePromises = [];
|
|
420
426
|
resolve();
|
|
421
427
|
this.isStopping = false;
|
|
@@ -423,7 +429,7 @@ class MidyGM2 {
|
|
|
423
429
|
return;
|
|
424
430
|
}
|
|
425
431
|
else if (this.isSeeking) {
|
|
426
|
-
this.stopNotes();
|
|
432
|
+
this.stopNotes(0, true);
|
|
427
433
|
this.startTime = this.audioContext.currentTime;
|
|
428
434
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
429
435
|
offset = this.resumeTime - this.startTime;
|
|
@@ -538,21 +544,24 @@ class MidyGM2 {
|
|
|
538
544
|
}
|
|
539
545
|
return { instruments, timeline };
|
|
540
546
|
}
|
|
541
|
-
|
|
547
|
+
async stopChannelNotes(channelNumber, velocity, stopPedal) {
|
|
542
548
|
const now = this.audioContext.currentTime;
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
this.notePromises.push(promise);
|
|
551
|
-
}
|
|
552
|
-
});
|
|
549
|
+
const channel = this.channels[channelNumber];
|
|
550
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
551
|
+
noteList.forEach((note) => {
|
|
552
|
+
if (note) {
|
|
553
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
|
|
554
|
+
this.notePromises.push(promise);
|
|
555
|
+
}
|
|
553
556
|
});
|
|
554
|
-
channel.scheduledNotes.clear();
|
|
555
557
|
});
|
|
558
|
+
channel.scheduledNotes.clear();
|
|
559
|
+
await Promise.all(this.notePromises);
|
|
560
|
+
}
|
|
561
|
+
stopNotes(velocity, stopPedal) {
|
|
562
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
563
|
+
this.stopChannelNotes(i, velocity, stopPedal);
|
|
564
|
+
}
|
|
556
565
|
return Promise.all(this.notePromises);
|
|
557
566
|
}
|
|
558
567
|
async start() {
|
|
@@ -767,36 +776,54 @@ class MidyGM2 {
|
|
|
767
776
|
}
|
|
768
777
|
setVolumeEnvelope(note) {
|
|
769
778
|
const { instrumentKey, startTime } = note;
|
|
770
|
-
note.
|
|
779
|
+
note.volumeNode = new GainNode(this.audioContext, { gain: 0 });
|
|
771
780
|
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
772
781
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
773
782
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
774
783
|
const volAttack = volDelay + instrumentKey.volAttack;
|
|
775
784
|
const volHold = volAttack + instrumentKey.volHold;
|
|
776
785
|
const volDecay = volHold + instrumentKey.volDecay;
|
|
777
|
-
note.
|
|
786
|
+
note.volumeNode.gain
|
|
778
787
|
.setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
|
|
779
788
|
.exponentialRampToValueAtTime(attackVolume, volAttack)
|
|
780
789
|
.setValueAtTime(attackVolume, volHold)
|
|
781
790
|
.linearRampToValueAtTime(sustainVolume, volDecay);
|
|
782
791
|
}
|
|
783
|
-
|
|
784
|
-
const { instrumentKey,
|
|
792
|
+
setPitch(note, semitoneOffset) {
|
|
793
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
794
|
+
const modEnvToPitch = instrumentKey.modEnvToPitch / 100;
|
|
795
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
796
|
+
if (modEnvToPitch === 0)
|
|
797
|
+
return;
|
|
798
|
+
const basePitch = note.bufferSource.playbackRate.value;
|
|
799
|
+
const peekPitch = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset + modEnvToPitch);
|
|
800
|
+
const modDelay = startTime + instrumentKey.modDelay;
|
|
801
|
+
const modAttack = modDelay + instrumentKey.modAttack;
|
|
802
|
+
const modHold = modAttack + instrumentKey.modHold;
|
|
803
|
+
const modDecay = modHold + instrumentKey.modDecay;
|
|
804
|
+
note.bufferSource.playbackRate.value
|
|
805
|
+
.setValueAtTime(basePitch, modDelay)
|
|
806
|
+
.exponentialRampToValueAtTime(peekPitch, modAttack)
|
|
807
|
+
.setValueAtTime(peekPitch, modHold)
|
|
808
|
+
.linearRampToValueAtTime(basePitch, modDecay);
|
|
809
|
+
}
|
|
810
|
+
setFilterNode(channel, note) {
|
|
811
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
785
812
|
const softPedalFactor = 1 -
|
|
786
813
|
(0.1 + (noteNumber / 127) * 0.2) * channel.softPedal;
|
|
787
814
|
const maxFreq = this.audioContext.sampleRate / 2;
|
|
788
815
|
const baseFreq = this.centToHz(instrumentKey.initialFilterFc) *
|
|
789
816
|
softPedalFactor;
|
|
790
817
|
const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc) * softPedalFactor;
|
|
791
|
-
const sustainFreq =
|
|
792
|
-
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain)
|
|
818
|
+
const sustainFreq = baseFreq +
|
|
819
|
+
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
|
|
820
|
+
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
821
|
+
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
822
|
+
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
793
823
|
const modDelay = startTime + instrumentKey.modDelay;
|
|
794
824
|
const modAttack = modDelay + instrumentKey.modAttack;
|
|
795
825
|
const modHold = modAttack + instrumentKey.modHold;
|
|
796
826
|
const modDecay = modHold + instrumentKey.modDecay;
|
|
797
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
798
|
-
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
799
|
-
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
800
827
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
801
828
|
type: "lowpass",
|
|
802
829
|
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
@@ -807,39 +834,72 @@ class MidyGM2 {
|
|
|
807
834
|
.exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
|
|
808
835
|
.setValueAtTime(adjustedPeekFreq, modHold)
|
|
809
836
|
.linearRampToValueAtTime(adjustedSustainFreq, modDecay);
|
|
810
|
-
note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modEnvToPitch, modDelay);
|
|
811
837
|
}
|
|
812
|
-
startModulation(channel, note,
|
|
838
|
+
startModulation(channel, note, startTime) {
|
|
813
839
|
const { instrumentKey } = note;
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
});
|
|
817
|
-
note.modLFO = new OscillatorNode(this.audioContext, {
|
|
840
|
+
const { modLfoToPitch, modLfoToVolume } = instrumentKey;
|
|
841
|
+
note.modulationLFO = new OscillatorNode(this.audioContext, {
|
|
818
842
|
frequency: this.centToHz(instrumentKey.freqModLFO),
|
|
819
843
|
});
|
|
820
|
-
note.
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
844
|
+
note.filterDepth = new GainNode(this.audioContext, {
|
|
845
|
+
gain: instrumentKey.modLfoToFilterFc,
|
|
846
|
+
});
|
|
847
|
+
const modulationDepth = Math.abs(modLfoToPitch) + channel.modulationDepth;
|
|
848
|
+
const modulationDepthSign = (0 < modLfoToPitch) ? 1 : -1;
|
|
849
|
+
note.modulationDepth = new GainNode(this.audioContext, {
|
|
850
|
+
gain: modulationDepth * modulationDepthSign,
|
|
851
|
+
});
|
|
852
|
+
const volumeDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
|
|
853
|
+
const volumeDepthSign = (0 < modLfoToVolume) ? 1 : -1;
|
|
854
|
+
note.volumeDepth = new GainNode(this.audioContext, {
|
|
855
|
+
gain: volumeDepth * volumeDepthSign,
|
|
856
|
+
});
|
|
857
|
+
note.modulationLFO.start(startTime + instrumentKey.delayModLFO);
|
|
858
|
+
note.modulationLFO.connect(note.filterDepth);
|
|
859
|
+
note.filterDepth.connect(note.filterNode.frequency);
|
|
860
|
+
note.modulationLFO.connect(note.modulationDepth);
|
|
861
|
+
note.modulationDepth.connect(note.bufferSource.detune);
|
|
862
|
+
note.modulationLFO.connect(note.volumeDepth);
|
|
863
|
+
note.volumeDepth.connect(note.volumeNode.gain);
|
|
864
|
+
}
|
|
865
|
+
startVibrato(channel, note, startTime) {
|
|
866
|
+
const { instrumentKey } = note;
|
|
867
|
+
const { vibLfoToPitch } = instrumentKey;
|
|
868
|
+
note.vibratoLFO = new OscillatorNode(this.audioContext, {
|
|
869
|
+
frequency: this.centToHz(instrumentKey.freqVibLFO) *
|
|
870
|
+
channel.vibratoRate,
|
|
871
|
+
});
|
|
872
|
+
const vibratoDepth = Math.abs(vibLfoToPitch) * channel.vibratoDepth;
|
|
873
|
+
const vibratoDepthSign = 0 < vibLfoToPitch;
|
|
874
|
+
note.vibratoDepth = new GainNode(this.audioContext, {
|
|
875
|
+
gain: vibratoDepth * vibratoDepthSign,
|
|
876
|
+
});
|
|
877
|
+
note.vibratoLFO.start(startTime + instrumentKey.delayVibLFO * channel.vibratoDelay);
|
|
878
|
+
note.vibratoLFO.connect(note.vibratoDepth);
|
|
879
|
+
note.vibratoDepth.connect(note.bufferSource.detune);
|
|
825
880
|
}
|
|
826
881
|
async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
|
|
827
882
|
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
828
883
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
829
884
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
830
|
-
|
|
885
|
+
this.setFilterNode(channel, note);
|
|
831
886
|
this.setVolumeEnvelope(note);
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
887
|
+
if (0 < channel.vibratoDepth) {
|
|
888
|
+
this.startVibrato(channel, note, startTime);
|
|
889
|
+
}
|
|
890
|
+
if (0 < channel.modulationDepth) {
|
|
891
|
+
this.setPitch(note, semitoneOffset);
|
|
892
|
+
this.startModulation(channel, note, startTime);
|
|
893
|
+
}
|
|
894
|
+
else {
|
|
895
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
836
896
|
}
|
|
837
897
|
if (this.mono && channel.currentBufferSource) {
|
|
838
898
|
channel.currentBufferSource.stop(startTime);
|
|
839
899
|
channel.currentBufferSource = note.bufferSource;
|
|
840
900
|
}
|
|
841
901
|
note.bufferSource.connect(note.filterNode);
|
|
842
|
-
note.filterNode.connect(note.
|
|
902
|
+
note.filterNode.connect(note.volumeNode);
|
|
843
903
|
note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
|
|
844
904
|
return note;
|
|
845
905
|
}
|
|
@@ -864,8 +924,8 @@ class MidyGM2 {
|
|
|
864
924
|
if (!instrumentKey)
|
|
865
925
|
return;
|
|
866
926
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
867
|
-
note.
|
|
868
|
-
note.
|
|
927
|
+
note.volumeNode.connect(channel.gainL);
|
|
928
|
+
note.volumeNode.connect(channel.gainR);
|
|
869
929
|
if (channel.sostenutoPedal) {
|
|
870
930
|
channel.sostenutoNotes.set(noteNumber, note);
|
|
871
931
|
}
|
|
@@ -899,17 +959,14 @@ class MidyGM2 {
|
|
|
899
959
|
const velocityRate = (velocity + 127) / 127;
|
|
900
960
|
const volEndTime = stopTime +
|
|
901
961
|
note.instrumentKey.volRelease * velocityRate;
|
|
902
|
-
note.
|
|
962
|
+
note.volumeNode.gain
|
|
903
963
|
.cancelScheduledValues(stopTime)
|
|
904
964
|
.linearRampToValueAtTime(0, volEndTime);
|
|
905
|
-
const
|
|
906
|
-
const baseFreq = this.centToHz(note.instrumentKey.initialFilterFc);
|
|
907
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
908
|
-
const modEndTime = stopTime +
|
|
965
|
+
const modRelease = stopTime +
|
|
909
966
|
note.instrumentKey.modRelease * velocityRate;
|
|
910
967
|
note.filterNode.frequency
|
|
911
968
|
.cancelScheduledValues(stopTime)
|
|
912
|
-
.linearRampToValueAtTime(
|
|
969
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
913
970
|
note.ending = true;
|
|
914
971
|
this.scheduleTask(() => {
|
|
915
972
|
note.bufferSource.loop = false;
|
|
@@ -918,16 +975,18 @@ class MidyGM2 {
|
|
|
918
975
|
note.bufferSource.onended = () => {
|
|
919
976
|
scheduledNotes[i] = null;
|
|
920
977
|
note.bufferSource.disconnect();
|
|
978
|
+
note.volumeNode.disconnect();
|
|
921
979
|
note.filterNode.disconnect();
|
|
922
|
-
note.
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
980
|
+
if (note.volumeDepth)
|
|
981
|
+
note.volumeDepth.disconnect();
|
|
982
|
+
if (note.modulationDepth)
|
|
983
|
+
note.modulationDepth.disconnect();
|
|
984
|
+
if (note.modulationLFO)
|
|
985
|
+
note.modulationLFO.stop();
|
|
986
|
+
if (note.vibratoDepth)
|
|
987
|
+
note.vibratoDepth.disconnect();
|
|
988
|
+
if (note.vibratoLFO)
|
|
989
|
+
note.vibratoLFO.stop();
|
|
931
990
|
resolve();
|
|
932
991
|
};
|
|
933
992
|
note.bufferSource.stop(volEndTime);
|
|
@@ -943,10 +1002,10 @@ class MidyGM2 {
|
|
|
943
1002
|
const channel = this.channels[channelNumber];
|
|
944
1003
|
const promises = [];
|
|
945
1004
|
channel.sustainPedal = false;
|
|
946
|
-
channel.scheduledNotes.forEach((
|
|
947
|
-
|
|
948
|
-
if (
|
|
949
|
-
const { noteNumber } =
|
|
1005
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1006
|
+
noteList.forEach((note) => {
|
|
1007
|
+
if (note) {
|
|
1008
|
+
const { noteNumber } = note;
|
|
950
1009
|
const promise = this.releaseNote(channelNumber, noteNumber, velocity);
|
|
951
1010
|
promises.push(promise);
|
|
952
1011
|
}
|
|
@@ -1000,8 +1059,8 @@ class MidyGM2 {
|
|
|
1000
1059
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1001
1060
|
if (channel.channelPressure.amplitudeControl !== 1) {
|
|
1002
1061
|
activeNotes.forEach((activeNote) => {
|
|
1003
|
-
const gain = activeNote.
|
|
1004
|
-
activeNote.
|
|
1062
|
+
const gain = activeNote.volumeNode.gain.value;
|
|
1063
|
+
activeNote.volumeNode.gain
|
|
1005
1064
|
.cancelScheduledValues(now)
|
|
1006
1065
|
.setValueAtTime(gain * pressure, now);
|
|
1007
1066
|
});
|
|
@@ -1024,7 +1083,7 @@ class MidyGM2 {
|
|
|
1024
1083
|
case 0:
|
|
1025
1084
|
return this.setBankMSB(channelNumber, value);
|
|
1026
1085
|
case 1:
|
|
1027
|
-
return this.
|
|
1086
|
+
return this.setModulationDepth(channelNumber, value);
|
|
1028
1087
|
case 5:
|
|
1029
1088
|
return this.setPortamentoTime(channelNumber, value);
|
|
1030
1089
|
case 6:
|
|
@@ -1080,18 +1139,19 @@ class MidyGM2 {
|
|
|
1080
1139
|
const now = this.audioContext.currentTime;
|
|
1081
1140
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1082
1141
|
activeNotes.forEach((activeNote) => {
|
|
1083
|
-
if (activeNote.
|
|
1084
|
-
|
|
1085
|
-
gainNode.gain.setValueAtTime(this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation), now);
|
|
1142
|
+
if (activeNote.modulationDepth) {
|
|
1143
|
+
activeNote.modulationDepth.gain.setValueAtTime(channel.modulationDepth, now);
|
|
1086
1144
|
}
|
|
1087
1145
|
else {
|
|
1146
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
1147
|
+
this.setPitch(activeNote, semitoneOffset);
|
|
1088
1148
|
this.startModulation(channel, activeNote, now);
|
|
1089
1149
|
}
|
|
1090
1150
|
});
|
|
1091
1151
|
}
|
|
1092
|
-
|
|
1152
|
+
setModulationDepth(channelNumber, modulation) {
|
|
1093
1153
|
const channel = this.channels[channelNumber];
|
|
1094
|
-
channel.
|
|
1154
|
+
channel.modulationDepth = (modulation / 127) * channel.modulationDepthRange;
|
|
1095
1155
|
this.updateModulation(channel);
|
|
1096
1156
|
}
|
|
1097
1157
|
setPortamentoTime(channelNumber, portamentoTime) {
|
|
@@ -1301,47 +1361,23 @@ class MidyGM2 {
|
|
|
1301
1361
|
handleModulationDepthRangeRPN(channelNumber) {
|
|
1302
1362
|
const channel = this.channels[channelNumber];
|
|
1303
1363
|
this.limitData(channel, 0, 127, 0, 127);
|
|
1304
|
-
const modulationDepthRange = dataMSB + dataLSB / 128;
|
|
1364
|
+
const modulationDepthRange = (dataMSB + dataLSB / 128) * 100;
|
|
1305
1365
|
this.setModulationDepthRange(channelNumber, modulationDepthRange);
|
|
1306
1366
|
}
|
|
1307
1367
|
setModulationDepthRange(channelNumber, modulationDepthRange) {
|
|
1308
1368
|
const channel = this.channels[channelNumber];
|
|
1309
1369
|
channel.modulationDepthRange = modulationDepthRange;
|
|
1310
|
-
channel.
|
|
1370
|
+
channel.modulationDepth = (modulation / 127) * modulationDepthRange;
|
|
1311
1371
|
this.updateModulation(channel);
|
|
1312
1372
|
}
|
|
1313
1373
|
allSoundOff(channelNumber) {
|
|
1314
|
-
|
|
1315
|
-
const channel = this.channels[channelNumber];
|
|
1316
|
-
const velocity = 0;
|
|
1317
|
-
const stopPedal = true;
|
|
1318
|
-
const promises = [];
|
|
1319
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
1320
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
1321
|
-
if (activeNote) {
|
|
1322
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
|
|
1323
|
-
promises.push(notePromise);
|
|
1324
|
-
}
|
|
1325
|
-
});
|
|
1326
|
-
return promises;
|
|
1374
|
+
return this.stopChannelNotes(channelNumber, 0, true);
|
|
1327
1375
|
}
|
|
1328
1376
|
resetAllControllers(channelNumber) {
|
|
1329
1377
|
Object.assign(this.channels[channelNumber], this.effectSettings);
|
|
1330
1378
|
}
|
|
1331
1379
|
allNotesOff(channelNumber) {
|
|
1332
|
-
|
|
1333
|
-
const channel = this.channels[channelNumber];
|
|
1334
|
-
const velocity = 0;
|
|
1335
|
-
const stopPedal = false;
|
|
1336
|
-
const promises = [];
|
|
1337
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
1338
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
1339
|
-
if (activeNote) {
|
|
1340
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
|
|
1341
|
-
promises.push(notePromise);
|
|
1342
|
-
}
|
|
1343
|
-
});
|
|
1344
|
-
return promises;
|
|
1380
|
+
return this.stopChannelNotes(channelNumber, 0, false);
|
|
1345
1381
|
}
|
|
1346
1382
|
omniOff() {
|
|
1347
1383
|
this.omni = false;
|
|
@@ -1702,6 +1738,9 @@ Object.defineProperty(MidyGM2, "channelSettings", {
|
|
|
1702
1738
|
portamentoTime: 0,
|
|
1703
1739
|
reverbSendLevel: 0,
|
|
1704
1740
|
chorusSendLevel: 0,
|
|
1741
|
+
vibratoRate: 1,
|
|
1742
|
+
vibratoDepth: 1,
|
|
1743
|
+
vibratoDelay: 1,
|
|
1705
1744
|
bank: 121 * 128,
|
|
1706
1745
|
bankMSB: 121,
|
|
1707
1746
|
bankLSB: 0,
|
|
@@ -1711,7 +1750,7 @@ Object.defineProperty(MidyGM2, "channelSettings", {
|
|
|
1711
1750
|
pitchBend: 0,
|
|
1712
1751
|
fineTuning: 0, // cb
|
|
1713
1752
|
coarseTuning: 0, // cb
|
|
1714
|
-
modulationDepthRange:
|
|
1753
|
+
modulationDepthRange: 50, // cent
|
|
1715
1754
|
}
|
|
1716
1755
|
});
|
|
1717
1756
|
Object.defineProperty(MidyGM2, "effectSettings", {
|
|
@@ -1720,7 +1759,7 @@ Object.defineProperty(MidyGM2, "effectSettings", {
|
|
|
1720
1759
|
writable: true,
|
|
1721
1760
|
value: {
|
|
1722
1761
|
expression: 1,
|
|
1723
|
-
|
|
1762
|
+
modulationDepth: 0,
|
|
1724
1763
|
sustainPedal: false,
|
|
1725
1764
|
portamento: false,
|
|
1726
1765
|
sostenutoPedal: false,
|
package/script/midy-GMLite.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export class MidyGMLite {
|
|
|
11
11
|
};
|
|
12
12
|
static effectSettings: {
|
|
13
13
|
expression: number;
|
|
14
|
-
|
|
14
|
+
modulationDepth: number;
|
|
15
15
|
sustainPedal: boolean;
|
|
16
16
|
rpnMSB: number;
|
|
17
17
|
rpnLSB: number;
|
|
@@ -60,7 +60,8 @@ export class MidyGMLite {
|
|
|
60
60
|
instruments: Set<any>;
|
|
61
61
|
timeline: any[];
|
|
62
62
|
};
|
|
63
|
-
|
|
63
|
+
stopChannelNotes(channelNumber: any, velocity: any, stopPedal: any): Promise<void>;
|
|
64
|
+
stopNotes(velocity: any, stopPedal: any): Promise<any[]>;
|
|
64
65
|
start(): Promise<void>;
|
|
65
66
|
stop(): void;
|
|
66
67
|
pause(): void;
|
|
@@ -75,21 +76,22 @@ export class MidyGMLite {
|
|
|
75
76
|
calcSemitoneOffset(channel: any): number;
|
|
76
77
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
77
78
|
setVolumeEnvelope(note: any): void;
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
setPitch(note: any, semitoneOffset: any): void;
|
|
80
|
+
setFilterNode(channel: any, note: any): void;
|
|
81
|
+
startModulation(channel: any, note: any, startTime: any): void;
|
|
80
82
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
81
83
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
82
84
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
83
85
|
scheduleNoteRelease(channelNumber: any, noteNumber: any, velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
|
|
84
86
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
85
87
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
86
|
-
handleMIDIMessage(statusByte: any, data1: any, data2: any): void |
|
|
88
|
+
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
87
89
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
88
90
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
89
91
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
90
|
-
handleControlChange(channelNumber: any, controller: any, value: any): void |
|
|
92
|
+
handleControlChange(channelNumber: any, controller: any, value: any): void | Promise<void>;
|
|
91
93
|
updateModulation(channel: any): void;
|
|
92
|
-
|
|
94
|
+
setModulationDepth(channelNumber: any, modulation: any): void;
|
|
93
95
|
setVolume(channelNumber: any, volume: any): void;
|
|
94
96
|
panToGain(pan: any): {
|
|
95
97
|
gainLeft: number;
|
|
@@ -107,9 +109,9 @@ export class MidyGMLite {
|
|
|
107
109
|
updateDetune(channel: any, detuneChange: any): void;
|
|
108
110
|
handlePitchBendRangeRPN(channelNumber: any): void;
|
|
109
111
|
setPitchBendRange(channelNumber: any, pitchBendRange: any): void;
|
|
110
|
-
allSoundOff(channelNumber: any):
|
|
112
|
+
allSoundOff(channelNumber: any): Promise<void>;
|
|
111
113
|
resetAllControllers(channelNumber: any): void;
|
|
112
|
-
allNotesOff(channelNumber: any):
|
|
114
|
+
allNotesOff(channelNumber: any): Promise<void>;
|
|
113
115
|
handleUniversalNonRealTimeExclusiveMessage(data: any): void;
|
|
114
116
|
GM1SystemOn(): void;
|
|
115
117
|
handleUniversalRealTimeExclusiveMessage(data: any): void;
|
|
@@ -122,10 +124,11 @@ export class MidyGMLite {
|
|
|
122
124
|
declare class Note {
|
|
123
125
|
constructor(noteNumber: any, velocity: any, startTime: any, instrumentKey: any);
|
|
124
126
|
bufferSource: any;
|
|
125
|
-
gainNode: any;
|
|
126
127
|
filterNode: any;
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
volumeNode: any;
|
|
129
|
+
volumeDepth: any;
|
|
130
|
+
modulationLFO: any;
|
|
131
|
+
modulationDepth: any;
|
|
129
132
|
noteNumber: any;
|
|
130
133
|
velocity: any;
|
|
131
134
|
startTime: any;
|
|
@@ -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":"AAsBA;IAmBE;;;;;;;;;MASE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA5CD,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAuBhB,kBAAgC;IAChC,gBAA4C;IAC5C,gBAAiD;IAKnD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EA+CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA8DC;IAED,mFAmBC;IAED,yDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,2BAEC;IAED,4BAEC;IAED,yCAEC;IAED,mFAGC;IAED,mCAcC;IAED,+CAwBC;IAED,6CA6BC;IAED,+DA0BC;IAED,wHA8BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIA4CC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,uDAOC;IAED,2FA+BC;IAED,qCAeC;IAED,8DAIC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,sCAUC;IAED,sDAMC;IAED,oCAYC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAUC;IAED,kDAKC;IAED,iEAOC;IAED,+CAEC;IAED,8CAEC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AA1+BD;IAQE,gFAKC;IAZD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|