@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/esm/midy-GM1.d.ts +2 -1
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +16 -13
- package/esm/midy-GM2.d.ts +12 -19
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +78 -108
- package/esm/midy-GMLite.d.ts +3 -2
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +18 -13
- package/esm/midy.d.ts +14 -18
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +158 -105
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +2 -1
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +16 -13
- package/script/midy-GM2.d.ts +12 -19
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +78 -108
- package/script/midy-GMLite.d.ts +3 -2
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +18 -13
- package/script/midy.d.ts +14 -18
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +158 -105
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1040
|
-
|
|
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
|
|
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(
|
|
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
|
|
1353
|
+
channel.state.polyphonicKeyPressure = pressure / 127;
|
|
1354
|
+
const table = channel.polyphonicKeyPressureTable;
|
|
1354
1355
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1355
|
-
if (
|
|
1356
|
-
|
|
1357
|
-
|
|
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.
|
|
1377
|
-
const pressureDepth = (channel.
|
|
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.
|
|
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.
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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]
|
|
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
|
-
|
|
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
|
-
});
|