@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.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,
|
|
@@ -410,7 +416,7 @@ export class Midy {
|
|
|
410
416
|
const t = this.audioContext.currentTime + offset;
|
|
411
417
|
queueIndex = await this.scheduleTimelineEvents(t, offset, queueIndex);
|
|
412
418
|
if (this.isPausing) {
|
|
413
|
-
await this.stopNotes();
|
|
419
|
+
await this.stopNotes(0, true);
|
|
414
420
|
this.notePromises = [];
|
|
415
421
|
resolve();
|
|
416
422
|
this.isPausing = false;
|
|
@@ -418,7 +424,7 @@ export class Midy {
|
|
|
418
424
|
return;
|
|
419
425
|
}
|
|
420
426
|
else if (this.isStopping) {
|
|
421
|
-
await this.stopNotes();
|
|
427
|
+
await this.stopNotes(0, true);
|
|
422
428
|
this.notePromises = [];
|
|
423
429
|
resolve();
|
|
424
430
|
this.isStopping = false;
|
|
@@ -426,7 +432,7 @@ export class Midy {
|
|
|
426
432
|
return;
|
|
427
433
|
}
|
|
428
434
|
else if (this.isSeeking) {
|
|
429
|
-
this.stopNotes();
|
|
435
|
+
this.stopNotes(0, true);
|
|
430
436
|
this.startTime = this.audioContext.currentTime;
|
|
431
437
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
432
438
|
offset = this.resumeTime - this.startTime;
|
|
@@ -541,21 +547,24 @@ export class Midy {
|
|
|
541
547
|
}
|
|
542
548
|
return { instruments, timeline };
|
|
543
549
|
}
|
|
544
|
-
|
|
550
|
+
async stopChannelNotes(channelNumber, velocity, stopPedal) {
|
|
545
551
|
const now = this.audioContext.currentTime;
|
|
546
|
-
const
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
this.notePromises.push(promise);
|
|
554
|
-
}
|
|
555
|
-
});
|
|
552
|
+
const channel = this.channels[channelNumber];
|
|
553
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
554
|
+
noteList.forEach((note) => {
|
|
555
|
+
if (note) {
|
|
556
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
|
|
557
|
+
this.notePromises.push(promise);
|
|
558
|
+
}
|
|
556
559
|
});
|
|
557
|
-
channel.scheduledNotes.clear();
|
|
558
560
|
});
|
|
561
|
+
channel.scheduledNotes.clear();
|
|
562
|
+
await Promise.all(this.notePromises);
|
|
563
|
+
}
|
|
564
|
+
stopNotes(velocity, stopPedal) {
|
|
565
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
566
|
+
this.stopChannelNotes(i, velocity, stopPedal);
|
|
567
|
+
}
|
|
559
568
|
return Promise.all(this.notePromises);
|
|
560
569
|
}
|
|
561
570
|
async start() {
|
|
@@ -770,36 +779,54 @@ export class Midy {
|
|
|
770
779
|
}
|
|
771
780
|
setVolumeEnvelope(note) {
|
|
772
781
|
const { instrumentKey, startTime } = note;
|
|
773
|
-
note.
|
|
782
|
+
note.volumeNode = new GainNode(this.audioContext, { gain: 0 });
|
|
774
783
|
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
775
784
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
776
785
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
777
786
|
const volAttack = volDelay + instrumentKey.volAttack;
|
|
778
787
|
const volHold = volAttack + instrumentKey.volHold;
|
|
779
788
|
const volDecay = volHold + instrumentKey.volDecay;
|
|
780
|
-
note.
|
|
789
|
+
note.volumeNode.gain
|
|
781
790
|
.setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
|
|
782
791
|
.exponentialRampToValueAtTime(attackVolume, volAttack)
|
|
783
792
|
.setValueAtTime(attackVolume, volHold)
|
|
784
793
|
.linearRampToValueAtTime(sustainVolume, volDecay);
|
|
785
794
|
}
|
|
786
|
-
|
|
787
|
-
const { instrumentKey,
|
|
795
|
+
setPitch(note, semitoneOffset) {
|
|
796
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
797
|
+
const modEnvToPitch = instrumentKey.modEnvToPitch / 100;
|
|
798
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
799
|
+
if (modEnvToPitch === 0)
|
|
800
|
+
return;
|
|
801
|
+
const basePitch = note.bufferSource.playbackRate.value;
|
|
802
|
+
const peekPitch = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset + modEnvToPitch);
|
|
803
|
+
const modDelay = startTime + instrumentKey.modDelay;
|
|
804
|
+
const modAttack = modDelay + instrumentKey.modAttack;
|
|
805
|
+
const modHold = modAttack + instrumentKey.modHold;
|
|
806
|
+
const modDecay = modHold + instrumentKey.modDecay;
|
|
807
|
+
note.bufferSource.playbackRate.value
|
|
808
|
+
.setValueAtTime(basePitch, modDelay)
|
|
809
|
+
.exponentialRampToValueAtTime(peekPitch, modAttack)
|
|
810
|
+
.setValueAtTime(peekPitch, modHold)
|
|
811
|
+
.linearRampToValueAtTime(basePitch, modDecay);
|
|
812
|
+
}
|
|
813
|
+
setFilterNode(channel, note) {
|
|
814
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
788
815
|
const softPedalFactor = 1 -
|
|
789
816
|
(0.1 + (noteNumber / 127) * 0.2) * channel.softPedal;
|
|
790
817
|
const maxFreq = this.audioContext.sampleRate / 2;
|
|
791
818
|
const baseFreq = this.centToHz(instrumentKey.initialFilterFc) *
|
|
792
819
|
softPedalFactor;
|
|
793
820
|
const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc) * softPedalFactor;
|
|
794
|
-
const sustainFreq =
|
|
795
|
-
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain)
|
|
821
|
+
const sustainFreq = baseFreq +
|
|
822
|
+
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
|
|
823
|
+
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
824
|
+
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
825
|
+
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
796
826
|
const modDelay = startTime + instrumentKey.modDelay;
|
|
797
827
|
const modAttack = modDelay + instrumentKey.modAttack;
|
|
798
828
|
const modHold = modAttack + instrumentKey.modHold;
|
|
799
829
|
const modDecay = modHold + instrumentKey.modDecay;
|
|
800
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
801
|
-
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
802
|
-
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
803
830
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
804
831
|
type: "lowpass",
|
|
805
832
|
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
@@ -810,56 +837,72 @@ export class Midy {
|
|
|
810
837
|
.exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
|
|
811
838
|
.setValueAtTime(adjustedPeekFreq, modHold)
|
|
812
839
|
.linearRampToValueAtTime(adjustedSustainFreq, modDecay);
|
|
813
|
-
note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modEnvToPitch, modDelay);
|
|
814
840
|
}
|
|
815
|
-
startModulation(channel, note,
|
|
841
|
+
startModulation(channel, note, startTime) {
|
|
816
842
|
const { instrumentKey } = note;
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
});
|
|
820
|
-
note.modLFO = new OscillatorNode(this.audioContext, {
|
|
843
|
+
const { modLfoToPitch, modLfoToVolume } = instrumentKey;
|
|
844
|
+
note.modulationLFO = new OscillatorNode(this.audioContext, {
|
|
821
845
|
frequency: this.centToHz(instrumentKey.freqModLFO),
|
|
822
846
|
});
|
|
823
|
-
note.
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
847
|
+
note.filterDepth = new GainNode(this.audioContext, {
|
|
848
|
+
gain: instrumentKey.modLfoToFilterFc,
|
|
849
|
+
});
|
|
850
|
+
const modulationDepth = Math.abs(modLfoToPitch) + channel.modulationDepth;
|
|
851
|
+
const modulationDepthSign = (0 < modLfoToPitch) ? 1 : -1;
|
|
852
|
+
note.modulationDepth = new GainNode(this.audioContext, {
|
|
853
|
+
gain: modulationDepth * modulationDepthSign,
|
|
854
|
+
});
|
|
855
|
+
const volumeDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
|
|
856
|
+
const volumeDepthSign = (0 < modLfoToVolume) ? 1 : -1;
|
|
857
|
+
note.volumeDepth = new GainNode(this.audioContext, {
|
|
858
|
+
gain: volumeDepth * volumeDepthSign,
|
|
833
859
|
});
|
|
834
|
-
note.
|
|
835
|
-
|
|
860
|
+
note.modulationLFO.start(startTime + instrumentKey.delayModLFO);
|
|
861
|
+
note.modulationLFO.connect(note.filterDepth);
|
|
862
|
+
note.filterDepth.connect(note.filterNode.frequency);
|
|
863
|
+
note.modulationLFO.connect(note.modulationDepth);
|
|
864
|
+
note.modulationDepth.connect(note.bufferSource.detune);
|
|
865
|
+
note.modulationLFO.connect(note.volumeDepth);
|
|
866
|
+
note.volumeDepth.connect(note.volumeNode.gain);
|
|
867
|
+
}
|
|
868
|
+
startVibrato(channel, note, startTime) {
|
|
869
|
+
const { instrumentKey } = note;
|
|
870
|
+
const { vibLfoToPitch } = instrumentKey;
|
|
871
|
+
note.vibratoLFO = new OscillatorNode(this.audioContext, {
|
|
872
|
+
frequency: this.centToHz(instrumentKey.freqVibLFO) *
|
|
836
873
|
channel.vibratoRate,
|
|
837
874
|
});
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
note.
|
|
875
|
+
const vibratoDepth = Math.abs(vibLfoToPitch) * channel.vibratoDepth;
|
|
876
|
+
const vibratoDepthSign = 0 < vibLfoToPitch;
|
|
877
|
+
note.vibratoDepth = new GainNode(this.audioContext, {
|
|
878
|
+
gain: vibratoDepth * vibratoDepthSign,
|
|
879
|
+
});
|
|
880
|
+
note.vibratoLFO.start(startTime + instrumentKey.delayVibLFO * channel.vibratoDelay);
|
|
881
|
+
note.vibratoLFO.connect(note.vibratoDepth);
|
|
882
|
+
note.vibratoDepth.connect(note.bufferSource.detune);
|
|
841
883
|
}
|
|
842
884
|
async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
|
|
843
885
|
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
844
886
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
845
887
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
846
|
-
|
|
888
|
+
this.setFilterNode(channel, note);
|
|
847
889
|
this.setVolumeEnvelope(note);
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
const delayModLFO = startTime + instrumentKey.delayModLFO;
|
|
851
|
-
this.startModulation(channel, note, delayModLFO);
|
|
890
|
+
if (0 < channel.vibratoDepth) {
|
|
891
|
+
this.startVibrato(channel, note, startTime);
|
|
852
892
|
}
|
|
853
|
-
if (channel.
|
|
854
|
-
|
|
855
|
-
this.
|
|
893
|
+
if (0 < channel.modulationDepth) {
|
|
894
|
+
this.setPitch(note, semitoneOffset);
|
|
895
|
+
this.startModulation(channel, note, startTime);
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
856
899
|
}
|
|
857
900
|
if (this.mono && channel.currentBufferSource) {
|
|
858
901
|
channel.currentBufferSource.stop(startTime);
|
|
859
902
|
channel.currentBufferSource = note.bufferSource;
|
|
860
903
|
}
|
|
861
904
|
note.bufferSource.connect(note.filterNode);
|
|
862
|
-
note.filterNode.connect(note.
|
|
905
|
+
note.filterNode.connect(note.volumeNode);
|
|
863
906
|
note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
|
|
864
907
|
return note;
|
|
865
908
|
}
|
|
@@ -884,8 +927,8 @@ export class Midy {
|
|
|
884
927
|
if (!instrumentKey)
|
|
885
928
|
return;
|
|
886
929
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
887
|
-
note.
|
|
888
|
-
note.
|
|
930
|
+
note.volumeNode.connect(channel.gainL);
|
|
931
|
+
note.volumeNode.connect(channel.gainR);
|
|
889
932
|
if (channel.sostenutoPedal) {
|
|
890
933
|
channel.sostenutoNotes.set(noteNumber, note);
|
|
891
934
|
}
|
|
@@ -919,17 +962,14 @@ export class Midy {
|
|
|
919
962
|
const velocityRate = (velocity + 127) / 127;
|
|
920
963
|
const volEndTime = stopTime +
|
|
921
964
|
note.instrumentKey.volRelease * velocityRate;
|
|
922
|
-
note.
|
|
965
|
+
note.volumeNode.gain
|
|
923
966
|
.cancelScheduledValues(stopTime)
|
|
924
967
|
.linearRampToValueAtTime(0, volEndTime);
|
|
925
|
-
const
|
|
926
|
-
const baseFreq = this.centToHz(note.instrumentKey.initialFilterFc);
|
|
927
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
928
|
-
const modEndTime = stopTime +
|
|
968
|
+
const modRelease = stopTime +
|
|
929
969
|
note.instrumentKey.modRelease * velocityRate;
|
|
930
970
|
note.filterNode.frequency
|
|
931
971
|
.cancelScheduledValues(stopTime)
|
|
932
|
-
.linearRampToValueAtTime(
|
|
972
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
933
973
|
note.ending = true;
|
|
934
974
|
this.scheduleTask(() => {
|
|
935
975
|
note.bufferSource.loop = false;
|
|
@@ -938,16 +978,18 @@ export class Midy {
|
|
|
938
978
|
note.bufferSource.onended = () => {
|
|
939
979
|
scheduledNotes[i] = null;
|
|
940
980
|
note.bufferSource.disconnect();
|
|
981
|
+
note.volumeNode.disconnect();
|
|
941
982
|
note.filterNode.disconnect();
|
|
942
|
-
note.
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
983
|
+
if (note.volumeDepth)
|
|
984
|
+
note.volumeDepth.disconnect();
|
|
985
|
+
if (note.modulationDepth)
|
|
986
|
+
note.modulationDepth.disconnect();
|
|
987
|
+
if (note.modulationLFO)
|
|
988
|
+
note.modulationLFO.stop();
|
|
989
|
+
if (note.vibratoDepth)
|
|
990
|
+
note.vibratoDepth.disconnect();
|
|
991
|
+
if (note.vibratoLFO)
|
|
992
|
+
note.vibratoLFO.stop();
|
|
951
993
|
resolve();
|
|
952
994
|
};
|
|
953
995
|
note.bufferSource.stop(volEndTime);
|
|
@@ -963,10 +1005,10 @@ export class Midy {
|
|
|
963
1005
|
const channel = this.channels[channelNumber];
|
|
964
1006
|
const promises = [];
|
|
965
1007
|
channel.sustainPedal = false;
|
|
966
|
-
channel.scheduledNotes.forEach((
|
|
967
|
-
|
|
968
|
-
if (
|
|
969
|
-
const { noteNumber } =
|
|
1008
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1009
|
+
noteList.forEach((note) => {
|
|
1010
|
+
if (note) {
|
|
1011
|
+
const { noteNumber } = note;
|
|
970
1012
|
const promise = this.releaseNote(channelNumber, noteNumber, velocity);
|
|
971
1013
|
promises.push(promise);
|
|
972
1014
|
}
|
|
@@ -1017,8 +1059,8 @@ export class Midy {
|
|
|
1017
1059
|
if (channel.polyphonicKeyPressure.amplitudeControl !== 1) {
|
|
1018
1060
|
if (activeNotes.has(noteNumber)) {
|
|
1019
1061
|
const activeNote = activeNotes.get(noteNumber);
|
|
1020
|
-
const gain = activeNote.
|
|
1021
|
-
activeNote.
|
|
1062
|
+
const gain = activeNote.volumeNode.gain.value;
|
|
1063
|
+
activeNote.volumeNode.gain
|
|
1022
1064
|
.cancelScheduledValues(now)
|
|
1023
1065
|
.setValueAtTime(gain * pressure, now);
|
|
1024
1066
|
}
|
|
@@ -1037,8 +1079,8 @@ export class Midy {
|
|
|
1037
1079
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1038
1080
|
if (channel.channelPressure.amplitudeControl !== 1) {
|
|
1039
1081
|
activeNotes.forEach((activeNote) => {
|
|
1040
|
-
const gain = activeNote.
|
|
1041
|
-
activeNote.
|
|
1082
|
+
const gain = activeNote.volumeNode.gain.value;
|
|
1083
|
+
activeNote.volumeNode.gain
|
|
1042
1084
|
.cancelScheduledValues(now)
|
|
1043
1085
|
.setValueAtTime(gain * pressure, now);
|
|
1044
1086
|
});
|
|
@@ -1061,7 +1103,7 @@ export class Midy {
|
|
|
1061
1103
|
case 0:
|
|
1062
1104
|
return this.setBankMSB(channelNumber, value);
|
|
1063
1105
|
case 1:
|
|
1064
|
-
return this.
|
|
1106
|
+
return this.setModulationDepth(channelNumber, value);
|
|
1065
1107
|
case 5:
|
|
1066
1108
|
return this.setPortamentoTime(channelNumber, value);
|
|
1067
1109
|
case 6:
|
|
@@ -1128,18 +1170,19 @@ export class Midy {
|
|
|
1128
1170
|
const now = this.audioContext.currentTime;
|
|
1129
1171
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1130
1172
|
activeNotes.forEach((activeNote) => {
|
|
1131
|
-
if (activeNote.
|
|
1132
|
-
|
|
1133
|
-
gainNode.gain.setValueAtTime(this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation), now);
|
|
1173
|
+
if (activeNote.modulationDepth) {
|
|
1174
|
+
activeNote.modulationDepth.gain.setValueAtTime(channel.modulationDepth, now);
|
|
1134
1175
|
}
|
|
1135
1176
|
else {
|
|
1177
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
1178
|
+
this.setPitch(activeNote, semitoneOffset);
|
|
1136
1179
|
this.startModulation(channel, activeNote, now);
|
|
1137
1180
|
}
|
|
1138
1181
|
});
|
|
1139
1182
|
}
|
|
1140
|
-
|
|
1183
|
+
setModulationDepth(channelNumber, modulation) {
|
|
1141
1184
|
const channel = this.channels[channelNumber];
|
|
1142
|
-
channel.
|
|
1185
|
+
channel.modulationDepth = (modulation / 127) * channel.modulationDepthRange;
|
|
1143
1186
|
this.updateModulation(channel);
|
|
1144
1187
|
}
|
|
1145
1188
|
setPortamentoTime(channelNumber, portamentoTime) {
|
|
@@ -1241,21 +1284,15 @@ export class Midy {
|
|
|
1241
1284
|
}
|
|
1242
1285
|
setVibratoRate(channelNumber, vibratoRate) {
|
|
1243
1286
|
const channel = this.channels[channelNumber];
|
|
1244
|
-
channel.vibratoRate = vibratoRate /
|
|
1287
|
+
channel.vibratoRate = vibratoRate / 64;
|
|
1245
1288
|
}
|
|
1246
1289
|
setVibratoDepth(channelNumber, vibratoDepth) {
|
|
1247
1290
|
const channel = this.channels[channelNumber];
|
|
1248
|
-
channel.vibratoDepth = vibratoDepth /
|
|
1291
|
+
channel.vibratoDepth = vibratoDepth / 64;
|
|
1249
1292
|
}
|
|
1250
1293
|
setVibratoDelay(channelNumber, vibratoDelay) {
|
|
1251
|
-
// Access Virus: 0-10sec
|
|
1252
|
-
// Elektron: 0-5sec
|
|
1253
|
-
// Korg: 0-5sec
|
|
1254
|
-
// Nord: 0-5sec
|
|
1255
|
-
// Roland: 0-5sec
|
|
1256
|
-
// Yamaha: 0-8sec
|
|
1257
1294
|
const channel = this.channels[channelNumber];
|
|
1258
|
-
channel.vibratoDelay = vibratoDelay /
|
|
1295
|
+
channel.vibratoDelay = vibratoDelay / 64;
|
|
1259
1296
|
}
|
|
1260
1297
|
limitData(channel, minMSB, maxMSB, minLSB, maxLSB) {
|
|
1261
1298
|
if (maxLSB < channel.dataLSB) {
|
|
@@ -1377,47 +1414,23 @@ export class Midy {
|
|
|
1377
1414
|
handleModulationDepthRangeRPN(channelNumber) {
|
|
1378
1415
|
const channel = this.channels[channelNumber];
|
|
1379
1416
|
this.limitData(channel, 0, 127, 0, 127);
|
|
1380
|
-
const modulationDepthRange = dataMSB + dataLSB / 128;
|
|
1417
|
+
const modulationDepthRange = (dataMSB + dataLSB / 128) * 100;
|
|
1381
1418
|
this.setModulationDepthRange(channelNumber, modulationDepthRange);
|
|
1382
1419
|
}
|
|
1383
1420
|
setModulationDepthRange(channelNumber, modulationDepthRange) {
|
|
1384
1421
|
const channel = this.channels[channelNumber];
|
|
1385
1422
|
channel.modulationDepthRange = modulationDepthRange;
|
|
1386
|
-
channel.
|
|
1423
|
+
channel.modulationDepth = (modulation / 127) * modulationDepthRange;
|
|
1387
1424
|
this.updateModulation(channel);
|
|
1388
1425
|
}
|
|
1389
1426
|
allSoundOff(channelNumber) {
|
|
1390
|
-
|
|
1391
|
-
const channel = this.channels[channelNumber];
|
|
1392
|
-
const velocity = 0;
|
|
1393
|
-
const stopPedal = true;
|
|
1394
|
-
const promises = [];
|
|
1395
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
1396
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
1397
|
-
if (activeNote) {
|
|
1398
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
|
|
1399
|
-
promises.push(notePromise);
|
|
1400
|
-
}
|
|
1401
|
-
});
|
|
1402
|
-
return promises;
|
|
1427
|
+
return this.stopChannelNotes(channelNumber, 0, true);
|
|
1403
1428
|
}
|
|
1404
1429
|
resetAllControllers(channelNumber) {
|
|
1405
1430
|
Object.assign(this.channels[channelNumber], this.effectSettings);
|
|
1406
1431
|
}
|
|
1407
1432
|
allNotesOff(channelNumber) {
|
|
1408
|
-
|
|
1409
|
-
const channel = this.channels[channelNumber];
|
|
1410
|
-
const velocity = 0;
|
|
1411
|
-
const stopPedal = false;
|
|
1412
|
-
const promises = [];
|
|
1413
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
1414
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
1415
|
-
if (activeNote) {
|
|
1416
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
|
|
1417
|
-
promises.push(notePromise);
|
|
1418
|
-
}
|
|
1419
|
-
});
|
|
1420
|
-
return promises;
|
|
1433
|
+
return this.stopChannelNotes(channelNumber, 0, false);
|
|
1421
1434
|
}
|
|
1422
1435
|
omniOff() {
|
|
1423
1436
|
this.omni = false;
|
|
@@ -1777,9 +1790,9 @@ Object.defineProperty(Midy, "channelSettings", {
|
|
|
1777
1790
|
portamentoTime: 0,
|
|
1778
1791
|
reverbSendLevel: 0,
|
|
1779
1792
|
chorusSendLevel: 0,
|
|
1780
|
-
vibratoRate:
|
|
1781
|
-
vibratoDepth:
|
|
1782
|
-
vibratoDelay:
|
|
1793
|
+
vibratoRate: 1,
|
|
1794
|
+
vibratoDepth: 1,
|
|
1795
|
+
vibratoDelay: 1,
|
|
1783
1796
|
bank: 121 * 128,
|
|
1784
1797
|
bankMSB: 121,
|
|
1785
1798
|
bankLSB: 0,
|
|
@@ -1789,7 +1802,7 @@ Object.defineProperty(Midy, "channelSettings", {
|
|
|
1789
1802
|
pitchBend: 0,
|
|
1790
1803
|
fineTuning: 0, // cb
|
|
1791
1804
|
coarseTuning: 0, // cb
|
|
1792
|
-
modulationDepthRange:
|
|
1805
|
+
modulationDepthRange: 50, // cent
|
|
1793
1806
|
}
|
|
1794
1807
|
});
|
|
1795
1808
|
Object.defineProperty(Midy, "effectSettings", {
|
|
@@ -1798,7 +1811,7 @@ Object.defineProperty(Midy, "effectSettings", {
|
|
|
1798
1811
|
writable: true,
|
|
1799
1812
|
value: {
|
|
1800
1813
|
expression: 1,
|
|
1801
|
-
|
|
1814
|
+
modulationDepth: 0,
|
|
1802
1815
|
sustainPedal: false,
|
|
1803
1816
|
portamento: false,
|
|
1804
1817
|
sostenutoPedal: false,
|