@marmooo/midy 0.0.7 → 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/script/midy.js CHANGED
@@ -78,13 +78,13 @@ class Midy {
78
78
  configurable: true,
79
79
  writable: true,
80
80
  value: 0
81
- });
81
+ }); // cb
82
82
  Object.defineProperty(this, "masterCoarseTuning", {
83
83
  enumerable: true,
84
84
  configurable: true,
85
85
  writable: true,
86
86
  value: 0
87
- });
87
+ }); // cb
88
88
  Object.defineProperty(this, "mono", {
89
89
  enumerable: true,
90
90
  configurable: true,
@@ -751,7 +751,7 @@ class Midy {
751
751
  startModulation(channel, note, time) {
752
752
  const { instrumentKey } = note;
753
753
  note.modLFOGain = new GainNode(this.audioContext, {
754
- gain: this.cbToRatio(instrumentKey.modLfoToVolume) * channel.modulation,
754
+ gain: this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation),
755
755
  });
756
756
  note.modLFO = new OscillatorNode(this.audioContext, {
757
757
  frequency: this.centToHz(instrumentKey.freqModLFO),
@@ -998,7 +998,7 @@ class Midy {
998
998
  case 5:
999
999
  return this.setPortamentoTime(channelNumber, value);
1000
1000
  case 6:
1001
- return this.setDataEntry(channelNumber, value, true);
1001
+ return this.dataEntryMSB(channelNumber, value);
1002
1002
  case 7:
1003
1003
  return this.setVolume(channelNumber, value);
1004
1004
  case 10:
@@ -1008,7 +1008,7 @@ class Midy {
1008
1008
  case 32:
1009
1009
  return this.setBankLSB(channelNumber, value);
1010
1010
  case 38:
1011
- return this.setDataEntry(channelNumber, value, false);
1011
+ return this.dataEntryLSB(channelNumber, value);
1012
1012
  case 64:
1013
1013
  return this.setSustainPedal(channelNumber, value);
1014
1014
  case 65:
@@ -1025,13 +1025,13 @@ class Midy {
1025
1025
  case 78:
1026
1026
  return this.setVibratoDelay(channelNumber, value);
1027
1027
  case 91:
1028
- return this.setReverb(channelNumber, value);
1028
+ return this.setReverbSendLevel(channelNumber, value);
1029
1029
  case 93:
1030
- return this.setChorus(channelNumber, value);
1030
+ return this.setChorusSendLevel(channelNumber, value);
1031
1031
  case 96: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp18.pdf
1032
- return incrementRPNValue(channelNumber);
1032
+ return this.dataIncrement(channelNumber);
1033
1033
  case 97: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp18.pdf
1034
- return decrementRPNValue(channelNumber);
1034
+ return this.dataDecrement(channelNumber);
1035
1035
  case 100:
1036
1036
  return this.setRPNLSB(channelNumber, value);
1037
1037
  case 101:
@@ -1057,22 +1057,24 @@ class Midy {
1057
1057
  setBankMSB(channelNumber, msb) {
1058
1058
  this.channels[channelNumber].bankMSB = msb;
1059
1059
  }
1060
- setModulation(channelNumber, modulation) {
1060
+ updateModulation(channel) {
1061
1061
  const now = this.audioContext.currentTime;
1062
- const channel = this.channels[channelNumber];
1063
- channel.modulation = (modulation / 127) *
1064
- (channel.modulationDepthRange * 100);
1065
1062
  const activeNotes = this.getActiveNotes(channel, now);
1066
1063
  activeNotes.forEach((activeNote) => {
1067
1064
  if (activeNote.modLFO) {
1068
- activeNote.gainNode.gain.setValueAtTime(this.cbToRatio(activeNote.instrumentKey.modLfoToVolume) *
1069
- channel.modulation, now);
1065
+ const { gainNode, instrumentKey } = activeNote;
1066
+ gainNode.gain.setValueAtTime(this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation), now);
1070
1067
  }
1071
1068
  else {
1072
1069
  this.startModulation(channel, activeNote, now);
1073
1070
  }
1074
1071
  });
1075
1072
  }
1073
+ setModulation(channelNumber, modulation) {
1074
+ const channel = this.channels[channelNumber];
1075
+ channel.modulation = (modulation / 127) * channel.modulationDepthRange;
1076
+ this.updateModulation(channel);
1077
+ }
1076
1078
  setPortamentoTime(channelNumber, portamentoTime) {
1077
1079
  this.channels[channelNumber].portamentoTime = portamentoTime / 127;
1078
1080
  }
@@ -1101,6 +1103,10 @@ class Midy {
1101
1103
  setBankLSB(channelNumber, lsb) {
1102
1104
  this.channels[channelNumber].bankLSB = lsb;
1103
1105
  }
1106
+ dataEntryLSB(channelNumber, value) {
1107
+ this.channels[channelNumber].dataLSB = value;
1108
+ this.handleRPN(channelNumber, 0);
1109
+ }
1104
1110
  updateChannelGain(channel) {
1105
1111
  const now = this.audioContext.currentTime;
1106
1112
  const volume = channel.volume * channel.expression;
@@ -1122,7 +1128,7 @@ class Midy {
1122
1128
  setPortamento(channelNumber, value) {
1123
1129
  this.channels[channelNumber].portamento = value >= 64;
1124
1130
  }
1125
- setReverb(channelNumber, reverb) {
1131
+ setReverbSendLevel(channelNumber, reverb) {
1126
1132
  const now = this.audioContext.currentTime;
1127
1133
  const channel = this.channels[channelNumber];
1128
1134
  const reverbEffect = channel.reverbEffect;
@@ -1132,7 +1138,7 @@ class Midy {
1132
1138
  reverbEffect.wetGain.gain.cancelScheduledValues(now);
1133
1139
  reverbEffect.wetGain.gain.setValueAtTime(channel.reverb, now);
1134
1140
  }
1135
- setChorus(channelNumber, chorus) {
1141
+ setChorusSendLevel(channelNumber, chorus) {
1136
1142
  const channel = this.channels[channelNumber];
1137
1143
  channel.chorus = chorus / 127;
1138
1144
  channel.chorusEffect.lfoGain = channel.chorus;
@@ -1198,31 +1204,34 @@ class Midy {
1198
1204
  channel.dataMSB = minMSB;
1199
1205
  }
1200
1206
  }
1201
- // TODO: support 3-4?
1202
1207
  handleRPN(channelNumber, value) {
1203
1208
  const channel = this.channels[channelNumber];
1204
1209
  const rpn = channel.rpnMSB * 128 + channel.rpnLSB;
1205
1210
  switch (rpn) {
1206
1211
  case 0:
1207
1212
  channel.dataLSB += value;
1208
- this.handlePitchBendRangeMessage(channelNumber);
1213
+ this.handlePitchBendRangeRPN(channelNumber);
1209
1214
  break;
1210
1215
  case 1:
1211
1216
  channel.dataLSB += value;
1212
- this.handleFineTuningMessage(channelNumber);
1217
+ this.handleFineTuningRPN(channelNumber);
1213
1218
  break;
1214
1219
  case 2:
1215
1220
  channel.dataMSB += value;
1216
- this.handleCoarseTuningMessage(channelNumber);
1221
+ this.handleCoarseTuningRPN(channelNumber);
1222
+ break;
1223
+ case 5:
1224
+ channel.dataLSB += value;
1225
+ this.handleModulationDepthRangeRPN(channelNumber);
1217
1226
  break;
1218
1227
  default:
1219
1228
  console.warn(`Channel ${channelNumber}: Unsupported RPN MSB=${channel.rpnMSB} LSB=${channel.rpnLSB}`);
1220
1229
  }
1221
1230
  }
1222
- incrementRPNValue(channelNumber) {
1231
+ dataIncrement(channelNumber) {
1223
1232
  this.handleRPN(channelNumber, 1);
1224
1233
  }
1225
- decrementRPNValue(channelNumber) {
1234
+ dataDecrement(channelNumber) {
1226
1235
  this.handleRPN(channelNumber, -1);
1227
1236
  }
1228
1237
  setRPNMSB(channelNumber, value) {
@@ -1231,9 +1240,8 @@ class Midy {
1231
1240
  setRPNLSB(channelNumber, value) {
1232
1241
  this.channels[channelNumber].rpnLSB = value;
1233
1242
  }
1234
- setDataEntry(channelNumber, value, isMSB) {
1235
- const channel = this.channels[channelNumber];
1236
- isMSB ? channel.dataMSB = value : channel.dataLSB = value;
1243
+ dataEntryMSB(channelNumber, value) {
1244
+ this.channels[channelNumber].dataMSB = value;
1237
1245
  this.handleRPN(channelNumber, 0);
1238
1246
  }
1239
1247
  updateDetune(channel, detuneChange) {
@@ -1247,7 +1255,7 @@ class Midy {
1247
1255
  .setValueAtTime(detune, now);
1248
1256
  });
1249
1257
  }
1250
- handlePitchBendRangeMessage(channelNumber) {
1258
+ handlePitchBendRangeRPN(channelNumber) {
1251
1259
  const channel = this.channels[channelNumber];
1252
1260
  this.limitData(channel, 0, 127, 0, 99);
1253
1261
  const pitchBendRange = channel.dataMSB + channel.dataLSB / 100;
@@ -1261,7 +1269,7 @@ class Midy {
1261
1269
  channel.pitchBend * 100;
1262
1270
  this.updateDetune(channel, detuneChange);
1263
1271
  }
1264
- handleFineTuningMessage(channelNumber) {
1272
+ handleFineTuningRPN(channelNumber) {
1265
1273
  const channel = this.channels[channelNumber];
1266
1274
  this.limitData(channel, 0, 127, 0, 127);
1267
1275
  const fineTuning = (channel.dataMSB * 128 + channel.dataLSB - 8192) / 8192;
@@ -1269,9 +1277,12 @@ class Midy {
1269
1277
  }
1270
1278
  setFineTuning(channelNumber, fineTuning) {
1271
1279
  const channel = this.channels[channelNumber];
1280
+ const prevFineTuning = channel.fineTuning;
1272
1281
  channel.fineTuning = fineTuning;
1282
+ const detuneChange = channel.fineTuning - prevFineTuning;
1283
+ this.updateDetune(channel, detuneChange);
1273
1284
  }
1274
- handleCoarseTuningMessage(channelNumber) {
1285
+ handleCoarseTuningRPN(channelNumber) {
1275
1286
  const channel = this.channels[channelNumber];
1276
1287
  this.limitDataMSB(channel, 0, 127);
1277
1288
  const coarseTuning = channel.dataMSB - 64;
@@ -1279,7 +1290,22 @@ class Midy {
1279
1290
  }
1280
1291
  setCoarseTuning(channelNumber, coarseTuning) {
1281
1292
  const channel = this.channels[channelNumber];
1282
- channel.fineTuning = coarseTuning;
1293
+ const prevCoarseTuning = channel.coarseTuning;
1294
+ channel.coarseTuning = coarseTuning;
1295
+ const detuneChange = channel.coarseTuning - prevCoarseTuning;
1296
+ this.updateDetune(channel, detuneChange);
1297
+ }
1298
+ handleModulationDepthRangeRPN(channelNumber) {
1299
+ const channel = this.channels[channelNumber];
1300
+ this.limitData(channel, 0, 127, 0, 127);
1301
+ const modulationDepthRange = dataMSB + dataLSB / 128;
1302
+ this.setModulationDepthRange(channelNumber, modulationDepthRange);
1303
+ }
1304
+ setModulationDepthRange(channelNumber, modulationDepthRange) {
1305
+ const channel = this.channels[channelNumber];
1306
+ channel.modulationDepthRange = modulationDepthRange;
1307
+ channel.modulation = (modulation / 127) * channel.modulationDepthRange;
1308
+ this.updateModulation(channel);
1283
1309
  }
1284
1310
  allSoundOff(channelNumber) {
1285
1311
  const now = this.audioContext.currentTime;
@@ -1370,9 +1396,9 @@ class Midy {
1370
1396
  switch (data[3]) {
1371
1397
  case 1:
1372
1398
  return this.handleMasterVolumeSysEx(data);
1373
- case 3:
1399
+ case 3: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
1374
1400
  return this.handleMasterFineTuningSysEx(data);
1375
- case 4:
1401
+ case 4: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
1376
1402
  return this.handleMasterCoarseTuningSysEx(data);
1377
1403
  // case 5: // TODO: Global Parameter Control
1378
1404
  default:
@@ -1498,9 +1524,9 @@ Object.defineProperty(Midy, "channelSettings", {
1498
1524
  dataLSB: 0,
1499
1525
  program: 0,
1500
1526
  pitchBend: 0,
1501
- fineTuning: 0,
1502
- coarseTuning: 0,
1503
- modulationDepthRange: 0.5,
1527
+ fineTuning: 0, // cb
1528
+ coarseTuning: 0, // cb
1529
+ modulationDepthRange: 0.5, // cb
1504
1530
  }
1505
1531
  });
1506
1532
  Object.defineProperty(Midy, "effectSettings", {