@marmooo/midy 0.0.6 → 0.0.8
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 +12 -2
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +101 -42
- package/esm/midy-GM2.d.ts +22 -10
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +138 -65
- package/esm/midy-GMLite.d.ts +6 -2
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +47 -40
- package/esm/midy.d.ts +20 -8
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +137 -90
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +12 -2
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +101 -42
- package/script/midy-GM2.d.ts +22 -10
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +138 -65
- package/script/midy-GMLite.d.ts +6 -2
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +47 -40
- package/script/midy.d.ts +20 -8
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +137 -90
package/esm/midy.js
CHANGED
|
@@ -75,13 +75,13 @@ export class Midy {
|
|
|
75
75
|
configurable: true,
|
|
76
76
|
writable: true,
|
|
77
77
|
value: 0
|
|
78
|
-
});
|
|
78
|
+
}); // cb
|
|
79
79
|
Object.defineProperty(this, "masterCoarseTuning", {
|
|
80
80
|
enumerable: true,
|
|
81
81
|
configurable: true,
|
|
82
82
|
writable: true,
|
|
83
83
|
value: 0
|
|
84
|
-
});
|
|
84
|
+
}); // cb
|
|
85
85
|
Object.defineProperty(this, "mono", {
|
|
86
86
|
enumerable: true,
|
|
87
87
|
configurable: true,
|
|
@@ -651,14 +651,16 @@ export class Midy {
|
|
|
651
651
|
connectNoteEffects(channel, gainNode) {
|
|
652
652
|
if (channel.reverb === 0) {
|
|
653
653
|
if (channel.chorus === 0) { // no effect
|
|
654
|
-
gainNode.connect(channel.
|
|
654
|
+
gainNode.connect(channel.gainL);
|
|
655
|
+
gainNode.connect(channel.gainR);
|
|
655
656
|
}
|
|
656
657
|
else { // chorus
|
|
657
658
|
channel.chorusEffect.delayNodes.forEach((delayNode) => {
|
|
658
659
|
gainNode.connect(delayNode);
|
|
659
660
|
});
|
|
660
661
|
channel.chorusEffect.chorusGains.forEach((chorusGain) => {
|
|
661
|
-
chorusGain.connect(channel.
|
|
662
|
+
chorusGain.connect(channel.gainL);
|
|
663
|
+
chorusGain.connect(channel.gainR);
|
|
662
664
|
});
|
|
663
665
|
}
|
|
664
666
|
}
|
|
@@ -746,7 +748,7 @@ export class Midy {
|
|
|
746
748
|
startModulation(channel, note, time) {
|
|
747
749
|
const { instrumentKey } = note;
|
|
748
750
|
note.modLFOGain = new GainNode(this.audioContext, {
|
|
749
|
-
gain: this.cbToRatio(instrumentKey.modLfoToVolume
|
|
751
|
+
gain: this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation),
|
|
750
752
|
});
|
|
751
753
|
note.modLFO = new OscillatorNode(this.audioContext, {
|
|
752
754
|
frequency: this.centToHz(instrumentKey.freqModLFO),
|
|
@@ -977,20 +979,12 @@ export class Midy {
|
|
|
977
979
|
this.setPitchBend(channelNumber, pitchBend);
|
|
978
980
|
}
|
|
979
981
|
setPitchBend(channelNumber, pitchBend) {
|
|
980
|
-
const now = this.audioContext.currentTime;
|
|
981
982
|
const channel = this.channels[channelNumber];
|
|
982
983
|
const prevPitchBend = channel.pitchBend;
|
|
983
984
|
channel.pitchBend = (pitchBend - 8192) / 8192;
|
|
984
985
|
const detuneChange = (channel.pitchBend - prevPitchBend) *
|
|
985
986
|
channel.pitchBendRange * 100;
|
|
986
|
-
|
|
987
|
-
activeNotes.forEach((activeNote) => {
|
|
988
|
-
const { bufferSource } = activeNote;
|
|
989
|
-
const detune = bufferSource.detune.value + detuneChange;
|
|
990
|
-
bufferSource.detune
|
|
991
|
-
.cancelScheduledValues(now)
|
|
992
|
-
.setValueAtTime(detune, now);
|
|
993
|
-
});
|
|
987
|
+
this.updateDetune(channel, detuneChange);
|
|
994
988
|
}
|
|
995
989
|
handleControlChange(channelNumber, controller, value) {
|
|
996
990
|
switch (controller) {
|
|
@@ -1001,7 +995,7 @@ export class Midy {
|
|
|
1001
995
|
case 5:
|
|
1002
996
|
return this.setPortamentoTime(channelNumber, value);
|
|
1003
997
|
case 6:
|
|
1004
|
-
return this.
|
|
998
|
+
return this.dataEntryMSB(channelNumber, value);
|
|
1005
999
|
case 7:
|
|
1006
1000
|
return this.setVolume(channelNumber, value);
|
|
1007
1001
|
case 10:
|
|
@@ -1011,7 +1005,7 @@ export class Midy {
|
|
|
1011
1005
|
case 32:
|
|
1012
1006
|
return this.setBankLSB(channelNumber, value);
|
|
1013
1007
|
case 38:
|
|
1014
|
-
return this.
|
|
1008
|
+
return this.dataEntryLSB(channelNumber, value);
|
|
1015
1009
|
case 64:
|
|
1016
1010
|
return this.setSustainPedal(channelNumber, value);
|
|
1017
1011
|
case 65:
|
|
@@ -1028,17 +1022,17 @@ export class Midy {
|
|
|
1028
1022
|
case 78:
|
|
1029
1023
|
return this.setVibratoDelay(channelNumber, value);
|
|
1030
1024
|
case 91:
|
|
1031
|
-
return this.
|
|
1025
|
+
return this.setReverbSendLevel(channelNumber, value);
|
|
1032
1026
|
case 93:
|
|
1033
|
-
return this.
|
|
1034
|
-
case 96:
|
|
1035
|
-
return
|
|
1036
|
-
case 97:
|
|
1037
|
-
return
|
|
1027
|
+
return this.setChorusSendLevel(channelNumber, value);
|
|
1028
|
+
case 96: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp18.pdf
|
|
1029
|
+
return this.dataIncrement(channelNumber);
|
|
1030
|
+
case 97: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp18.pdf
|
|
1031
|
+
return this.dataDecrement(channelNumber);
|
|
1038
1032
|
case 100:
|
|
1039
|
-
return this.setRPNMSB(channelNumber, value);
|
|
1040
|
-
case 101:
|
|
1041
1033
|
return this.setRPNLSB(channelNumber, value);
|
|
1034
|
+
case 101:
|
|
1035
|
+
return this.setRPNMSB(channelNumber, value);
|
|
1042
1036
|
case 120:
|
|
1043
1037
|
return this.allSoundOff(channelNumber);
|
|
1044
1038
|
case 121:
|
|
@@ -1060,22 +1054,24 @@ export class Midy {
|
|
|
1060
1054
|
setBankMSB(channelNumber, msb) {
|
|
1061
1055
|
this.channels[channelNumber].bankMSB = msb;
|
|
1062
1056
|
}
|
|
1063
|
-
|
|
1057
|
+
updateModulation(channel) {
|
|
1064
1058
|
const now = this.audioContext.currentTime;
|
|
1065
|
-
const channel = this.channels[channelNumber];
|
|
1066
|
-
channel.modulation = (modulation / 127) *
|
|
1067
|
-
(channel.modulationDepthRange * 100);
|
|
1068
1059
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1069
1060
|
activeNotes.forEach((activeNote) => {
|
|
1070
1061
|
if (activeNote.modLFO) {
|
|
1071
|
-
|
|
1072
|
-
|
|
1062
|
+
const { gainNode, instrumentKey } = activeNote;
|
|
1063
|
+
gainNode.gain.setValueAtTime(this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation), now);
|
|
1073
1064
|
}
|
|
1074
1065
|
else {
|
|
1075
1066
|
this.startModulation(channel, activeNote, now);
|
|
1076
1067
|
}
|
|
1077
1068
|
});
|
|
1078
1069
|
}
|
|
1070
|
+
setModulation(channelNumber, modulation) {
|
|
1071
|
+
const channel = this.channels[channelNumber];
|
|
1072
|
+
channel.modulation = (modulation / 127) * channel.modulationDepthRange;
|
|
1073
|
+
this.updateModulation(channel);
|
|
1074
|
+
}
|
|
1079
1075
|
setPortamentoTime(channelNumber, portamentoTime) {
|
|
1080
1076
|
this.channels[channelNumber].portamentoTime = portamentoTime / 127;
|
|
1081
1077
|
}
|
|
@@ -1104,6 +1100,10 @@ export class Midy {
|
|
|
1104
1100
|
setBankLSB(channelNumber, lsb) {
|
|
1105
1101
|
this.channels[channelNumber].bankLSB = lsb;
|
|
1106
1102
|
}
|
|
1103
|
+
dataEntryLSB(channelNumber, value) {
|
|
1104
|
+
this.channels[channelNumber].dataLSB = value;
|
|
1105
|
+
this.handleRPN(channelNumber, 0);
|
|
1106
|
+
}
|
|
1107
1107
|
updateChannelGain(channel) {
|
|
1108
1108
|
const now = this.audioContext.currentTime;
|
|
1109
1109
|
const volume = channel.volume * channel.expression;
|
|
@@ -1125,7 +1125,7 @@ export class Midy {
|
|
|
1125
1125
|
setPortamento(channelNumber, value) {
|
|
1126
1126
|
this.channels[channelNumber].portamento = value >= 64;
|
|
1127
1127
|
}
|
|
1128
|
-
|
|
1128
|
+
setReverbSendLevel(channelNumber, reverb) {
|
|
1129
1129
|
const now = this.audioContext.currentTime;
|
|
1130
1130
|
const channel = this.channels[channelNumber];
|
|
1131
1131
|
const reverbEffect = channel.reverbEffect;
|
|
@@ -1135,7 +1135,7 @@ export class Midy {
|
|
|
1135
1135
|
reverbEffect.wetGain.gain.cancelScheduledValues(now);
|
|
1136
1136
|
reverbEffect.wetGain.gain.setValueAtTime(channel.reverb, now);
|
|
1137
1137
|
}
|
|
1138
|
-
|
|
1138
|
+
setChorusSendLevel(channelNumber, chorus) {
|
|
1139
1139
|
const channel = this.channels[channelNumber];
|
|
1140
1140
|
channel.chorus = chorus / 127;
|
|
1141
1141
|
channel.chorusEffect.lfoGain = channel.chorus;
|
|
@@ -1175,79 +1175,74 @@ export class Midy {
|
|
|
1175
1175
|
const channel = this.channels[channelNumber];
|
|
1176
1176
|
channel.vibratoDelay = vibratoDelay / 127 * 5; // 0-5sec
|
|
1177
1177
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1178
|
+
limitData(channel, minMSB, maxMSB, minLSB, maxLSB) {
|
|
1179
|
+
if (maxLSB < channel.dataLSB) {
|
|
1180
|
+
channel.dataMSB++;
|
|
1181
|
+
channel.dataLSB = minLSB;
|
|
1182
|
+
}
|
|
1183
|
+
else if (channel.dataLSB < 0) {
|
|
1184
|
+
channel.dataMSB--;
|
|
1185
|
+
channel.dataLSB = maxLSB;
|
|
1186
|
+
}
|
|
1187
|
+
if (maxMSB < channel.dataMSB) {
|
|
1188
|
+
channel.dataMSB = maxMSB;
|
|
1189
|
+
channel.dataLSB = maxLSB;
|
|
1190
|
+
}
|
|
1191
|
+
else if (channel.dataMSB < 0) {
|
|
1192
|
+
channel.dataMSB = minMSB;
|
|
1193
|
+
channel.dataLSB = minLSB;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
limitDataMSB(channel, minMSB, maxMSB) {
|
|
1197
|
+
if (maxMSB < channel.dataMSB) {
|
|
1198
|
+
channel.dataMSB = maxMSB;
|
|
1199
|
+
}
|
|
1200
|
+
else if (channel.dataMSB < 0) {
|
|
1201
|
+
channel.dataMSB = minMSB;
|
|
1193
1202
|
}
|
|
1194
1203
|
}
|
|
1195
|
-
|
|
1204
|
+
handleRPN(channelNumber, value) {
|
|
1196
1205
|
const channel = this.channels[channelNumber];
|
|
1197
1206
|
const rpn = channel.rpnMSB * 128 + channel.rpnLSB;
|
|
1198
1207
|
switch (rpn) {
|
|
1199
1208
|
case 0:
|
|
1200
|
-
channel.
|
|
1209
|
+
channel.dataLSB += value;
|
|
1210
|
+
this.handlePitchBendRangeRPN(channelNumber);
|
|
1201
1211
|
break;
|
|
1202
1212
|
case 1:
|
|
1203
|
-
channel.
|
|
1213
|
+
channel.dataLSB += value;
|
|
1214
|
+
this.handleFineTuningRPN(channelNumber);
|
|
1204
1215
|
break;
|
|
1205
1216
|
case 2:
|
|
1206
|
-
channel.
|
|
1217
|
+
channel.dataMSB += value;
|
|
1218
|
+
this.handleCoarseTuningRPN(channelNumber);
|
|
1219
|
+
break;
|
|
1220
|
+
case 5:
|
|
1221
|
+
channel.dataLSB += value;
|
|
1222
|
+
this.handleModulationDepthRangeRPN(channelNumber);
|
|
1207
1223
|
break;
|
|
1208
1224
|
default:
|
|
1209
|
-
console.warn(`Channel ${channelNumber}: Unsupported RPN MSB=${channel.rpnMSB}
|
|
1225
|
+
console.warn(`Channel ${channelNumber}: Unsupported RPN MSB=${channel.rpnMSB} LSB=${channel.rpnLSB}`);
|
|
1210
1226
|
}
|
|
1211
1227
|
}
|
|
1228
|
+
dataIncrement(channelNumber) {
|
|
1229
|
+
this.handleRPN(channelNumber, 1);
|
|
1230
|
+
}
|
|
1231
|
+
dataDecrement(channelNumber) {
|
|
1232
|
+
this.handleRPN(channelNumber, -1);
|
|
1233
|
+
}
|
|
1212
1234
|
setRPNMSB(channelNumber, value) {
|
|
1213
1235
|
this.channels[channelNumber].rpnMSB = value;
|
|
1214
1236
|
}
|
|
1215
1237
|
setRPNLSB(channelNumber, value) {
|
|
1216
1238
|
this.channels[channelNumber].rpnLSB = value;
|
|
1217
1239
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
const rpn = channel.rpnMSB * 128 + channel.rpnLSB;
|
|
1222
|
-
isMSB ? channel.dataMSB = value : channel.dataLSB = value;
|
|
1223
|
-
const { dataMSB, dataLSB } = channel;
|
|
1224
|
-
switch (rpn) {
|
|
1225
|
-
case 0:
|
|
1226
|
-
return this.handlePitchBendRangeMessage(channelNumber, dataMSB, dataLSB);
|
|
1227
|
-
case 1:
|
|
1228
|
-
channel.fineTuning = (dataMSB * 128 + dataLSB - 8192) / 8192;
|
|
1229
|
-
break;
|
|
1230
|
-
case 2:
|
|
1231
|
-
channel.coarseTuning = dataMSB - 64;
|
|
1232
|
-
break;
|
|
1233
|
-
case 5:
|
|
1234
|
-
channel.modulationDepthRange = dataMSB + dataLSB / 128;
|
|
1235
|
-
break;
|
|
1236
|
-
default:
|
|
1237
|
-
console.warn(`Channel ${channelNumber}: Unsupported RPN MSB=${channel.rpnMSB} LSB=${channel.rpnLSB}`);
|
|
1238
|
-
}
|
|
1240
|
+
dataEntryMSB(channelNumber, value) {
|
|
1241
|
+
this.channels[channelNumber].dataMSB = value;
|
|
1242
|
+
this.handleRPN(channelNumber, 0);
|
|
1239
1243
|
}
|
|
1240
|
-
|
|
1241
|
-
const pitchBendRange = dataMSB + dataLSB / 100;
|
|
1242
|
-
this.setPitchBendRange(channelNumber, pitchBendRange);
|
|
1243
|
-
}
|
|
1244
|
-
setPitchBendRange(channelNumber, pitchBendRange) {
|
|
1244
|
+
updateDetune(channel, detuneChange) {
|
|
1245
1245
|
const now = this.audioContext.currentTime;
|
|
1246
|
-
const channel = this.channels[channelNumber];
|
|
1247
|
-
const prevPitchBendRange = channel.pitchBendRange;
|
|
1248
|
-
channel.pitchBendRange = pitchBendRange;
|
|
1249
|
-
const detuneChange = (channel.pitchBendRange - prevPitchBendRange) *
|
|
1250
|
-
channel.pitchBend * 100;
|
|
1251
1246
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1252
1247
|
activeNotes.forEach((activeNote) => {
|
|
1253
1248
|
const { bufferSource } = activeNote;
|
|
@@ -1257,6 +1252,58 @@ export class Midy {
|
|
|
1257
1252
|
.setValueAtTime(detune, now);
|
|
1258
1253
|
});
|
|
1259
1254
|
}
|
|
1255
|
+
handlePitchBendRangeRPN(channelNumber) {
|
|
1256
|
+
const channel = this.channels[channelNumber];
|
|
1257
|
+
this.limitData(channel, 0, 127, 0, 99);
|
|
1258
|
+
const pitchBendRange = channel.dataMSB + channel.dataLSB / 100;
|
|
1259
|
+
this.setPitchBendRange(channelNumber, pitchBendRange);
|
|
1260
|
+
}
|
|
1261
|
+
setPitchBendRange(channelNumber, pitchBendRange) {
|
|
1262
|
+
const channel = this.channels[channelNumber];
|
|
1263
|
+
const prevPitchBendRange = channel.pitchBendRange;
|
|
1264
|
+
channel.pitchBendRange = pitchBendRange;
|
|
1265
|
+
const detuneChange = (channel.pitchBendRange - prevPitchBendRange) *
|
|
1266
|
+
channel.pitchBend * 100;
|
|
1267
|
+
this.updateDetune(channel, detuneChange);
|
|
1268
|
+
}
|
|
1269
|
+
handleFineTuningRPN(channelNumber) {
|
|
1270
|
+
const channel = this.channels[channelNumber];
|
|
1271
|
+
this.limitData(channel, 0, 127, 0, 127);
|
|
1272
|
+
const fineTuning = (channel.dataMSB * 128 + channel.dataLSB - 8192) / 8192;
|
|
1273
|
+
this.setFineTuning(channelNumber, fineTuning);
|
|
1274
|
+
}
|
|
1275
|
+
setFineTuning(channelNumber, fineTuning) {
|
|
1276
|
+
const channel = this.channels[channelNumber];
|
|
1277
|
+
const prevFineTuning = channel.fineTuning;
|
|
1278
|
+
channel.fineTuning = fineTuning;
|
|
1279
|
+
const detuneChange = channel.fineTuning - prevFineTuning;
|
|
1280
|
+
this.updateDetune(channel, detuneChange);
|
|
1281
|
+
}
|
|
1282
|
+
handleCoarseTuningRPN(channelNumber) {
|
|
1283
|
+
const channel = this.channels[channelNumber];
|
|
1284
|
+
this.limitDataMSB(channel, 0, 127);
|
|
1285
|
+
const coarseTuning = channel.dataMSB - 64;
|
|
1286
|
+
this.setFineTuning(channelNumber, coarseTuning);
|
|
1287
|
+
}
|
|
1288
|
+
setCoarseTuning(channelNumber, coarseTuning) {
|
|
1289
|
+
const channel = this.channels[channelNumber];
|
|
1290
|
+
const prevCoarseTuning = channel.coarseTuning;
|
|
1291
|
+
channel.coarseTuning = coarseTuning;
|
|
1292
|
+
const detuneChange = channel.coarseTuning - prevCoarseTuning;
|
|
1293
|
+
this.updateDetune(channel, detuneChange);
|
|
1294
|
+
}
|
|
1295
|
+
handleModulationDepthRangeRPN(channelNumber) {
|
|
1296
|
+
const channel = this.channels[channelNumber];
|
|
1297
|
+
this.limitData(channel, 0, 127, 0, 127);
|
|
1298
|
+
const modulationDepthRange = dataMSB + dataLSB / 128;
|
|
1299
|
+
this.setModulationDepthRange(channelNumber, modulationDepthRange);
|
|
1300
|
+
}
|
|
1301
|
+
setModulationDepthRange(channelNumber, modulationDepthRange) {
|
|
1302
|
+
const channel = this.channels[channelNumber];
|
|
1303
|
+
channel.modulationDepthRange = modulationDepthRange;
|
|
1304
|
+
channel.modulation = (modulation / 127) * channel.modulationDepthRange;
|
|
1305
|
+
this.updateModulation(channel);
|
|
1306
|
+
}
|
|
1260
1307
|
allSoundOff(channelNumber) {
|
|
1261
1308
|
const now = this.audioContext.currentTime;
|
|
1262
1309
|
const channel = this.channels[channelNumber];
|
|
@@ -1328,8 +1375,8 @@ export class Midy {
|
|
|
1328
1375
|
channel.bankLSB = 0;
|
|
1329
1376
|
channel.bank = 0;
|
|
1330
1377
|
});
|
|
1331
|
-
this.channels[9].bankMSB =
|
|
1332
|
-
this.channels[9].bank =
|
|
1378
|
+
this.channels[9].bankMSB = 1;
|
|
1379
|
+
this.channels[9].bank = 128;
|
|
1333
1380
|
}
|
|
1334
1381
|
GM2SystemOn() {
|
|
1335
1382
|
this.channels.forEach((channel) => {
|
|
@@ -1346,9 +1393,9 @@ export class Midy {
|
|
|
1346
1393
|
switch (data[3]) {
|
|
1347
1394
|
case 1:
|
|
1348
1395
|
return this.handleMasterVolumeSysEx(data);
|
|
1349
|
-
case 3:
|
|
1396
|
+
case 3: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
|
|
1350
1397
|
return this.handleMasterFineTuningSysEx(data);
|
|
1351
|
-
case 4:
|
|
1398
|
+
case 4: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
|
|
1352
1399
|
return this.handleMasterCoarseTuningSysEx(data);
|
|
1353
1400
|
// case 5: // TODO: Global Parameter Control
|
|
1354
1401
|
default:
|
|
@@ -1473,9 +1520,9 @@ Object.defineProperty(Midy, "channelSettings", {
|
|
|
1473
1520
|
dataLSB: 0,
|
|
1474
1521
|
program: 0,
|
|
1475
1522
|
pitchBend: 0,
|
|
1476
|
-
fineTuning: 0,
|
|
1477
|
-
coarseTuning: 0,
|
|
1478
|
-
modulationDepthRange: 0.5,
|
|
1523
|
+
fineTuning: 0, // cb
|
|
1524
|
+
coarseTuning: 0, // cb
|
|
1525
|
+
modulationDepthRange: 0.5, // cb
|
|
1479
1526
|
}
|
|
1480
1527
|
});
|
|
1481
1528
|
Object.defineProperty(Midy, "effectSettings", {
|
package/package.json
CHANGED
package/script/midy-GM1.d.ts
CHANGED
|
@@ -130,6 +130,7 @@ export class MidyGM1 {
|
|
|
130
130
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
131
131
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
132
132
|
handleControlChange(channelNumber: any, controller: any, value: any): void | any[];
|
|
133
|
+
updateModulation(channel: any): void;
|
|
133
134
|
setModulation(channelNumber: any, modulation: any): void;
|
|
134
135
|
setVolume(channelNumber: any, volume: any): void;
|
|
135
136
|
panToGain(pan: any): {
|
|
@@ -138,13 +139,22 @@ export class MidyGM1 {
|
|
|
138
139
|
};
|
|
139
140
|
setPan(channelNumber: any, pan: any): void;
|
|
140
141
|
setExpression(channelNumber: any, expression: any): void;
|
|
142
|
+
dataEntryLSB(channelNumber: any, value: any): void;
|
|
141
143
|
updateChannelGain(channel: any): void;
|
|
142
144
|
setSustainPedal(channelNumber: any, value: any): void;
|
|
145
|
+
limitData(channel: any, minMSB: any, maxMSB: any, minLSB: any, maxLSB: any): void;
|
|
146
|
+
limitDataMSB(channel: any, minMSB: any, maxMSB: any): void;
|
|
147
|
+
handleRPN(channelNumber: any): void;
|
|
143
148
|
setRPNMSB(channelNumber: any, value: any): void;
|
|
144
149
|
setRPNLSB(channelNumber: any, value: any): void;
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
dataEntryMSB(channelNumber: any, value: any): void;
|
|
151
|
+
updateDetune(channel: any, detuneChange: any): void;
|
|
152
|
+
handlePitchBendRangeRPN(channelNumber: any): void;
|
|
147
153
|
setPitchBendRange(channelNumber: any, pitchBendRange: any): void;
|
|
154
|
+
handleFineTuningRPN(channelNumber: any): void;
|
|
155
|
+
setFineTuning(channelNumber: any, fineTuning: any): void;
|
|
156
|
+
handleCoarseTuningRPN(channelNumber: any): void;
|
|
157
|
+
setCoarseTuning(channelNumber: any, coarseTuning: any): void;
|
|
148
158
|
allSoundOff(channelNumber: any): any[];
|
|
149
159
|
resetAllControllers(channelNumber: any): void;
|
|
150
160
|
allNotesOff(channelNumber: any): any[];
|
package/script/midy-GM1.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAqBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA9CD,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;IAyBhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;MAYC;IAED;;;;;;;;;;;;;;;;;;;;QAUC;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,
|
|
1
|
+
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAqBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA9CD,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;IAyBhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;MAYC;IAED;;;;;;;;;;;;;;;;;;;;QAUC;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,sDAGC;IAED,2BAEC;IAED,4BAEC;IAED,sCAGC;IAED,mFAGC;IAED,iDAiBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHA6BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIAmDC;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,kFAeC;IAED,2DAMC;IAED,oCAkBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAUC;IAED,kDAKC;IAED,iEAOC;IAED,8CAKC;IAED,yDAMC;IAED,gDAKC;IAED,6DAMC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAtjCD;IAOE,gFAKC;IAXD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|
package/script/midy-GM1.js
CHANGED
|
@@ -495,7 +495,8 @@ class MidyGM1 {
|
|
|
495
495
|
return noteList[0];
|
|
496
496
|
}
|
|
497
497
|
connectNoteEffects(channel, gainNode) {
|
|
498
|
-
gainNode.connect(channel.
|
|
498
|
+
gainNode.connect(channel.gainL);
|
|
499
|
+
gainNode.connect(channel.gainR);
|
|
499
500
|
}
|
|
500
501
|
cbToRatio(cb) {
|
|
501
502
|
return Math.pow(10, cb / 200);
|
|
@@ -706,27 +707,19 @@ class MidyGM1 {
|
|
|
706
707
|
this.setPitchBend(channelNumber, pitchBend);
|
|
707
708
|
}
|
|
708
709
|
setPitchBend(channelNumber, pitchBend) {
|
|
709
|
-
const now = this.audioContext.currentTime;
|
|
710
710
|
const channel = this.channels[channelNumber];
|
|
711
711
|
const prevPitchBend = channel.pitchBend;
|
|
712
712
|
channel.pitchBend = (pitchBend - 8192) / 8192;
|
|
713
713
|
const detuneChange = (channel.pitchBend - prevPitchBend) *
|
|
714
714
|
channel.pitchBendRange * 100;
|
|
715
|
-
|
|
716
|
-
activeNotes.forEach((activeNote) => {
|
|
717
|
-
const { bufferSource } = activeNote;
|
|
718
|
-
const detune = bufferSource.detune.value + detuneChange;
|
|
719
|
-
bufferSource.detune
|
|
720
|
-
.cancelScheduledValues(now)
|
|
721
|
-
.setValueAtTime(detune, now);
|
|
722
|
-
});
|
|
715
|
+
this.updateDetune(channel, detuneChange);
|
|
723
716
|
}
|
|
724
717
|
handleControlChange(channelNumber, controller, value) {
|
|
725
718
|
switch (controller) {
|
|
726
719
|
case 1:
|
|
727
720
|
return this.setModulation(channelNumber, value);
|
|
728
721
|
case 6:
|
|
729
|
-
return this.
|
|
722
|
+
return this.dataEntryMSB(channelNumber, value);
|
|
730
723
|
case 7:
|
|
731
724
|
return this.setVolume(channelNumber, value);
|
|
732
725
|
case 10:
|
|
@@ -734,13 +727,13 @@ class MidyGM1 {
|
|
|
734
727
|
case 11:
|
|
735
728
|
return this.setExpression(channelNumber, value);
|
|
736
729
|
case 38:
|
|
737
|
-
return this.
|
|
730
|
+
return this.dataEntryLSB(channelNumber, value);
|
|
738
731
|
case 64:
|
|
739
732
|
return this.setSustainPedal(channelNumber, value);
|
|
740
733
|
case 100:
|
|
741
|
-
return this.setRPNMSB(channelNumber, value);
|
|
742
|
-
case 101:
|
|
743
734
|
return this.setRPNLSB(channelNumber, value);
|
|
735
|
+
case 101:
|
|
736
|
+
return this.setRPNMSB(channelNumber, value);
|
|
744
737
|
case 120:
|
|
745
738
|
return this.allSoundOff(channelNumber);
|
|
746
739
|
case 121:
|
|
@@ -751,22 +744,24 @@ class MidyGM1 {
|
|
|
751
744
|
console.warn(`Unsupported Control change: controller=${controller} value=${value}`);
|
|
752
745
|
}
|
|
753
746
|
}
|
|
754
|
-
|
|
747
|
+
updateModulation(channel) {
|
|
755
748
|
const now = this.audioContext.currentTime;
|
|
756
|
-
const channel = this.channels[channelNumber];
|
|
757
|
-
channel.modulation = (modulation / 127) *
|
|
758
|
-
(channel.modulationDepthRange * 100);
|
|
759
749
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
760
750
|
activeNotes.forEach((activeNote) => {
|
|
761
751
|
if (activeNote.modLFO) {
|
|
762
|
-
|
|
763
|
-
|
|
752
|
+
const { gainNode, instrumentKey } = activeNote;
|
|
753
|
+
gainNode.gain.setValueAtTime(this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation), now);
|
|
764
754
|
}
|
|
765
755
|
else {
|
|
766
756
|
this.startModulation(channel, activeNote, now);
|
|
767
757
|
}
|
|
768
758
|
});
|
|
769
759
|
}
|
|
760
|
+
setModulation(channelNumber, modulation) {
|
|
761
|
+
const channel = this.channels[channelNumber];
|
|
762
|
+
channel.modulation = (modulation / 127) * channel.modulationDepthRange;
|
|
763
|
+
this.updateModulation(channel);
|
|
764
|
+
}
|
|
770
765
|
setVolume(channelNumber, volume) {
|
|
771
766
|
const channel = this.channels[channelNumber];
|
|
772
767
|
channel.volume = volume / 127;
|
|
@@ -789,6 +784,10 @@ class MidyGM1 {
|
|
|
789
784
|
channel.expression = expression / 127;
|
|
790
785
|
this.updateChannelGain(channel);
|
|
791
786
|
}
|
|
787
|
+
dataEntryLSB(channelNumber, value) {
|
|
788
|
+
this.channels[channelNumber].dataLSB = value;
|
|
789
|
+
this.handleRPN(channelNumber, 0);
|
|
790
|
+
}
|
|
792
791
|
updateChannelGain(channel) {
|
|
793
792
|
const now = this.audioContext.currentTime;
|
|
794
793
|
const volume = channel.volume * channel.expression;
|
|
@@ -807,41 +806,61 @@ class MidyGM1 {
|
|
|
807
806
|
this.releaseSustainPedal(channelNumber, value);
|
|
808
807
|
}
|
|
809
808
|
}
|
|
810
|
-
|
|
811
|
-
|
|
809
|
+
limitData(channel, minMSB, maxMSB, minLSB, maxLSB) {
|
|
810
|
+
if (maxLSB < channel.dataLSB) {
|
|
811
|
+
channel.dataMSB++;
|
|
812
|
+
channel.dataLSB = minLSB;
|
|
813
|
+
}
|
|
814
|
+
else if (channel.dataLSB < 0) {
|
|
815
|
+
channel.dataMSB--;
|
|
816
|
+
channel.dataLSB = maxLSB;
|
|
817
|
+
}
|
|
818
|
+
if (maxMSB < channel.dataMSB) {
|
|
819
|
+
channel.dataMSB = maxMSB;
|
|
820
|
+
channel.dataLSB = maxLSB;
|
|
821
|
+
}
|
|
822
|
+
else if (channel.dataMSB < 0) {
|
|
823
|
+
channel.dataMSB = minMSB;
|
|
824
|
+
channel.dataLSB = minLSB;
|
|
825
|
+
}
|
|
812
826
|
}
|
|
813
|
-
|
|
814
|
-
|
|
827
|
+
limitDataMSB(channel, minMSB, maxMSB) {
|
|
828
|
+
if (maxMSB < channel.dataMSB) {
|
|
829
|
+
channel.dataMSB = maxMSB;
|
|
830
|
+
}
|
|
831
|
+
else if (channel.dataMSB < 0) {
|
|
832
|
+
channel.dataMSB = minMSB;
|
|
833
|
+
}
|
|
815
834
|
}
|
|
816
|
-
|
|
835
|
+
handleRPN(channelNumber) {
|
|
817
836
|
const channel = this.channels[channelNumber];
|
|
818
837
|
const rpn = channel.rpnMSB * 128 + channel.rpnLSB;
|
|
819
|
-
isMSB ? channel.dataMSB = value : channel.dataLSB = value;
|
|
820
|
-
const { dataMSB, dataLSB } = channel;
|
|
821
838
|
switch (rpn) {
|
|
822
839
|
case 0:
|
|
823
|
-
|
|
840
|
+
this.handlePitchBendRangeRPN(channelNumber);
|
|
841
|
+
break;
|
|
824
842
|
case 1:
|
|
825
|
-
|
|
843
|
+
this.handleFineTuningRPN(channelNumber);
|
|
826
844
|
break;
|
|
827
845
|
case 2:
|
|
828
|
-
|
|
846
|
+
this.handleCoarseTuningRPN(channelNumber);
|
|
829
847
|
break;
|
|
830
848
|
default:
|
|
831
849
|
console.warn(`Channel ${channelNumber}: Unsupported RPN MSB=${channel.rpnMSB} LSB=${channel.rpnLSB}`);
|
|
832
850
|
}
|
|
833
851
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
this.setPitchBendRange(channelNumber, pitchBendRange);
|
|
852
|
+
setRPNMSB(channelNumber, value) {
|
|
853
|
+
this.channels[channelNumber].rpnMSB = value;
|
|
837
854
|
}
|
|
838
|
-
|
|
855
|
+
setRPNLSB(channelNumber, value) {
|
|
856
|
+
this.channels[channelNumber].rpnLSB = value;
|
|
857
|
+
}
|
|
858
|
+
dataEntryMSB(channelNumber, value) {
|
|
859
|
+
this.channels[channelNumber].dataMSB = value;
|
|
860
|
+
this.handleRPN(channelNumber);
|
|
861
|
+
}
|
|
862
|
+
updateDetune(channel, detuneChange) {
|
|
839
863
|
const now = this.audioContext.currentTime;
|
|
840
|
-
const channel = this.channels[channelNumber];
|
|
841
|
-
const prevPitchBendRange = channel.pitchBendRange;
|
|
842
|
-
channel.pitchBendRange = pitchBendRange;
|
|
843
|
-
const detuneChange = (channel.pitchBendRange - prevPitchBendRange) *
|
|
844
|
-
channel.pitchBend * 100;
|
|
845
864
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
846
865
|
activeNotes.forEach((activeNote) => {
|
|
847
866
|
const { bufferSource } = activeNote;
|
|
@@ -851,6 +870,46 @@ class MidyGM1 {
|
|
|
851
870
|
.setValueAtTime(detune, now);
|
|
852
871
|
});
|
|
853
872
|
}
|
|
873
|
+
handlePitchBendRangeRPN(channelNumber) {
|
|
874
|
+
const channel = this.channels[channelNumber];
|
|
875
|
+
this.limitData(channel, 0, 127, 0, 99);
|
|
876
|
+
const pitchBendRange = channel.dataMSB + channel.dataLSB / 100;
|
|
877
|
+
this.setPitchBendRange(channelNumber, pitchBendRange);
|
|
878
|
+
}
|
|
879
|
+
setPitchBendRange(channelNumber, pitchBendRange) {
|
|
880
|
+
const channel = this.channels[channelNumber];
|
|
881
|
+
const prevPitchBendRange = channel.pitchBendRange;
|
|
882
|
+
channel.pitchBendRange = pitchBendRange;
|
|
883
|
+
const detuneChange = (channel.pitchBendRange - prevPitchBendRange) *
|
|
884
|
+
channel.pitchBend * 100;
|
|
885
|
+
this.updateDetune(channel, detuneChange);
|
|
886
|
+
}
|
|
887
|
+
handleFineTuningRPN(channelNumber) {
|
|
888
|
+
const channel = this.channels[channelNumber];
|
|
889
|
+
this.limitData(channel, 0, 127, 0, 127);
|
|
890
|
+
const fineTuning = (channel.dataMSB * 128 + channel.dataLSB - 8192) / 8192;
|
|
891
|
+
this.setFineTuning(channelNumber, fineTuning);
|
|
892
|
+
}
|
|
893
|
+
setFineTuning(channelNumber, fineTuning) {
|
|
894
|
+
const channel = this.channels[channelNumber];
|
|
895
|
+
const prevFineTuning = channel.fineTuning;
|
|
896
|
+
channel.fineTuning = fineTuning;
|
|
897
|
+
const detuneChange = channel.fineTuning - prevFineTuning;
|
|
898
|
+
this.updateDetune(channel, detuneChange);
|
|
899
|
+
}
|
|
900
|
+
handleCoarseTuningRPN(channelNumber) {
|
|
901
|
+
const channel = this.channels[channelNumber];
|
|
902
|
+
this.limitDataMSB(channel, 0, 127);
|
|
903
|
+
const coarseTuning = channel.dataMSB - 64;
|
|
904
|
+
this.setFineTuning(channelNumber, coarseTuning);
|
|
905
|
+
}
|
|
906
|
+
setCoarseTuning(channelNumber, coarseTuning) {
|
|
907
|
+
const channel = this.channels[channelNumber];
|
|
908
|
+
const prevCoarseTuning = channel.coarseTuning;
|
|
909
|
+
channel.coarseTuning = coarseTuning;
|
|
910
|
+
const detuneChange = channel.coarseTuning - prevCoarseTuning;
|
|
911
|
+
this.updateDetune(channel, detuneChange);
|
|
912
|
+
}
|
|
854
913
|
allSoundOff(channelNumber) {
|
|
855
914
|
const now = this.audioContext.currentTime;
|
|
856
915
|
const channel = this.channels[channelNumber];
|
|
@@ -976,9 +1035,9 @@ Object.defineProperty(MidyGM1, "channelSettings", {
|
|
|
976
1035
|
dataLSB: 0,
|
|
977
1036
|
program: 0,
|
|
978
1037
|
pitchBend: 0,
|
|
979
|
-
fineTuning: 0,
|
|
980
|
-
coarseTuning: 0,
|
|
981
|
-
modulationDepthRange: 0.5,
|
|
1038
|
+
fineTuning: 0, // cb
|
|
1039
|
+
coarseTuning: 0, // cb
|
|
1040
|
+
modulationDepthRange: 0.5, // cb
|
|
982
1041
|
}
|
|
983
1042
|
});
|
|
984
1043
|
Object.defineProperty(MidyGM1, "effectSettings", {
|