@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/esm/midy-GM2.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseMidi } from "./deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.js";
|
|
2
|
-
import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.
|
|
2
|
+
import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.js";
|
|
3
3
|
class Note {
|
|
4
4
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
5
5
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -8,37 +8,43 @@ class Note {
|
|
|
8
8
|
writable: true,
|
|
9
9
|
value: void 0
|
|
10
10
|
});
|
|
11
|
-
Object.defineProperty(this, "
|
|
11
|
+
Object.defineProperty(this, "filterNode", {
|
|
12
12
|
enumerable: true,
|
|
13
13
|
configurable: true,
|
|
14
14
|
writable: true,
|
|
15
15
|
value: void 0
|
|
16
16
|
});
|
|
17
|
-
Object.defineProperty(this, "
|
|
17
|
+
Object.defineProperty(this, "volumeNode", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: void 0
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(this, "volumeDepth", {
|
|
18
24
|
enumerable: true,
|
|
19
25
|
configurable: true,
|
|
20
26
|
writable: true,
|
|
21
27
|
value: void 0
|
|
22
28
|
});
|
|
23
|
-
Object.defineProperty(this, "
|
|
29
|
+
Object.defineProperty(this, "modulationLFO", {
|
|
24
30
|
enumerable: true,
|
|
25
31
|
configurable: true,
|
|
26
32
|
writable: true,
|
|
27
33
|
value: void 0
|
|
28
34
|
});
|
|
29
|
-
Object.defineProperty(this, "
|
|
35
|
+
Object.defineProperty(this, "modulationDepth", {
|
|
30
36
|
enumerable: true,
|
|
31
37
|
configurable: true,
|
|
32
38
|
writable: true,
|
|
33
39
|
value: void 0
|
|
34
40
|
});
|
|
35
|
-
Object.defineProperty(this, "
|
|
41
|
+
Object.defineProperty(this, "vibratoLFO", {
|
|
36
42
|
enumerable: true,
|
|
37
43
|
configurable: true,
|
|
38
44
|
writable: true,
|
|
39
45
|
value: void 0
|
|
40
46
|
});
|
|
41
|
-
Object.defineProperty(this, "
|
|
47
|
+
Object.defineProperty(this, "vibratoDepth", {
|
|
42
48
|
enumerable: true,
|
|
43
49
|
configurable: true,
|
|
44
50
|
writable: true,
|
|
@@ -404,7 +410,7 @@ export class MidyGM2 {
|
|
|
404
410
|
const t = this.audioContext.currentTime + offset;
|
|
405
411
|
queueIndex = await this.scheduleTimelineEvents(t, offset, queueIndex);
|
|
406
412
|
if (this.isPausing) {
|
|
407
|
-
await this.stopNotes();
|
|
413
|
+
await this.stopNotes(0, true);
|
|
408
414
|
this.notePromises = [];
|
|
409
415
|
resolve();
|
|
410
416
|
this.isPausing = false;
|
|
@@ -412,7 +418,7 @@ export class MidyGM2 {
|
|
|
412
418
|
return;
|
|
413
419
|
}
|
|
414
420
|
else if (this.isStopping) {
|
|
415
|
-
await this.stopNotes();
|
|
421
|
+
await this.stopNotes(0, true);
|
|
416
422
|
this.notePromises = [];
|
|
417
423
|
resolve();
|
|
418
424
|
this.isStopping = false;
|
|
@@ -420,7 +426,7 @@ export class MidyGM2 {
|
|
|
420
426
|
return;
|
|
421
427
|
}
|
|
422
428
|
else if (this.isSeeking) {
|
|
423
|
-
this.stopNotes();
|
|
429
|
+
this.stopNotes(0, true);
|
|
424
430
|
this.startTime = this.audioContext.currentTime;
|
|
425
431
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
426
432
|
offset = this.resumeTime - this.startTime;
|
|
@@ -535,21 +541,24 @@ export class MidyGM2 {
|
|
|
535
541
|
}
|
|
536
542
|
return { instruments, timeline };
|
|
537
543
|
}
|
|
538
|
-
|
|
544
|
+
async stopChannelNotes(channelNumber, velocity, stopPedal) {
|
|
539
545
|
const now = this.audioContext.currentTime;
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
this.notePromises.push(promise);
|
|
548
|
-
}
|
|
549
|
-
});
|
|
546
|
+
const channel = this.channels[channelNumber];
|
|
547
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
548
|
+
noteList.forEach((note) => {
|
|
549
|
+
if (note) {
|
|
550
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
|
|
551
|
+
this.notePromises.push(promise);
|
|
552
|
+
}
|
|
550
553
|
});
|
|
551
|
-
channel.scheduledNotes.clear();
|
|
552
554
|
});
|
|
555
|
+
channel.scheduledNotes.clear();
|
|
556
|
+
await Promise.all(this.notePromises);
|
|
557
|
+
}
|
|
558
|
+
stopNotes(velocity, stopPedal) {
|
|
559
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
560
|
+
this.stopChannelNotes(i, velocity, stopPedal);
|
|
561
|
+
}
|
|
553
562
|
return Promise.all(this.notePromises);
|
|
554
563
|
}
|
|
555
564
|
async start() {
|
|
@@ -764,36 +773,54 @@ export class MidyGM2 {
|
|
|
764
773
|
}
|
|
765
774
|
setVolumeEnvelope(note) {
|
|
766
775
|
const { instrumentKey, startTime } = note;
|
|
767
|
-
note.
|
|
776
|
+
note.volumeNode = new GainNode(this.audioContext, { gain: 0 });
|
|
768
777
|
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
769
778
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
770
779
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
771
780
|
const volAttack = volDelay + instrumentKey.volAttack;
|
|
772
781
|
const volHold = volAttack + instrumentKey.volHold;
|
|
773
782
|
const volDecay = volHold + instrumentKey.volDecay;
|
|
774
|
-
note.
|
|
783
|
+
note.volumeNode.gain
|
|
775
784
|
.setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
|
|
776
785
|
.exponentialRampToValueAtTime(attackVolume, volAttack)
|
|
777
786
|
.setValueAtTime(attackVolume, volHold)
|
|
778
787
|
.linearRampToValueAtTime(sustainVolume, volDecay);
|
|
779
788
|
}
|
|
780
|
-
|
|
781
|
-
const { instrumentKey,
|
|
789
|
+
setPitch(note, semitoneOffset) {
|
|
790
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
791
|
+
const modEnvToPitch = instrumentKey.modEnvToPitch / 100;
|
|
792
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
793
|
+
if (modEnvToPitch === 0)
|
|
794
|
+
return;
|
|
795
|
+
const basePitch = note.bufferSource.playbackRate.value;
|
|
796
|
+
const peekPitch = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset + modEnvToPitch);
|
|
797
|
+
const modDelay = startTime + instrumentKey.modDelay;
|
|
798
|
+
const modAttack = modDelay + instrumentKey.modAttack;
|
|
799
|
+
const modHold = modAttack + instrumentKey.modHold;
|
|
800
|
+
const modDecay = modHold + instrumentKey.modDecay;
|
|
801
|
+
note.bufferSource.playbackRate.value
|
|
802
|
+
.setValueAtTime(basePitch, modDelay)
|
|
803
|
+
.exponentialRampToValueAtTime(peekPitch, modAttack)
|
|
804
|
+
.setValueAtTime(peekPitch, modHold)
|
|
805
|
+
.linearRampToValueAtTime(basePitch, modDecay);
|
|
806
|
+
}
|
|
807
|
+
setFilterNode(channel, note) {
|
|
808
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
782
809
|
const softPedalFactor = 1 -
|
|
783
810
|
(0.1 + (noteNumber / 127) * 0.2) * channel.softPedal;
|
|
784
811
|
const maxFreq = this.audioContext.sampleRate / 2;
|
|
785
812
|
const baseFreq = this.centToHz(instrumentKey.initialFilterFc) *
|
|
786
813
|
softPedalFactor;
|
|
787
814
|
const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc) * softPedalFactor;
|
|
788
|
-
const sustainFreq =
|
|
789
|
-
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain)
|
|
815
|
+
const sustainFreq = baseFreq +
|
|
816
|
+
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
|
|
817
|
+
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
818
|
+
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
819
|
+
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
790
820
|
const modDelay = startTime + instrumentKey.modDelay;
|
|
791
821
|
const modAttack = modDelay + instrumentKey.modAttack;
|
|
792
822
|
const modHold = modAttack + instrumentKey.modHold;
|
|
793
823
|
const modDecay = modHold + instrumentKey.modDecay;
|
|
794
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
795
|
-
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
796
|
-
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
797
824
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
798
825
|
type: "lowpass",
|
|
799
826
|
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
@@ -804,39 +831,72 @@ export class MidyGM2 {
|
|
|
804
831
|
.exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
|
|
805
832
|
.setValueAtTime(adjustedPeekFreq, modHold)
|
|
806
833
|
.linearRampToValueAtTime(adjustedSustainFreq, modDecay);
|
|
807
|
-
note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modEnvToPitch, modDelay);
|
|
808
834
|
}
|
|
809
|
-
startModulation(channel, note,
|
|
835
|
+
startModulation(channel, note, startTime) {
|
|
810
836
|
const { instrumentKey } = note;
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
});
|
|
814
|
-
note.modLFO = new OscillatorNode(this.audioContext, {
|
|
837
|
+
const { modLfoToPitch, modLfoToVolume } = instrumentKey;
|
|
838
|
+
note.modulationLFO = new OscillatorNode(this.audioContext, {
|
|
815
839
|
frequency: this.centToHz(instrumentKey.freqModLFO),
|
|
816
840
|
});
|
|
817
|
-
note.
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
841
|
+
note.filterDepth = new GainNode(this.audioContext, {
|
|
842
|
+
gain: instrumentKey.modLfoToFilterFc,
|
|
843
|
+
});
|
|
844
|
+
const modulationDepth = Math.abs(modLfoToPitch) + channel.modulationDepth;
|
|
845
|
+
const modulationDepthSign = (0 < modLfoToPitch) ? 1 : -1;
|
|
846
|
+
note.modulationDepth = new GainNode(this.audioContext, {
|
|
847
|
+
gain: modulationDepth * modulationDepthSign,
|
|
848
|
+
});
|
|
849
|
+
const volumeDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
|
|
850
|
+
const volumeDepthSign = (0 < modLfoToVolume) ? 1 : -1;
|
|
851
|
+
note.volumeDepth = new GainNode(this.audioContext, {
|
|
852
|
+
gain: volumeDepth * volumeDepthSign,
|
|
853
|
+
});
|
|
854
|
+
note.modulationLFO.start(startTime + instrumentKey.delayModLFO);
|
|
855
|
+
note.modulationLFO.connect(note.filterDepth);
|
|
856
|
+
note.filterDepth.connect(note.filterNode.frequency);
|
|
857
|
+
note.modulationLFO.connect(note.modulationDepth);
|
|
858
|
+
note.modulationDepth.connect(note.bufferSource.detune);
|
|
859
|
+
note.modulationLFO.connect(note.volumeDepth);
|
|
860
|
+
note.volumeDepth.connect(note.volumeNode.gain);
|
|
861
|
+
}
|
|
862
|
+
startVibrato(channel, note, startTime) {
|
|
863
|
+
const { instrumentKey } = note;
|
|
864
|
+
const { vibLfoToPitch } = instrumentKey;
|
|
865
|
+
note.vibratoLFO = new OscillatorNode(this.audioContext, {
|
|
866
|
+
frequency: this.centToHz(instrumentKey.freqVibLFO) *
|
|
867
|
+
channel.vibratoRate,
|
|
868
|
+
});
|
|
869
|
+
const vibratoDepth = Math.abs(vibLfoToPitch) * channel.vibratoDepth;
|
|
870
|
+
const vibratoDepthSign = 0 < vibLfoToPitch;
|
|
871
|
+
note.vibratoDepth = new GainNode(this.audioContext, {
|
|
872
|
+
gain: vibratoDepth * vibratoDepthSign,
|
|
873
|
+
});
|
|
874
|
+
note.vibratoLFO.start(startTime + instrumentKey.delayVibLFO * channel.vibratoDelay);
|
|
875
|
+
note.vibratoLFO.connect(note.vibratoDepth);
|
|
876
|
+
note.vibratoDepth.connect(note.bufferSource.detune);
|
|
822
877
|
}
|
|
823
878
|
async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
|
|
824
879
|
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
825
880
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
826
881
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
827
|
-
|
|
882
|
+
this.setFilterNode(channel, note);
|
|
828
883
|
this.setVolumeEnvelope(note);
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
884
|
+
if (0 < channel.vibratoDepth) {
|
|
885
|
+
this.startVibrato(channel, note, startTime);
|
|
886
|
+
}
|
|
887
|
+
if (0 < channel.modulationDepth) {
|
|
888
|
+
this.setPitch(note, semitoneOffset);
|
|
889
|
+
this.startModulation(channel, note, startTime);
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
833
893
|
}
|
|
834
894
|
if (this.mono && channel.currentBufferSource) {
|
|
835
895
|
channel.currentBufferSource.stop(startTime);
|
|
836
896
|
channel.currentBufferSource = note.bufferSource;
|
|
837
897
|
}
|
|
838
898
|
note.bufferSource.connect(note.filterNode);
|
|
839
|
-
note.filterNode.connect(note.
|
|
899
|
+
note.filterNode.connect(note.volumeNode);
|
|
840
900
|
note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
|
|
841
901
|
return note;
|
|
842
902
|
}
|
|
@@ -861,8 +921,8 @@ export class MidyGM2 {
|
|
|
861
921
|
if (!instrumentKey)
|
|
862
922
|
return;
|
|
863
923
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
864
|
-
note.
|
|
865
|
-
note.
|
|
924
|
+
note.volumeNode.connect(channel.gainL);
|
|
925
|
+
note.volumeNode.connect(channel.gainR);
|
|
866
926
|
if (channel.sostenutoPedal) {
|
|
867
927
|
channel.sostenutoNotes.set(noteNumber, note);
|
|
868
928
|
}
|
|
@@ -896,17 +956,14 @@ export class MidyGM2 {
|
|
|
896
956
|
const velocityRate = (velocity + 127) / 127;
|
|
897
957
|
const volEndTime = stopTime +
|
|
898
958
|
note.instrumentKey.volRelease * velocityRate;
|
|
899
|
-
note.
|
|
959
|
+
note.volumeNode.gain
|
|
900
960
|
.cancelScheduledValues(stopTime)
|
|
901
961
|
.linearRampToValueAtTime(0, volEndTime);
|
|
902
|
-
const
|
|
903
|
-
const baseFreq = this.centToHz(note.instrumentKey.initialFilterFc);
|
|
904
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
905
|
-
const modEndTime = stopTime +
|
|
962
|
+
const modRelease = stopTime +
|
|
906
963
|
note.instrumentKey.modRelease * velocityRate;
|
|
907
964
|
note.filterNode.frequency
|
|
908
965
|
.cancelScheduledValues(stopTime)
|
|
909
|
-
.linearRampToValueAtTime(
|
|
966
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
910
967
|
note.ending = true;
|
|
911
968
|
this.scheduleTask(() => {
|
|
912
969
|
note.bufferSource.loop = false;
|
|
@@ -915,16 +972,18 @@ export class MidyGM2 {
|
|
|
915
972
|
note.bufferSource.onended = () => {
|
|
916
973
|
scheduledNotes[i] = null;
|
|
917
974
|
note.bufferSource.disconnect();
|
|
975
|
+
note.volumeNode.disconnect();
|
|
918
976
|
note.filterNode.disconnect();
|
|
919
|
-
note.
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
977
|
+
if (note.volumeDepth)
|
|
978
|
+
note.volumeDepth.disconnect();
|
|
979
|
+
if (note.modulationDepth)
|
|
980
|
+
note.modulationDepth.disconnect();
|
|
981
|
+
if (note.modulationLFO)
|
|
982
|
+
note.modulationLFO.stop();
|
|
983
|
+
if (note.vibratoDepth)
|
|
984
|
+
note.vibratoDepth.disconnect();
|
|
985
|
+
if (note.vibratoLFO)
|
|
986
|
+
note.vibratoLFO.stop();
|
|
928
987
|
resolve();
|
|
929
988
|
};
|
|
930
989
|
note.bufferSource.stop(volEndTime);
|
|
@@ -940,10 +999,10 @@ export class MidyGM2 {
|
|
|
940
999
|
const channel = this.channels[channelNumber];
|
|
941
1000
|
const promises = [];
|
|
942
1001
|
channel.sustainPedal = false;
|
|
943
|
-
channel.scheduledNotes.forEach((
|
|
944
|
-
|
|
945
|
-
if (
|
|
946
|
-
const { noteNumber } =
|
|
1002
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1003
|
+
noteList.forEach((note) => {
|
|
1004
|
+
if (note) {
|
|
1005
|
+
const { noteNumber } = note;
|
|
947
1006
|
const promise = this.releaseNote(channelNumber, noteNumber, velocity);
|
|
948
1007
|
promises.push(promise);
|
|
949
1008
|
}
|
|
@@ -997,8 +1056,8 @@ export class MidyGM2 {
|
|
|
997
1056
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
998
1057
|
if (channel.channelPressure.amplitudeControl !== 1) {
|
|
999
1058
|
activeNotes.forEach((activeNote) => {
|
|
1000
|
-
const gain = activeNote.
|
|
1001
|
-
activeNote.
|
|
1059
|
+
const gain = activeNote.volumeNode.gain.value;
|
|
1060
|
+
activeNote.volumeNode.gain
|
|
1002
1061
|
.cancelScheduledValues(now)
|
|
1003
1062
|
.setValueAtTime(gain * pressure, now);
|
|
1004
1063
|
});
|
|
@@ -1021,7 +1080,7 @@ export class MidyGM2 {
|
|
|
1021
1080
|
case 0:
|
|
1022
1081
|
return this.setBankMSB(channelNumber, value);
|
|
1023
1082
|
case 1:
|
|
1024
|
-
return this.
|
|
1083
|
+
return this.setModulationDepth(channelNumber, value);
|
|
1025
1084
|
case 5:
|
|
1026
1085
|
return this.setPortamentoTime(channelNumber, value);
|
|
1027
1086
|
case 6:
|
|
@@ -1077,18 +1136,19 @@ export class MidyGM2 {
|
|
|
1077
1136
|
const now = this.audioContext.currentTime;
|
|
1078
1137
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1079
1138
|
activeNotes.forEach((activeNote) => {
|
|
1080
|
-
if (activeNote.
|
|
1081
|
-
|
|
1082
|
-
gainNode.gain.setValueAtTime(this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation), now);
|
|
1139
|
+
if (activeNote.modulationDepth) {
|
|
1140
|
+
activeNote.modulationDepth.gain.setValueAtTime(channel.modulationDepth, now);
|
|
1083
1141
|
}
|
|
1084
1142
|
else {
|
|
1143
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
1144
|
+
this.setPitch(activeNote, semitoneOffset);
|
|
1085
1145
|
this.startModulation(channel, activeNote, now);
|
|
1086
1146
|
}
|
|
1087
1147
|
});
|
|
1088
1148
|
}
|
|
1089
|
-
|
|
1149
|
+
setModulationDepth(channelNumber, modulation) {
|
|
1090
1150
|
const channel = this.channels[channelNumber];
|
|
1091
|
-
channel.
|
|
1151
|
+
channel.modulationDepth = (modulation / 127) * channel.modulationDepthRange;
|
|
1092
1152
|
this.updateModulation(channel);
|
|
1093
1153
|
}
|
|
1094
1154
|
setPortamentoTime(channelNumber, portamentoTime) {
|
|
@@ -1298,47 +1358,23 @@ export class MidyGM2 {
|
|
|
1298
1358
|
handleModulationDepthRangeRPN(channelNumber) {
|
|
1299
1359
|
const channel = this.channels[channelNumber];
|
|
1300
1360
|
this.limitData(channel, 0, 127, 0, 127);
|
|
1301
|
-
const modulationDepthRange = dataMSB + dataLSB / 128;
|
|
1361
|
+
const modulationDepthRange = (dataMSB + dataLSB / 128) * 100;
|
|
1302
1362
|
this.setModulationDepthRange(channelNumber, modulationDepthRange);
|
|
1303
1363
|
}
|
|
1304
1364
|
setModulationDepthRange(channelNumber, modulationDepthRange) {
|
|
1305
1365
|
const channel = this.channels[channelNumber];
|
|
1306
1366
|
channel.modulationDepthRange = modulationDepthRange;
|
|
1307
|
-
channel.
|
|
1367
|
+
channel.modulationDepth = (modulation / 127) * modulationDepthRange;
|
|
1308
1368
|
this.updateModulation(channel);
|
|
1309
1369
|
}
|
|
1310
1370
|
allSoundOff(channelNumber) {
|
|
1311
|
-
|
|
1312
|
-
const channel = this.channels[channelNumber];
|
|
1313
|
-
const velocity = 0;
|
|
1314
|
-
const stopPedal = true;
|
|
1315
|
-
const promises = [];
|
|
1316
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
1317
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
1318
|
-
if (activeNote) {
|
|
1319
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
|
|
1320
|
-
promises.push(notePromise);
|
|
1321
|
-
}
|
|
1322
|
-
});
|
|
1323
|
-
return promises;
|
|
1371
|
+
return this.stopChannelNotes(channelNumber, 0, true);
|
|
1324
1372
|
}
|
|
1325
1373
|
resetAllControllers(channelNumber) {
|
|
1326
1374
|
Object.assign(this.channels[channelNumber], this.effectSettings);
|
|
1327
1375
|
}
|
|
1328
1376
|
allNotesOff(channelNumber) {
|
|
1329
|
-
|
|
1330
|
-
const channel = this.channels[channelNumber];
|
|
1331
|
-
const velocity = 0;
|
|
1332
|
-
const stopPedal = false;
|
|
1333
|
-
const promises = [];
|
|
1334
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
1335
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
1336
|
-
if (activeNote) {
|
|
1337
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
|
|
1338
|
-
promises.push(notePromise);
|
|
1339
|
-
}
|
|
1340
|
-
});
|
|
1341
|
-
return promises;
|
|
1377
|
+
return this.stopChannelNotes(channelNumber, 0, false);
|
|
1342
1378
|
}
|
|
1343
1379
|
omniOff() {
|
|
1344
1380
|
this.omni = false;
|
|
@@ -1698,6 +1734,9 @@ Object.defineProperty(MidyGM2, "channelSettings", {
|
|
|
1698
1734
|
portamentoTime: 0,
|
|
1699
1735
|
reverbSendLevel: 0,
|
|
1700
1736
|
chorusSendLevel: 0,
|
|
1737
|
+
vibratoRate: 1,
|
|
1738
|
+
vibratoDepth: 1,
|
|
1739
|
+
vibratoDelay: 1,
|
|
1701
1740
|
bank: 121 * 128,
|
|
1702
1741
|
bankMSB: 121,
|
|
1703
1742
|
bankLSB: 0,
|
|
@@ -1707,7 +1746,7 @@ Object.defineProperty(MidyGM2, "channelSettings", {
|
|
|
1707
1746
|
pitchBend: 0,
|
|
1708
1747
|
fineTuning: 0, // cb
|
|
1709
1748
|
coarseTuning: 0, // cb
|
|
1710
|
-
modulationDepthRange:
|
|
1749
|
+
modulationDepthRange: 50, // cent
|
|
1711
1750
|
}
|
|
1712
1751
|
});
|
|
1713
1752
|
Object.defineProperty(MidyGM2, "effectSettings", {
|
|
@@ -1716,7 +1755,7 @@ Object.defineProperty(MidyGM2, "effectSettings", {
|
|
|
1716
1755
|
writable: true,
|
|
1717
1756
|
value: {
|
|
1718
1757
|
expression: 1,
|
|
1719
|
-
|
|
1758
|
+
modulationDepth: 0,
|
|
1720
1759
|
sustainPedal: false,
|
|
1721
1760
|
portamento: false,
|
|
1722
1761
|
sostenutoPedal: false,
|
package/esm/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;
|
package/esm/midy-GMLite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"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"}
|