@marmooo/midy 0.2.3 → 0.2.4

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
@@ -89,6 +89,12 @@ class Note {
89
89
  writable: true,
90
90
  value: void 0
91
91
  });
92
+ Object.defineProperty(this, "pressure", {
93
+ enumerable: true,
94
+ configurable: true,
95
+ writable: true,
96
+ value: 0
97
+ });
92
98
  this.noteNumber = noteNumber;
93
99
  this.velocity = velocity;
94
100
  this.startTime = startTime;
@@ -100,7 +106,7 @@ class Note {
100
106
  const defaultControllerState = {
101
107
  noteOnVelocity: { type: 2, defaultValue: 0 },
102
108
  noteOnKeyNumber: { type: 3, defaultValue: 0 },
103
- polyPressure: { type: 10, defaultValue: 0 },
109
+ polyphonicKeyPressure: { type: 10, defaultValue: 0 },
104
110
  channelPressure: { type: 13, defaultValue: 0 },
105
111
  pitchWheel: { type: 14, defaultValue: 8192 / 16383 },
106
112
  pitchWheelSensitivity: { type: 16, defaultValue: 2 / 128 },
@@ -432,12 +438,6 @@ class Midy {
432
438
  ...this.setChannelAudioNodes(audioContext),
433
439
  scheduledNotes: new Map(),
434
440
  sostenutoNotes: new Map(),
435
- polyphonicKeyPressure: {
436
- ...this.constructor.controllerDestinationSettings,
437
- },
438
- channelPressure: {
439
- ...this.constructor.controllerDestinationSettings,
440
- },
441
441
  };
442
442
  });
443
443
  return channels;
@@ -942,28 +942,31 @@ class Midy {
942
942
  const pitchWheel = channel.state.pitchWheel * 2 - 1;
943
943
  const pitchWheelSensitivity = channel.state.pitchWheelSensitivity * 12800;
944
944
  const pitch = pitchWheel * pitchWheelSensitivity;
945
- const pressureDepth = (channel.pressureTable[0] - 64) / 37.5; // 2400 / 64;
945
+ const pressureDepth = (channel.channelPressureTable[0] - 64) / 37.5; // 2400 / 64;
946
946
  const pressure = pressureDepth * channel.state.channelPressure;
947
947
  return tuning + pitch + pressure;
948
948
  }
949
949
  calcNoteDetune(channel, note) {
950
950
  return channel.scaleOctaveTuningTable[note.noteNumber % 12];
951
951
  }
952
- updateDetune(channel) {
953
- const now = this.audioContext.currentTime;
952
+ updateChannelDetune(channel) {
954
953
  channel.scheduledNotes.forEach((noteList) => {
955
954
  for (let i = 0; i < noteList.length; i++) {
956
955
  const note = noteList[i];
957
956
  if (!note)
958
957
  continue;
959
- const noteDetune = this.calcNoteDetune(channel, note);
960
- const detune = channel.detune + noteDetune;
961
- note.bufferSource.detune
962
- .cancelScheduledValues(now)
963
- .setValueAtTime(detune, now);
958
+ this.updateDetune(channel, note, 0);
964
959
  }
965
960
  });
966
961
  }
962
+ updateDetune(channel, note, pressure) {
963
+ const now = this.audioContext.currentTime;
964
+ const noteDetune = this.calcNoteDetune(channel, note);
965
+ const detune = channel.detune + noteDetune + pressure;
966
+ note.bufferSource.detune
967
+ .cancelScheduledValues(now)
968
+ .setValueAtTime(detune, now);
969
+ }
967
970
  getPortamentoTime(channel) {
968
971
  const factor = 5 * Math.log(10) / 127;
969
972
  const time = channel.state.portamentoTime;
@@ -981,14 +984,12 @@ class Midy {
981
984
  .setValueAtTime(0, volDelay)
982
985
  .linearRampToValueAtTime(sustainVolume, portamentoTime);
983
986
  }
984
- setVolumeEnvelope(channel, note) {
987
+ setVolumeEnvelope(channel, note, pressure) {
985
988
  const now = this.audioContext.currentTime;
986
989
  const state = channel.state;
987
990
  const { voiceParams, startTime } = note;
988
- const pressureDepth = channel.pressureTable[2] / 64;
989
- const pressure = 1 + pressureDepth * channel.state.channelPressure;
990
991
  const attackVolume = this.cbToRatio(-voiceParams.initialAttenuation) *
991
- pressure;
992
+ (1 + pressure);
992
993
  const sustainVolume = attackVolume * (1 - voiceParams.volSustain);
993
994
  const volDelay = startTime + voiceParams.volDelay;
994
995
  const volAttack = volDelay + voiceParams.volAttack * state.attackTime * 2;
@@ -1036,10 +1037,8 @@ class Midy {
1036
1037
  const { voiceParams, noteNumber, startTime } = note;
1037
1038
  const softPedalFactor = 1 -
1038
1039
  (0.1 + (noteNumber / 127) * 0.2) * state.softPedal;
1039
- const pressureDepth = (channel.pressureTable[1] - 64) * 15;
1040
- const pressure = pressureDepth * channel.state.channelPressure;
1041
- const baseCent = voiceParams.initialFilterFc + pressure;
1042
- const baseFreq = this.centToHz(baseCent) * softPedalFactor *
1040
+ const baseFreq = this.centToHz(voiceParams.initialFilterFc) *
1041
+ softPedalFactor *
1043
1042
  state.brightness * 2;
1044
1043
  const peekFreq = this.centToHz(voiceParams.initialFilterFc + voiceParams.modEnvToFilterFc) * softPedalFactor * state.brightness * 2;
1045
1044
  const sustainFreq = baseFreq +
@@ -1054,15 +1053,17 @@ class Midy {
1054
1053
  .setValueAtTime(adjustedBaseFreq, modDelay)
1055
1054
  .linearRampToValueAtTime(adjustedSustainFreq, portamentoTime);
1056
1055
  }
1057
- setFilterEnvelope(channel, note) {
1056
+ setFilterEnvelope(channel, note, pressure) {
1058
1057
  const now = this.audioContext.currentTime;
1059
1058
  const state = channel.state;
1060
1059
  const { voiceParams, noteNumber, startTime } = note;
1061
1060
  const softPedalFactor = 1 -
1062
1061
  (0.1 + (noteNumber / 127) * 0.2) * state.softPedal;
1063
- const baseFreq = this.centToHz(voiceParams.initialFilterFc) *
1062
+ const baseCent = voiceParams.initialFilterFc + pressure;
1063
+ const baseFreq = this.centToHz(baseCent) * softPedalFactor *
1064
+ state.brightness * 2;
1065
+ const peekFreq = this.centToHz(baseCent + voiceParams.modEnvToFilterFc) *
1064
1066
  softPedalFactor * state.brightness * 2;
1065
- const peekFreq = this.centToHz(voiceParams.initialFilterFc + voiceParams.modEnvToFilterFc) * softPedalFactor * state.brightness * 2;
1066
1067
  const sustainFreq = baseFreq +
1067
1068
  (peekFreq - baseFreq) * (1 - voiceParams.modSustain);
1068
1069
  const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
@@ -1089,9 +1090,9 @@ class Midy {
1089
1090
  gain: voiceParams.modLfoToFilterFc,
1090
1091
  });
1091
1092
  note.modulationDepth = new GainNode(this.audioContext);
1092
- this.setModLfoToPitch(channel, note);
1093
+ this.setModLfoToPitch(channel, note, 0);
1093
1094
  note.volumeDepth = new GainNode(this.audioContext);
1094
- this.setModLfoToVolume(channel, note);
1095
+ this.setModLfoToVolume(note, 0);
1095
1096
  note.modulationLFO.start(startTime + voiceParams.delayModLFO);
1096
1097
  note.modulationLFO.connect(note.filterDepth);
1097
1098
  note.filterDepth.connect(note.filterNode.frequency);
@@ -1104,8 +1105,7 @@ class Midy {
1104
1105
  const { voiceParams } = note;
1105
1106
  const state = channel.state;
1106
1107
  note.vibratoLFO = new OscillatorNode(this.audioContext, {
1107
- frequency: this.centToHz(voiceParams.freqVibLFO) *
1108
- state.vibratoRate,
1108
+ frequency: this.centToHz(voiceParams.freqVibLFO) * state.vibratoRate * 2,
1109
1109
  });
1110
1110
  note.vibratoLFO.start(startTime + voiceParams.delayVibLFO * state.vibratoDelay * 2);
1111
1111
  note.vibratoDepth = new GainNode(this.audioContext);
@@ -1134,8 +1134,8 @@ class Midy {
1134
1134
  }
1135
1135
  else {
1136
1136
  note.portamento = false;
1137
- this.setVolumeEnvelope(channel, note);
1138
- this.setFilterEnvelope(channel, note);
1137
+ this.setVolumeEnvelope(channel, note, 0);
1138
+ this.setFilterEnvelope(channel, note, 0);
1139
1139
  }
1140
1140
  if (0 < state.vibratoDepth) {
1141
1141
  this.startVibrato(channel, note, startTime);
@@ -1350,16 +1350,12 @@ class Midy {
1350
1350
  handlePolyphonicKeyPressure(channelNumber, noteNumber, pressure) {
1351
1351
  const now = this.audioContext.currentTime;
1352
1352
  const channel = this.channels[channelNumber];
1353
- pressure /= 64;
1353
+ channel.state.polyphonicKeyPressure = pressure / 127;
1354
+ const table = channel.polyphonicKeyPressureTable;
1354
1355
  const activeNotes = this.getActiveNotes(channel, now);
1355
- if (channel.polyphonicKeyPressure.amplitudeControl !== 1) {
1356
- if (activeNotes.has(noteNumber)) {
1357
- const activeNote = activeNotes.get(noteNumber);
1358
- const gain = activeNote.gainL.gain.value;
1359
- activeNote.volumeNode.gain
1360
- .cancelScheduledValues(now)
1361
- .setValueAtTime(gain * pressure, now);
1362
- }
1356
+ if (activeNotes.has(noteNumber)) {
1357
+ const note = activeNotes.get(noteNumber);
1358
+ this.applyDestinationSettings(channel, note, table);
1363
1359
  }
1364
1360
  // this.applyVoiceParams(channel, 10);
1365
1361
  }
@@ -1373,11 +1369,11 @@ class Midy {
1373
1369
  const prev = channel.state.channelPressure;
1374
1370
  const next = value / 127;
1375
1371
  channel.state.channelPressure = next;
1376
- if (channel.pressureTable[0] !== 64) {
1377
- const pressureDepth = (channel.pressureTable[0] - 64) / 37.5; // 2400 / 64;
1372
+ if (channel.channelPressureTable[0] !== 64) {
1373
+ const pressureDepth = (channel.channelPressureTable[0] - 64) / 37.5; // 2400 / 64;
1378
1374
  channel.detune += pressureDepth * (next - prev);
1379
1375
  }
1380
- const table = channel.pressureTable;
1376
+ const table = channel.channelPressureTable;
1381
1377
  channel.scheduledNotes.forEach((noteList) => {
1382
1378
  for (let i = 0; i < noteList.length; i++) {
1383
1379
  const note = noteList[i];
@@ -1399,16 +1395,13 @@ class Midy {
1399
1395
  const next = (value - 8192) / 8192;
1400
1396
  state.pitchWheel = value / 16383;
1401
1397
  channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
1402
- this.updateDetune(channel);
1398
+ this.updateChannelDetune(channel);
1403
1399
  this.applyVoiceParams(channel, 14);
1404
1400
  }
1405
- setModLfoToPitch(channel, note) {
1401
+ setModLfoToPitch(channel, note, pressure) {
1406
1402
  const now = this.audioContext.currentTime;
1407
- const pressureDepth = channel.pressureTable[3] / 127 * 600;
1408
- const pressure = pressureDepth * channel.state.channelPressure;
1409
1403
  const modLfoToPitch = note.voiceParams.modLfoToPitch + pressure;
1410
- const baseDepth = Math.abs(modLfoToPitch) +
1411
- channel.state.modulationDepth;
1404
+ const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
1412
1405
  const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
1413
1406
  note.modulationDepth.gain
1414
1407
  .cancelScheduledValues(now)
@@ -1424,22 +1417,18 @@ class Midy {
1424
1417
  .cancelScheduledValues(now)
1425
1418
  .setValueAtTime(vibratoDepth * vibratoDepthSign, now);
1426
1419
  }
1427
- setModLfoToFilterFc(channel, note) {
1420
+ setModLfoToFilterFc(note, pressure) {
1428
1421
  const now = this.audioContext.currentTime;
1429
- const pressureDepth = channel.pressureTable[4] / 127 * 2400;
1430
- const pressure = pressureDepth * channel.state.channelPressure;
1431
1422
  const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc + pressure;
1432
1423
  note.filterDepth.gain
1433
1424
  .cancelScheduledValues(now)
1434
1425
  .setValueAtTime(modLfoToFilterFc, now);
1435
1426
  }
1436
- setModLfoToVolume(channel, note) {
1427
+ setModLfoToVolume(note, pressure) {
1437
1428
  const now = this.audioContext.currentTime;
1438
1429
  const modLfoToVolume = note.voiceParams.modLfoToVolume;
1439
1430
  const baseDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
1440
- const pressureDepth = channel.pressureTable[5] / 127;
1441
- const pressure = 1 + pressureDepth * channel.state.channelPressure;
1442
- const volumeDepth = baseDepth * Math.sign(modLfoToVolume) * pressure;
1431
+ const volumeDepth = baseDepth * Math.sign(modLfoToVolume) * (1 + pressure);
1443
1432
  note.volumeDepth.gain
1444
1433
  .cancelScheduledValues(now)
1445
1434
  .setValueAtTime(volumeDepth, now);
@@ -1512,11 +1501,18 @@ class Midy {
1512
1501
  .cancelScheduledValues(now)
1513
1502
  .setValueAtTime(freqModLFO, now);
1514
1503
  }
1504
+ setFreqVibLFO(channel, note) {
1505
+ const now = this.audioContext.currentTime;
1506
+ const freqVibLFO = note.voiceParams.freqVibLFO;
1507
+ note.vibratoLFO.frequency
1508
+ .cancelScheduledValues(now)
1509
+ .setValueAtTime(freqVibLFO * channel.state.vibratoRate * 2, now);
1510
+ }
1515
1511
  createVoiceParamsHandlers() {
1516
1512
  return {
1517
1513
  modLfoToPitch: (channel, note, _prevValue) => {
1518
1514
  if (0 < channel.state.modulationDepth) {
1519
- this.setModLfoToPitch(channel, note);
1515
+ this.setModLfoToPitch(channel, note, 0);
1520
1516
  }
1521
1517
  },
1522
1518
  vibLfoToPitch: (channel, note, _prevValue) => {
@@ -1526,12 +1522,12 @@ class Midy {
1526
1522
  },
1527
1523
  modLfoToFilterFc: (channel, note, _prevValue) => {
1528
1524
  if (0 < channel.state.modulationDepth) {
1529
- this.setModLfoToFilterFc(channel, note);
1525
+ this.setModLfoToFilterFc(note, 0);
1530
1526
  }
1531
1527
  },
1532
1528
  modLfoToVolume: (channel, note, _prevValue) => {
1533
1529
  if (0 < channel.state.modulationDepth) {
1534
- this.setModLfoToVolume(channel, note);
1530
+ this.setModLfoToVolume(note, 0);
1535
1531
  }
1536
1532
  },
1537
1533
  chorusEffectsSend: (channel, note, prevValue) => {
@@ -1557,11 +1553,7 @@ class Midy {
1557
1553
  },
1558
1554
  freqVibLFO: (channel, note, _prevValue) => {
1559
1555
  if (0 < channel.state.vibratoDepth) {
1560
- const now = this.audioContext.currentTime;
1561
- const freqVibLFO = note.voiceParams.freqVibLFO;
1562
- note.vibratoLFO.frequency
1563
- .cancelScheduledValues(now)
1564
- .setValueAtTime(freqVibLFO * channel.state.vibratoRate, now);
1556
+ this.setFreqVibLFO(channel, note);
1565
1557
  }
1566
1558
  },
1567
1559
  };
@@ -1605,7 +1597,7 @@ class Midy {
1605
1597
  this.setPortamentoStartFilterEnvelope(channel, note);
1606
1598
  }
1607
1599
  else {
1608
- this.setFilterEnvelope(channel, note);
1600
+ this.setFilterEnvelope(channel, note, 0);
1609
1601
  }
1610
1602
  this.setPitchEnvelope(note);
1611
1603
  }
@@ -1619,7 +1611,7 @@ class Midy {
1619
1611
  if (key in voiceParams)
1620
1612
  noteVoiceParams[key] = voiceParams[key];
1621
1613
  }
1622
- this.setVolumeEnvelope(channel, note);
1614
+ this.setVolumeEnvelope(channel, note, 0);
1623
1615
  }
1624
1616
  }
1625
1617
  }
@@ -1840,7 +1832,7 @@ class Midy {
1840
1832
  continue;
1841
1833
  if (note.startTime < now)
1842
1834
  continue;
1843
- this.setVolumeEnvelope(channel, note);
1835
+ this.setVolumeEnvelope(channel, note, 0);
1844
1836
  }
1845
1837
  });
1846
1838
  }
@@ -1852,7 +1844,12 @@ class Midy {
1852
1844
  const note = noteList[i];
1853
1845
  if (!note)
1854
1846
  continue;
1855
- this.setFilterEnvelope(channel, note);
1847
+ if (note.portamento) {
1848
+ this.setPortamentoStartFilterEnvelope(channel, note);
1849
+ }
1850
+ else {
1851
+ this.setFilterEnvelope(channel, note, 0);
1852
+ }
1856
1853
  }
1857
1854
  });
1858
1855
  }
@@ -1864,7 +1861,7 @@ class Midy {
1864
1861
  const note = noteList[i];
1865
1862
  if (!note)
1866
1863
  continue;
1867
- this.setVolumeEnvelope(channel, note);
1864
+ this.setVolumeEnvelope(channel, note, 0);
1868
1865
  }
1869
1866
  });
1870
1867
  }
@@ -1873,21 +1870,53 @@ class Midy {
1873
1870
  channel.state.vibratoRate = vibratoRate / 64;
1874
1871
  if (channel.vibratoDepth <= 0)
1875
1872
  return;
1876
- const now = this.audioContext.currentTime;
1877
- const activeNotes = this.getActiveNotes(channel, now);
1878
- activeNotes.forEach((activeNote) => {
1879
- activeNote.vibratoLFO.frequency
1880
- .cancelScheduledValues(now)
1881
- .setValueAtTime(channel.state.vibratoRate, now);
1873
+ channel.scheduledNotes.forEach((noteList) => {
1874
+ for (let i = 0; i < noteList.length; i++) {
1875
+ const note = noteList[i];
1876
+ if (!note)
1877
+ continue;
1878
+ this.setVibLfoToPitch(channel, note);
1879
+ }
1882
1880
  });
1883
1881
  }
1884
1882
  setVibratoDepth(channelNumber, vibratoDepth) {
1885
1883
  const channel = this.channels[channelNumber];
1884
+ const prev = channel.state.vibratoDepth;
1886
1885
  channel.state.vibratoDepth = vibratoDepth / 64;
1886
+ if (0 < prev) {
1887
+ channel.scheduledNotes.forEach((noteList) => {
1888
+ for (let i = 0; i < noteList.length; i++) {
1889
+ const note = noteList[i];
1890
+ if (!note)
1891
+ continue;
1892
+ this.setFreqVibLFO(channel, note);
1893
+ }
1894
+ });
1895
+ }
1896
+ else {
1897
+ channel.scheduledNotes.forEach((noteList) => {
1898
+ for (let i = 0; i < noteList.length; i++) {
1899
+ const note = noteList[i];
1900
+ if (!note)
1901
+ continue;
1902
+ this.startVibrato(channel, note, note.startTime);
1903
+ }
1904
+ });
1905
+ }
1887
1906
  }
1888
1907
  setVibratoDelay(channelNumber, vibratoDelay) {
1889
1908
  const channel = this.channels[channelNumber];
1890
1909
  channel.state.vibratoDelay = vibratoDelay / 64;
1910
+ if (0 < channel.state.vibratoDepth) {
1911
+ channel.scheduledNotes.forEach((noteList) => {
1912
+ for (let i = 0; i < noteList.length; i++) {
1913
+ const note = noteList[i];
1914
+ if (!note)
1915
+ continue;
1916
+ this.startVibrato(channel, note, note.startTime);
1917
+ }
1918
+ });
1919
+ }
1891
1920
  }
1892
1921
  setReverbSendLevel(channelNumber, reverbSendLevel) {
1893
1922
  const channel = this.channels[channelNumber];
@@ -2052,7 +2081,7 @@ class Midy {
2052
2081
  const next = value / 128;
2053
2082
  state.pitchWheelSensitivity = next;
2054
2083
  channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
2055
- this.updateDetune(channel);
2084
+ this.updateChannelDetune(channel);
2056
2085
  this.applyVoiceParams(channel, 16);
2057
2086
  }
2058
2087
  handleFineTuningRPN(channelNumber) {
@@ -2067,7 +2096,7 @@ class Midy {
2067
2096
  const next = (value - 8192) / 8.192; // cent
2068
2097
  channel.fineTuning = next;
2069
2098
  channel.detune += next - prev;
2070
- this.updateDetune(channel);
2099
+ this.updateChannelDetune(channel);
2071
2100
  }
2072
2101
  handleCoarseTuningRPN(channelNumber) {
2073
2102
  const channel = this.channels[channelNumber];
@@ -2081,7 +2110,7 @@ class Midy {
2081
2110
  const next = (value - 64) * 100; // cent
2082
2111
  channel.coarseTuning = next;
2083
2112
  channel.detune += next - prev;
2084
- this.updateDetune(channel);
2113
+ this.updateChannelDetune(channel);
2085
2114
  }
2086
2115
  handleModulationDepthRangeRPN(channelNumber) {
2087
2116
  const channel = this.channels[channelNumber];
@@ -2112,7 +2141,7 @@ class Midy {
2112
2141
  const state = channel.state;
2113
2142
  for (let i = 0; i < stateTypes.length; i++) {
2114
2143
  const type = stateTypes[i];
2115
- state[type] = defaultControllerState[type];
2144
+ state[type] = defaultControllerState[type].defaultValue;
2116
2145
  }
2117
2146
  const settingTypes = [
2118
2147
  "rpnMSB",
@@ -2215,7 +2244,9 @@ class Midy {
2215
2244
  case 9:
2216
2245
  switch (data[3]) {
2217
2246
  case 1: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
2218
- return this.handleChannelPressureSysEx(data);
2247
+ return this.handlePressureSysEx(data, "channelPressureTable");
2248
+ case 2: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
2249
+ return this.handlePressureSysEx(data, "polyphonicKeyPressureTable");
2219
2250
  case 3: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
2220
2251
  return this.handleControlChangeSysEx(data);
2221
2252
  default:
@@ -2257,7 +2288,7 @@ class Midy {
2257
2288
  const next = (value - 8192) / 8.192; // cent
2258
2289
  this.masterFineTuning = next;
2259
2290
  channel.detune += next - prev;
2260
- this.updateDetune(channel);
2291
+ this.updateChannelDetune(channel);
2261
2292
  }
2262
2293
  handleMasterCoarseTuningSysEx(data) {
2263
2294
  const coarseTuning = data[4];
@@ -2268,7 +2299,7 @@ class Midy {
2268
2299
  const next = (value - 64) * 100; // cent
2269
2300
  this.masterCoarseTuning = next;
2270
2301
  channel.detune += next - prev;
2271
- this.updateDetune(channel);
2302
+ this.updateChannelDetune(channel);
2272
2303
  }
2273
2304
  handleGlobalParameterControlSysEx(data) {
2274
2305
  if (data[7] === 1) {
@@ -2492,29 +2523,63 @@ class Midy {
2492
2523
  }
2493
2524
  applyDestinationSettings(channel, note, table) {
2494
2525
  if (table[0] !== 64) {
2495
- this.updateDetune(channel);
2526
+ const polyphonicKeyPressure = (0 < note.pressure)
2527
+ ? channel.polyphonicKeyPressureTable[0] * note.pressure
2528
+ : 0;
2529
+ const pressure = (polyphonicKeyPressure - 64) / 37.5; // 2400 / 64;
2530
+ this.updateDetune(channel, note, pressure);
2496
2531
  }
2497
2532
  if (!note.portamento) {
2498
2533
  if (table[1] !== 64) {
2499
- this.setFilterEnvelope(channel, note);
2534
+ const channelPressure = channel.channelPressureTable[1] *
2535
+ channel.state.channelPressure;
2536
+ const polyphonicKeyPressure = (0 < note.pressure)
2537
+ ? channel.polyphonicKeyPressureTable[1] * note.pressure
2538
+ : 0;
2539
+ const pressure = (channelPressure + polyphonicKeyPressure - 128) * 15;
2540
+ this.setFilterEnvelope(channel, note, pressure);
2500
2541
  }
2501
2542
  if (table[2] !== 64) {
2502
- this.setVolumeEnvelope(channel, note);
2543
+ const channelPressure = channel.channelPressureTable[2] *
2544
+ channel.state.channelPressure;
2545
+ const polyphonicKeyPressure = (0 < note.pressure)
2546
+ ? channel.polyphonicKeyPressureTable[2] * note.pressure
2547
+ : 0;
2548
+ const pressure = (channelPressure + polyphonicKeyPressure) / 128;
2549
+ this.setVolumeEnvelope(channel, note, pressure);
2503
2550
  }
2504
2551
  }
2505
2552
  if (table[3] !== 0) {
2506
- this.setModLfoToPitch(channel, note);
2553
+ const channelPressure = channel.channelPressureTable[3] *
2554
+ channel.state.channelPressure;
2555
+ const polyphonicKeyPressure = (0 < note.pressure)
2556
+ ? channel.polyphonicKeyPressureTable[3] * note.pressure
2557
+ : 0;
2558
+ const pressure = (channelPressure + polyphonicKeyPressure) / 254 * 600;
2559
+ this.setModLfoToPitch(channel, note, pressure);
2507
2560
  }
2508
2561
  if (table[4] !== 0) {
2509
- this.setModLfoToFilterFc(channel, note);
2562
+ const channelPressure = channel.channelPressureTable[4] *
2563
+ channel.state.channelPressure;
2564
+ const polyphonicKeyPressure = (0 < note.pressure)
2565
+ ? channel.polyphonicKeyPressureTable[4] * note.pressure
2566
+ : 0;
2567
+ const pressure = (channelPressure + polyphonicKeyPressure) / 254 * 2400;
2568
+ this.setModLfoToFilterFc(note, pressure);
2510
2569
  }
2511
2570
  if (table[5] !== 0) {
2512
- this.setModLfoToVolume(channel, note);
2571
+ const channelPressure = channel.channelPressureTable[5] *
2572
+ channel.state.channelPressure;
2573
+ const polyphonicKeyPressure = (0 < note.pressure)
2574
+ ? channel.polyphonicKeyPressureTable[5] * note.pressure
2575
+ : 0;
2576
+ const pressure = (channelPressure + polyphonicKeyPressure) / 254;
2577
+ this.setModLfoToVolume(note, pressure);
2513
2578
  }
2514
2579
  }
2515
- handleChannelPressureSysEx(data) {
2580
+ handleChannelPressureSysEx(data, tableName) {
2516
2581
  const channelNumber = data[4];
2517
- const table = this.channels[channelNumber].pressureTable;
2582
+ const table = this.channels[channelNumber][tableName];
2518
2583
  for (let i = 5; i < data.length - 1; i += 2) {
2519
2584
  const pp = data[i];
2520
2585
  const rr = data[i + 1];
@@ -2606,7 +2671,8 @@ Object.defineProperty(Midy, "channelSettings", {
2606
2671
  currentBufferSource: null,
2607
2672
  detune: 0,
2608
2673
  scaleOctaveTuningTable: new Array(12).fill(0), // cent
2609
- pressureTable: new Uint8Array([64, 64, 64, 0, 0, 0]),
2674
+ channelPressureTable: new Uint8Array([64, 64, 64, 0, 0, 0]),
2675
+ polyphonicKeyPressureTable: new Uint8Array([64, 64, 64, 0, 0, 0]),
2610
2676
  keyBasedInstrumentControlTable: new Int8Array(128 * 128), // [-64, 63]
2611
2677
  program: 0,
2612
2678
  bank: 121 * 128,
@@ -2621,16 +2687,3 @@ Object.defineProperty(Midy, "channelSettings", {
2621
2687
  modulationDepthRange: 50, // cent
2622
2688
  }
2623
2689
  });
2624
- Object.defineProperty(Midy, "controllerDestinationSettings", {
2625
- enumerable: true,
2626
- configurable: true,
2627
- writable: true,
2628
- value: {
2629
- pitchControl: 0,
2630
- filterCutoffControl: 0,
2631
- amplitudeControl: 1,
2632
- lfoPitchDepth: 0,
2633
- lfoFilterDepth: 0,
2634
- lfoAmplitudeDepth: 0,
2635
- }
2636
- });