@marmooo/midy 0.1.0 → 0.1.2
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/midy-GM1.d.ts +1 -2
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +11 -17
- package/esm/midy-GM2.d.ts +29 -20
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +169 -104
- package/esm/midy-GMLite.d.ts +1 -2
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +11 -17
- package/esm/midy.d.ts +29 -20
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +169 -104
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +1 -2
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +11 -17
- package/script/midy-GM2.d.ts +29 -20
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +169 -104
- package/script/midy-GMLite.d.ts +1 -2
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +11 -17
- package/script/midy.d.ts +29 -20
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +169 -104
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":"AAuBA;
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}
|
package/script/midy-GM2.js
CHANGED
|
@@ -85,7 +85,7 @@ class MidyGM2 {
|
|
|
85
85
|
writable: true,
|
|
86
86
|
value: {
|
|
87
87
|
time: this.getReverbTime(64),
|
|
88
|
-
feedback: 0.
|
|
88
|
+
feedback: 0.8,
|
|
89
89
|
}
|
|
90
90
|
});
|
|
91
91
|
Object.defineProperty(this, "chorus", {
|
|
@@ -93,10 +93,11 @@ class MidyGM2 {
|
|
|
93
93
|
configurable: true,
|
|
94
94
|
writable: true,
|
|
95
95
|
value: {
|
|
96
|
-
modRate: 3
|
|
97
|
-
modDepth: (
|
|
98
|
-
feedback: 8
|
|
99
|
-
sendToReverb: 0
|
|
96
|
+
modRate: this.getChorusModRate(3),
|
|
97
|
+
modDepth: this.getChorusModDepth(19),
|
|
98
|
+
feedback: this.getChorusFeedback(8),
|
|
99
|
+
sendToReverb: this.getChorusSendToReverb(0),
|
|
100
|
+
delayTimes: this.generateDistributedArray(0.02, 2, 0.5),
|
|
100
101
|
}
|
|
101
102
|
});
|
|
102
103
|
Object.defineProperty(this, "mono", {
|
|
@@ -226,8 +227,12 @@ class MidyGM2 {
|
|
|
226
227
|
this.audioContext = audioContext;
|
|
227
228
|
this.options = { ...this.defaultOptions, ...options };
|
|
228
229
|
this.masterGain = new GainNode(audioContext);
|
|
229
|
-
this.masterGain.connect(audioContext.destination);
|
|
230
230
|
this.channels = this.createChannels(audioContext);
|
|
231
|
+
this.reverbEffect = this.options.reverbAlgorithm(audioContext);
|
|
232
|
+
this.chorusEffect = this.createChorusEffect(audioContext);
|
|
233
|
+
this.chorusEffect.output.connect(this.masterGain);
|
|
234
|
+
this.reverbEffect.output.connect(this.masterGain);
|
|
235
|
+
this.masterGain.connect(audioContext.destination);
|
|
231
236
|
this.GM2SystemOn();
|
|
232
237
|
}
|
|
233
238
|
initSoundFontTable() {
|
|
@@ -271,14 +276,11 @@ class MidyGM2 {
|
|
|
271
276
|
const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
|
|
272
277
|
gainL.connect(merger, 0, 0);
|
|
273
278
|
gainR.connect(merger, 0, 1);
|
|
274
|
-
|
|
275
|
-
const chorusEffect = this.createChorusEffect(audioContext);
|
|
279
|
+
merger.connect(this.masterGain);
|
|
276
280
|
return {
|
|
277
281
|
gainL,
|
|
278
282
|
gainR,
|
|
279
283
|
merger,
|
|
280
|
-
reverbEffect,
|
|
281
|
-
chorusEffect,
|
|
282
284
|
};
|
|
283
285
|
}
|
|
284
286
|
createChannels(audioContext) {
|
|
@@ -688,12 +690,10 @@ class MidyGM2 {
|
|
|
688
690
|
}
|
|
689
691
|
// https://hajim.rochester.edu/ece/sites/zduan/teaching/ece472/reading/Schroeder_1962.pdf
|
|
690
692
|
// M.R.Schroeder, "Natural Sounding Artificial Reverberation", J.Audio Eng. Soc., vol.10, p.219, 1962
|
|
691
|
-
createSchroederReverb(audioContext, combDelays,
|
|
693
|
+
createSchroederReverb(audioContext, combFeedbacks, combDelays, allpassFeedbacks, allpassDelays) {
|
|
692
694
|
const input = new GainNode(audioContext);
|
|
693
695
|
const output = new GainNode(audioContext);
|
|
694
|
-
const mergerGain = new GainNode(audioContext
|
|
695
|
-
gain: 1 / (combDelays.length * 2),
|
|
696
|
-
});
|
|
696
|
+
const mergerGain = new GainNode(audioContext);
|
|
697
697
|
for (let i = 0; i < combDelays.length; i++) {
|
|
698
698
|
const comb = this.createCombFilter(audioContext, input, combDelays[i], combFeedbacks[i]);
|
|
699
699
|
comb.connect(mergerGain);
|
|
@@ -706,62 +706,49 @@ class MidyGM2 {
|
|
|
706
706
|
allpasses.at(-1).connect(output);
|
|
707
707
|
return { input, output };
|
|
708
708
|
}
|
|
709
|
-
createChorusEffect(audioContext
|
|
710
|
-
const
|
|
711
|
-
const lfo = new OscillatorNode(audioContext, { frequency: chorusRate });
|
|
712
|
-
const lfoGain = new GainNode(audioContext, { gain: chorusDepth });
|
|
709
|
+
createChorusEffect(audioContext) {
|
|
710
|
+
const input = new GainNode(audioContext);
|
|
713
711
|
const output = new GainNode(audioContext);
|
|
714
|
-
const
|
|
712
|
+
const sendGain = new GainNode(audioContext);
|
|
713
|
+
const lfo = new OscillatorNode(audioContext, {
|
|
714
|
+
frequency: this.chorus.modRate,
|
|
715
|
+
});
|
|
716
|
+
const lfoGain = new GainNode(audioContext, {
|
|
717
|
+
gain: this.chorus.modDepth / 2,
|
|
718
|
+
});
|
|
719
|
+
const delayTimes = this.chorus.delayTimes;
|
|
715
720
|
const delayNodes = [];
|
|
716
|
-
const
|
|
717
|
-
for (let i = 0; i <
|
|
718
|
-
const
|
|
719
|
-
const delayTime = (i + 1) * delay + randomDelayFactor;
|
|
721
|
+
const feedbackGains = [];
|
|
722
|
+
for (let i = 0; i < delayTimes.length; i++) {
|
|
723
|
+
const delayTime = delayTimes[i];
|
|
720
724
|
const delayNode = new DelayNode(audioContext, {
|
|
721
|
-
maxDelayTime: delayTime
|
|
725
|
+
maxDelayTime: 0.1, // generally, 5ms < delayTime < 50ms
|
|
726
|
+
delayTime,
|
|
727
|
+
});
|
|
728
|
+
const feedbackGain = new GainNode(audioContext, {
|
|
729
|
+
gain: this.chorus.feedback,
|
|
722
730
|
});
|
|
723
|
-
const chorusGain = new GainNode(audioContext, { gain: baseGain });
|
|
724
731
|
delayNodes.push(delayNode);
|
|
725
|
-
|
|
732
|
+
feedbackGains.push(feedbackGain);
|
|
733
|
+
input.connect(delayNode);
|
|
726
734
|
lfoGain.connect(delayNode.delayTime);
|
|
727
|
-
delayNode.connect(
|
|
728
|
-
|
|
735
|
+
delayNode.connect(feedbackGain);
|
|
736
|
+
feedbackGain.connect(delayNode);
|
|
737
|
+
delayNode.connect(output);
|
|
729
738
|
}
|
|
739
|
+
output.connect(sendGain);
|
|
730
740
|
lfo.connect(lfoGain);
|
|
731
741
|
lfo.start();
|
|
732
742
|
return {
|
|
743
|
+
input,
|
|
744
|
+
output,
|
|
745
|
+
sendGain,
|
|
733
746
|
lfo,
|
|
734
747
|
lfoGain,
|
|
735
748
|
delayNodes,
|
|
736
|
-
|
|
737
|
-
output,
|
|
749
|
+
feedbackGains,
|
|
738
750
|
};
|
|
739
751
|
}
|
|
740
|
-
connectEffects(channel, gainNode) {
|
|
741
|
-
gainNode.connect(channel.merger);
|
|
742
|
-
channel.merger.connect(this.masterGain);
|
|
743
|
-
if (channel.reverbSendLevel === 0) {
|
|
744
|
-
if (channel.chorusSendLevel !== 0) { // chorus
|
|
745
|
-
channel.chorusEffect.delayNodes.forEach((delayNode) => {
|
|
746
|
-
channel.merger.connect(delayNode);
|
|
747
|
-
});
|
|
748
|
-
channel.chorusEffect.output.connect(this.masterGain);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
else {
|
|
752
|
-
if (channel.chorusSendLevel === 0) { // reverb
|
|
753
|
-
channel.merger.connect(channel.reverbEffect.input);
|
|
754
|
-
channel.reverbEffect.output.connect(this.masterGain);
|
|
755
|
-
}
|
|
756
|
-
else { // reverb + chorus
|
|
757
|
-
channel.chorusEffect.delayNodes.forEach((delayNode) => {
|
|
758
|
-
channel.merger.connect(delayNode);
|
|
759
|
-
});
|
|
760
|
-
channel.merger.connect(channel.reverbEffect.input);
|
|
761
|
-
channel.reverbEffect.output.connect(this.masterGain);
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
752
|
cbToRatio(cb) {
|
|
766
753
|
return Math.pow(10, cb / 200);
|
|
767
754
|
}
|
|
@@ -778,14 +765,10 @@ class MidyGM2 {
|
|
|
778
765
|
return instrumentKey.playbackRate(noteNumber) *
|
|
779
766
|
Math.pow(2, semitoneOffset / 12);
|
|
780
767
|
}
|
|
781
|
-
setVolumeEnvelope(
|
|
782
|
-
const { instrumentKey, startTime
|
|
768
|
+
setVolumeEnvelope(note) {
|
|
769
|
+
const { instrumentKey, startTime } = note;
|
|
783
770
|
note.gainNode = new GainNode(this.audioContext, { gain: 0 });
|
|
784
|
-
|
|
785
|
-
if (volume === 0)
|
|
786
|
-
volume = 1e-6; // exponentialRampToValueAtTime() requires a non-zero value
|
|
787
|
-
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation) *
|
|
788
|
-
volume;
|
|
771
|
+
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
789
772
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
790
773
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
791
774
|
const volAttack = volDelay + instrumentKey.volAttack;
|
|
@@ -845,7 +828,7 @@ class MidyGM2 {
|
|
|
845
828
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
846
829
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
847
830
|
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
848
|
-
this.setVolumeEnvelope(
|
|
831
|
+
this.setVolumeEnvelope(note);
|
|
849
832
|
this.setFilterEnvelope(channel, note);
|
|
850
833
|
if (channel.modulation > 0) {
|
|
851
834
|
const delayModLFO = startTime + instrumentKey.delayModLFO;
|
|
@@ -881,7 +864,8 @@ class MidyGM2 {
|
|
|
881
864
|
if (!instrumentKey)
|
|
882
865
|
return;
|
|
883
866
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
884
|
-
|
|
867
|
+
note.gainNode.connect(channel.gainL);
|
|
868
|
+
note.gainNode.connect(channel.gainR);
|
|
885
869
|
if (channel.sostenutoPedal) {
|
|
886
870
|
channel.sostenutoNotes.set(noteNumber, note);
|
|
887
871
|
}
|
|
@@ -1024,13 +1008,13 @@ class MidyGM2 {
|
|
|
1024
1008
|
}
|
|
1025
1009
|
}
|
|
1026
1010
|
handlePitchBendMessage(channelNumber, lsb, msb) {
|
|
1027
|
-
const pitchBend = msb * 128 + lsb;
|
|
1011
|
+
const pitchBend = msb * 128 + lsb - 8192;
|
|
1028
1012
|
this.setPitchBend(channelNumber, pitchBend);
|
|
1029
1013
|
}
|
|
1030
1014
|
setPitchBend(channelNumber, pitchBend) {
|
|
1031
1015
|
const channel = this.channels[channelNumber];
|
|
1032
1016
|
const prevPitchBend = channel.pitchBend;
|
|
1033
|
-
channel.pitchBend =
|
|
1017
|
+
channel.pitchBend = pitchBend / 8192;
|
|
1034
1018
|
const detuneChange = (channel.pitchBend - prevPitchBend) *
|
|
1035
1019
|
channel.pitchBendRange * 100;
|
|
1036
1020
|
this.updateDetune(channel, detuneChange);
|
|
@@ -1165,17 +1149,30 @@ class MidyGM2 {
|
|
|
1165
1149
|
this.channels[channelNumber].portamento = value >= 64;
|
|
1166
1150
|
}
|
|
1167
1151
|
setReverbSendLevel(channelNumber, reverbSendLevel) {
|
|
1168
|
-
const now = this.audioContext.currentTime;
|
|
1169
1152
|
const channel = this.channels[channelNumber];
|
|
1170
|
-
const reverbEffect =
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1153
|
+
const reverbEffect = this.reverbEffect;
|
|
1154
|
+
if (0 < reverbSendLevel) {
|
|
1155
|
+
const now = this.audioContext.currentTime;
|
|
1156
|
+
channel.reverbSendLevel = reverbSendLevel / 127;
|
|
1157
|
+
reverbEffect.output.gain.cancelScheduledValues(now);
|
|
1158
|
+
reverbEffect.output.gain.setValueAtTime(channel.reverbSendLevel, now);
|
|
1159
|
+
}
|
|
1160
|
+
else if (channel.reverbSendLevel !== 0) {
|
|
1161
|
+
channel.merger.disconnect(reverbEffect.input);
|
|
1162
|
+
}
|
|
1174
1163
|
}
|
|
1175
1164
|
setChorusSendLevel(channelNumber, chorusSendLevel) {
|
|
1176
1165
|
const channel = this.channels[channelNumber];
|
|
1177
|
-
|
|
1178
|
-
|
|
1166
|
+
const chorusEffect = this.chorusEffect;
|
|
1167
|
+
if (0 < chorusSendLevel) {
|
|
1168
|
+
const now = this.audioContext.currentTime;
|
|
1169
|
+
channel.chorusSendLevel = chorusSendLevel / 127;
|
|
1170
|
+
chorusEffect.output.gain.cancelScheduledValues(now);
|
|
1171
|
+
chorusEffect.output.gain.setValueAtTime(channel.chorusSendLevel, now);
|
|
1172
|
+
}
|
|
1173
|
+
else if (channel.chorusSendLevel !== 0) {
|
|
1174
|
+
channel.merger.disconnect(chorusEffect.input);
|
|
1175
|
+
}
|
|
1179
1176
|
}
|
|
1180
1177
|
setSostenutoPedal(channelNumber, value) {
|
|
1181
1178
|
const isOn = value >= 64;
|
|
@@ -1340,7 +1337,7 @@ class MidyGM2 {
|
|
|
1340
1337
|
channel.scheduledNotes.forEach((noteList) => {
|
|
1341
1338
|
const activeNote = this.getActiveNote(noteList, now);
|
|
1342
1339
|
if (activeNote) {
|
|
1343
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
|
|
1340
|
+
const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
|
|
1344
1341
|
promises.push(notePromise);
|
|
1345
1342
|
}
|
|
1346
1343
|
});
|
|
@@ -1407,7 +1404,7 @@ class MidyGM2 {
|
|
|
1407
1404
|
case 4: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
|
|
1408
1405
|
return this.handleMasterCoarseTuningSysEx(data);
|
|
1409
1406
|
case 5:
|
|
1410
|
-
return this.
|
|
1407
|
+
return this.handleGlobalParameterControlSysEx(data);
|
|
1411
1408
|
default:
|
|
1412
1409
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1413
1410
|
}
|
|
@@ -1484,13 +1481,13 @@ class MidyGM2 {
|
|
|
1484
1481
|
this.masterCoarseTuning = coarseTuning - 64;
|
|
1485
1482
|
}
|
|
1486
1483
|
}
|
|
1487
|
-
|
|
1488
|
-
if (data[
|
|
1489
|
-
switch (data[
|
|
1484
|
+
handleGlobalParameterControlSysEx(data) {
|
|
1485
|
+
if (data[7] === 1) {
|
|
1486
|
+
switch (data[8]) {
|
|
1490
1487
|
case 1:
|
|
1491
|
-
return this.
|
|
1488
|
+
return this.handleReverbParameterSysEx(data);
|
|
1492
1489
|
case 2:
|
|
1493
|
-
return this.
|
|
1490
|
+
return this.handleChorusParameterSysEx(data);
|
|
1494
1491
|
default:
|
|
1495
1492
|
console.warn(`Unsupported Global Parameter Control Message: ${data}`);
|
|
1496
1493
|
}
|
|
@@ -1499,21 +1496,19 @@ class MidyGM2 {
|
|
|
1499
1496
|
console.warn(`Unsupported Global Parameter Control Message: ${data}`);
|
|
1500
1497
|
}
|
|
1501
1498
|
}
|
|
1502
|
-
|
|
1503
|
-
switch (data[
|
|
1499
|
+
handleReverbParameterSysEx(data) {
|
|
1500
|
+
switch (data[9]) {
|
|
1504
1501
|
case 0:
|
|
1505
|
-
return this.setReverbType(data[
|
|
1502
|
+
return this.setReverbType(data[10]);
|
|
1506
1503
|
case 1:
|
|
1507
|
-
return this.setReverbTime(data[
|
|
1504
|
+
return this.setReverbTime(data[10]);
|
|
1508
1505
|
}
|
|
1509
1506
|
}
|
|
1510
1507
|
setReverbType(type) {
|
|
1511
1508
|
this.reverb.time = this.getReverbTimeFromType(type);
|
|
1512
|
-
this.reverb.feedback = (type === 8) ? 0.
|
|
1513
|
-
const { audioContext,
|
|
1514
|
-
|
|
1515
|
-
channels[i].reverbEffect = options.reverbAlgorithm(audioContext);
|
|
1516
|
-
}
|
|
1509
|
+
this.reverb.feedback = (type === 8) ? 0.9 : 0.8;
|
|
1510
|
+
const { audioContext, options } = this;
|
|
1511
|
+
this.reverbEffect = options.reverbAlgorithm(audioContext);
|
|
1517
1512
|
}
|
|
1518
1513
|
getReverbTimeFromType(type) {
|
|
1519
1514
|
switch (type) {
|
|
@@ -1564,41 +1559,111 @@ class MidyGM2 {
|
|
|
1564
1559
|
// RT60 = -3 * delay / Math.log10(feedback)
|
|
1565
1560
|
// feedback = Math.pow(10, -3 * delay / RT60)
|
|
1566
1561
|
// delay estimation using ideal feedback
|
|
1567
|
-
//
|
|
1568
|
-
//
|
|
1569
|
-
// It
|
|
1562
|
+
// The structure of a concert hall is complex,
|
|
1563
|
+
// so estimates based on mean free path are unstable.
|
|
1564
|
+
// It is easier to determine the delay based on ideal feedback.
|
|
1565
|
+
// The average sound absorption coefficient
|
|
1566
|
+
// suitable for playing musical instruments is 0.18 to 0.28.
|
|
1570
1567
|
// delay = -RT60 * Math.log10(feedback) / 3
|
|
1571
1568
|
calcDelay(rt60, feedback) {
|
|
1572
1569
|
return -rt60 * Math.log10(feedback) / 3;
|
|
1573
1570
|
}
|
|
1574
|
-
|
|
1575
|
-
switch (data[
|
|
1571
|
+
handleChorusParameterSysEx(data) {
|
|
1572
|
+
switch (data[9]) {
|
|
1576
1573
|
case 0:
|
|
1577
|
-
return this.setChorusType(data[
|
|
1574
|
+
return this.setChorusType(data[10]);
|
|
1578
1575
|
case 1:
|
|
1579
|
-
return this.setChorusModRate(data[
|
|
1576
|
+
return this.setChorusModRate(data[10]);
|
|
1580
1577
|
case 2:
|
|
1581
|
-
return this.setChorusModDepth(data[
|
|
1578
|
+
return this.setChorusModDepth(data[10]);
|
|
1582
1579
|
case 3:
|
|
1583
|
-
return this.setChorusFeedback(data[
|
|
1580
|
+
return this.setChorusFeedback(data[10]);
|
|
1584
1581
|
case 4:
|
|
1585
|
-
return this.setChorusSendToReverb(data[
|
|
1582
|
+
return this.setChorusSendToReverb(data[10]);
|
|
1586
1583
|
}
|
|
1587
1584
|
}
|
|
1588
1585
|
setChorusType(type) {
|
|
1589
|
-
|
|
1586
|
+
switch (type) {
|
|
1587
|
+
case 0:
|
|
1588
|
+
return this.setChorusParameter(3, 5, 0, 0);
|
|
1589
|
+
case 1:
|
|
1590
|
+
return this.setChorusParameter(9, 19, 5, 0);
|
|
1591
|
+
case 2:
|
|
1592
|
+
return this.setChorusParameter(3, 19, 8, 0);
|
|
1593
|
+
case 3:
|
|
1594
|
+
return this.setChorusParameter(9, 16, 16, 0);
|
|
1595
|
+
case 4:
|
|
1596
|
+
return this.setChorusParameter(2, 24, 64, 0);
|
|
1597
|
+
case 5:
|
|
1598
|
+
return this.setChorusParameter(1, 5, 112, 0);
|
|
1599
|
+
default:
|
|
1600
|
+
console.warn(`Unsupported Chorus Type: ${type}`);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
setChorusParameter(modRate, modDepth, feedback, sendToReverb) {
|
|
1604
|
+
this.setChorusModRate(modRate);
|
|
1605
|
+
this.setChorusModDepth(modDepth);
|
|
1606
|
+
this.setChorusFeedback(feedback);
|
|
1607
|
+
this.setChorusSendToReverb(sendToReverb);
|
|
1590
1608
|
}
|
|
1591
1609
|
setChorusModRate(value) {
|
|
1592
|
-
|
|
1610
|
+
const now = this.audioContext.currentTime;
|
|
1611
|
+
const modRate = this.getChorusModRate(value);
|
|
1612
|
+
this.chorus.modRate = modRate;
|
|
1613
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
1614
|
+
const lfo = this.channels[i].chorusEffect.lfo;
|
|
1615
|
+
lfo.frequency.setValueAtTime(modRate, now);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
getChorusModRate(value) {
|
|
1619
|
+
return value * 0.122; // Hz
|
|
1593
1620
|
}
|
|
1594
1621
|
setChorusModDepth(value) {
|
|
1595
|
-
|
|
1622
|
+
const now = this.audioContext.currentTime;
|
|
1623
|
+
const modDepth = this.getChorusModDepth(value);
|
|
1624
|
+
this.chorus.modDepth = modDepth;
|
|
1625
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
1626
|
+
const chorusEffect = this.channels[i].chorusEffect;
|
|
1627
|
+
chorusEffect.lfoGain.gain
|
|
1628
|
+
.cancelScheduledValues(now)
|
|
1629
|
+
.setValueAtTime(modDepth / 2, now);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
getChorusModDepth(value) {
|
|
1633
|
+
return (value + 1) / 3200; // second
|
|
1596
1634
|
}
|
|
1597
1635
|
setChorusFeedback(value) {
|
|
1598
|
-
|
|
1636
|
+
const now = this.audioContext.currentTime;
|
|
1637
|
+
const feedback = this.getChorusFeedback(value);
|
|
1638
|
+
this.chorus.feedback = feedback;
|
|
1639
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
1640
|
+
const chorusEffect = this.channels[i].chorusEffect;
|
|
1641
|
+
for (let j = 0; j < chorusEffect.feedbackGains.length; j++) {
|
|
1642
|
+
const feedbackGain = chorusEffect.feedbackGains[j];
|
|
1643
|
+
feedbackGain.gain
|
|
1644
|
+
.cancelScheduledValues(now)
|
|
1645
|
+
.setValueAtTime(feedback, now);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
getChorusFeedback(value) {
|
|
1650
|
+
return value * 0.00763;
|
|
1599
1651
|
}
|
|
1600
1652
|
setChorusSendToReverb(value) {
|
|
1601
|
-
|
|
1653
|
+
const sendToReverb = this.getChorusSendToReverb(value);
|
|
1654
|
+
if (0 < sendToReverb) {
|
|
1655
|
+
const now = this.audioContext.currentTime;
|
|
1656
|
+
this.chorus.sendToReverb = sendToReverb;
|
|
1657
|
+
this.chorusEffect.sendGain.gain
|
|
1658
|
+
.cancelScheduledValues(now)
|
|
1659
|
+
.setValueAtTime(sendToReverb, now);
|
|
1660
|
+
}
|
|
1661
|
+
else if (this.chorus.sendToReverb !== 0) {
|
|
1662
|
+
this.chorusEffect.sendGain.disconnect(this.reverbEffect.input);
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
getChorusSendToReverb(value) {
|
|
1666
|
+
return value * 0.00787;
|
|
1602
1667
|
}
|
|
1603
1668
|
handleExclusiveMessage(data) {
|
|
1604
1669
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
package/script/midy-GMLite.d.ts
CHANGED
|
@@ -70,12 +70,11 @@ export class MidyGMLite {
|
|
|
70
70
|
currentTime(): number;
|
|
71
71
|
getActiveNotes(channel: any, time: any): Map<any, any>;
|
|
72
72
|
getActiveNote(noteList: any, time: any): any;
|
|
73
|
-
connectEffects(channel: any, gainNode: any): void;
|
|
74
73
|
cbToRatio(cb: any): number;
|
|
75
74
|
centToHz(cent: any): number;
|
|
76
75
|
calcSemitoneOffset(channel: any): number;
|
|
77
76
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
78
|
-
setVolumeEnvelope(
|
|
77
|
+
setVolumeEnvelope(note: any): void;
|
|
79
78
|
setFilterEnvelope(channel: any, note: any): void;
|
|
80
79
|
startModulation(channel: any, note: any, time: any): void;
|
|
81
80
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAqBA;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;
|
|
1
|
+
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAqBA;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,4BAsBC;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,iDAiCC;IAED,0DAmBC;IAED,wHA6BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIA8CC;IAED,0FAGC;IAED,kEAeC;IAED,wFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,uDAOC;IAED,mFA+BC;IAED,qCAcC;IAED,yDAIC;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,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AA5+BD;IAOE,gFAKC;IAXD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|
package/script/midy-GMLite.js
CHANGED
|
@@ -147,8 +147,8 @@ class MidyGMLite {
|
|
|
147
147
|
});
|
|
148
148
|
this.audioContext = audioContext;
|
|
149
149
|
this.masterGain = new GainNode(audioContext);
|
|
150
|
-
this.masterGain.connect(audioContext.destination);
|
|
151
150
|
this.channels = this.createChannels(audioContext);
|
|
151
|
+
this.masterGain.connect(audioContext.destination);
|
|
152
152
|
this.GM1SystemOn();
|
|
153
153
|
}
|
|
154
154
|
initSoundFontTable() {
|
|
@@ -192,6 +192,7 @@ class MidyGMLite {
|
|
|
192
192
|
const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
|
|
193
193
|
gainL.connect(merger, 0, 0);
|
|
194
194
|
gainR.connect(merger, 0, 1);
|
|
195
|
+
merger.connect(this.masterGain);
|
|
195
196
|
return {
|
|
196
197
|
gainL,
|
|
197
198
|
gainR,
|
|
@@ -494,10 +495,6 @@ class MidyGMLite {
|
|
|
494
495
|
}
|
|
495
496
|
return noteList[0];
|
|
496
497
|
}
|
|
497
|
-
connectEffects(channel, gainNode) {
|
|
498
|
-
gainNode.connect(channel.merger);
|
|
499
|
-
merger.connect(this.masterGain);
|
|
500
|
-
}
|
|
501
498
|
cbToRatio(cb) {
|
|
502
499
|
return Math.pow(10, cb / 200);
|
|
503
500
|
}
|
|
@@ -511,14 +508,10 @@ class MidyGMLite {
|
|
|
511
508
|
return instrumentKey.playbackRate(noteNumber) *
|
|
512
509
|
Math.pow(2, semitoneOffset / 12);
|
|
513
510
|
}
|
|
514
|
-
setVolumeEnvelope(
|
|
515
|
-
const { instrumentKey, startTime
|
|
511
|
+
setVolumeEnvelope(note) {
|
|
512
|
+
const { instrumentKey, startTime } = note;
|
|
516
513
|
note.gainNode = new GainNode(this.audioContext, { gain: 0 });
|
|
517
|
-
|
|
518
|
-
if (volume === 0)
|
|
519
|
-
volume = 1e-6; // exponentialRampToValueAtTime() requires a non-zero value
|
|
520
|
-
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation) *
|
|
521
|
-
volume;
|
|
514
|
+
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
522
515
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
523
516
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
524
517
|
const volAttack = volDelay + instrumentKey.volAttack;
|
|
@@ -578,7 +571,7 @@ class MidyGMLite {
|
|
|
578
571
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
579
572
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
580
573
|
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
581
|
-
this.setVolumeEnvelope(
|
|
574
|
+
this.setVolumeEnvelope(note);
|
|
582
575
|
this.setFilterEnvelope(channel, note);
|
|
583
576
|
if (channel.modulation > 0) {
|
|
584
577
|
const delayModLFO = startTime + instrumentKey.delayModLFO;
|
|
@@ -601,7 +594,8 @@ class MidyGMLite {
|
|
|
601
594
|
if (!instrumentKey)
|
|
602
595
|
return;
|
|
603
596
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
604
|
-
|
|
597
|
+
note.gainNode.connect(channel.gainL);
|
|
598
|
+
note.gainNode.connect(channel.gainR);
|
|
605
599
|
const scheduledNotes = channel.scheduledNotes;
|
|
606
600
|
if (scheduledNotes.has(noteNumber)) {
|
|
607
601
|
scheduledNotes.get(noteNumber).push(note);
|
|
@@ -704,13 +698,13 @@ class MidyGMLite {
|
|
|
704
698
|
channel.program = program;
|
|
705
699
|
}
|
|
706
700
|
handlePitchBendMessage(channelNumber, lsb, msb) {
|
|
707
|
-
const pitchBend = msb * 128 + lsb;
|
|
701
|
+
const pitchBend = msb * 128 + lsb - 8192;
|
|
708
702
|
this.setPitchBend(channelNumber, pitchBend);
|
|
709
703
|
}
|
|
710
704
|
setPitchBend(channelNumber, pitchBend) {
|
|
711
705
|
const channel = this.channels[channelNumber];
|
|
712
706
|
const prevPitchBend = channel.pitchBend;
|
|
713
|
-
channel.pitchBend =
|
|
707
|
+
channel.pitchBend = pitchBend / 8192;
|
|
714
708
|
const detuneChange = (channel.pitchBend - prevPitchBend) *
|
|
715
709
|
channel.pitchBendRange * 100;
|
|
716
710
|
this.updateDetune(channel, detuneChange);
|
|
@@ -880,7 +874,7 @@ class MidyGMLite {
|
|
|
880
874
|
channel.scheduledNotes.forEach((noteList) => {
|
|
881
875
|
const activeNote = this.getActiveNote(noteList, now);
|
|
882
876
|
if (activeNote) {
|
|
883
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
|
|
877
|
+
const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
|
|
884
878
|
promises.push(notePromise);
|
|
885
879
|
}
|
|
886
880
|
});
|
package/script/midy.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ export class Midy {
|
|
|
59
59
|
modDepth: number;
|
|
60
60
|
feedback: number;
|
|
61
61
|
sendToReverb: number;
|
|
62
|
+
delayTimes: any[];
|
|
62
63
|
};
|
|
63
64
|
mono: boolean;
|
|
64
65
|
omni: boolean;
|
|
@@ -92,6 +93,19 @@ export class Midy {
|
|
|
92
93
|
};
|
|
93
94
|
masterGain: any;
|
|
94
95
|
channels: any[];
|
|
96
|
+
reverbEffect: {
|
|
97
|
+
input: any;
|
|
98
|
+
output: any;
|
|
99
|
+
};
|
|
100
|
+
chorusEffect: {
|
|
101
|
+
input: any;
|
|
102
|
+
output: any;
|
|
103
|
+
sendGain: any;
|
|
104
|
+
lfo: any;
|
|
105
|
+
lfoGain: any;
|
|
106
|
+
delayNodes: any[];
|
|
107
|
+
feedbackGains: any[];
|
|
108
|
+
};
|
|
95
109
|
initSoundFontTable(): any[];
|
|
96
110
|
addSoundFont(soundFont: any): void;
|
|
97
111
|
loadSoundFont(soundFontUrl: any): Promise<void>;
|
|
@@ -100,17 +114,6 @@ export class Midy {
|
|
|
100
114
|
gainL: any;
|
|
101
115
|
gainR: any;
|
|
102
116
|
merger: any;
|
|
103
|
-
reverbEffect: {
|
|
104
|
-
input: any;
|
|
105
|
-
output: any;
|
|
106
|
-
};
|
|
107
|
-
chorusEffect: {
|
|
108
|
-
lfo: any;
|
|
109
|
-
lfoGain: any;
|
|
110
|
-
delayNodes: any[];
|
|
111
|
-
chorusGains: any[];
|
|
112
|
-
output: any;
|
|
113
|
-
};
|
|
114
117
|
};
|
|
115
118
|
createChannels(audioContext: any): any[];
|
|
116
119
|
createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
|
|
@@ -144,23 +147,24 @@ export class Midy {
|
|
|
144
147
|
createCombFilter(audioContext: any, input: any, delay: any, feedback: any): any;
|
|
145
148
|
createAllpassFilter(audioContext: any, input: any, delay: any, feedback: any): any;
|
|
146
149
|
generateDistributedArray(center: any, count: any, varianceRatio?: number, randomness?: number): any[];
|
|
147
|
-
createSchroederReverb(audioContext: any,
|
|
150
|
+
createSchroederReverb(audioContext: any, combFeedbacks: any, combDelays: any, allpassFeedbacks: any, allpassDelays: any): {
|
|
148
151
|
input: any;
|
|
149
152
|
output: any;
|
|
150
153
|
};
|
|
151
|
-
createChorusEffect(audioContext: any
|
|
154
|
+
createChorusEffect(audioContext: any): {
|
|
155
|
+
input: any;
|
|
156
|
+
output: any;
|
|
157
|
+
sendGain: any;
|
|
152
158
|
lfo: any;
|
|
153
159
|
lfoGain: any;
|
|
154
160
|
delayNodes: any[];
|
|
155
|
-
|
|
156
|
-
output: any;
|
|
161
|
+
feedbackGains: any[];
|
|
157
162
|
};
|
|
158
|
-
connectEffects(channel: any, gainNode: any): void;
|
|
159
163
|
cbToRatio(cb: any): number;
|
|
160
164
|
centToHz(cent: any): number;
|
|
161
165
|
calcSemitoneOffset(channel: any): any;
|
|
162
166
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
163
|
-
setVolumeEnvelope(
|
|
167
|
+
setVolumeEnvelope(note: any): void;
|
|
164
168
|
setFilterEnvelope(channel: any, note: any): void;
|
|
165
169
|
startModulation(channel: any, note: any, time: any): void;
|
|
166
170
|
startVibrato(channel: any, note: any, time: any): void;
|
|
@@ -236,19 +240,24 @@ export class Midy {
|
|
|
236
240
|
setMasterFineTuning(fineTuning: any): void;
|
|
237
241
|
handleMasterCoarseTuningSysEx(data: any): void;
|
|
238
242
|
setMasterCoarseTuning(coarseTuning: any): void;
|
|
239
|
-
|
|
240
|
-
|
|
243
|
+
handleGlobalParameterControlSysEx(data: any): void;
|
|
244
|
+
handleReverbParameterSysEx(data: any): void;
|
|
241
245
|
setReverbType(type: any): void;
|
|
242
246
|
getReverbTimeFromType(type: any): number | undefined;
|
|
243
247
|
setReverbTime(value: any): void;
|
|
244
248
|
getReverbTime(value: any): number;
|
|
245
249
|
calcDelay(rt60: any, feedback: any): number;
|
|
246
|
-
|
|
250
|
+
handleChorusParameterSysEx(data: any): void;
|
|
247
251
|
setChorusType(type: any): void;
|
|
252
|
+
setChorusParameter(modRate: any, modDepth: any, feedback: any, sendToReverb: any): void;
|
|
248
253
|
setChorusModRate(value: any): void;
|
|
254
|
+
getChorusModRate(value: any): number;
|
|
249
255
|
setChorusModDepth(value: any): void;
|
|
256
|
+
getChorusModDepth(value: any): number;
|
|
250
257
|
setChorusFeedback(value: any): void;
|
|
258
|
+
getChorusFeedback(value: any): number;
|
|
251
259
|
setChorusSendToReverb(value: any): void;
|
|
260
|
+
getChorusSendToReverb(value: any): number;
|
|
252
261
|
handleExclusiveMessage(data: any): void;
|
|
253
262
|
handleSysEx(data: any): void;
|
|
254
263
|
scheduleTask(callback: any, startTime: any): Promise<any>;
|