@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/esm/midy.js
CHANGED
|
@@ -86,6 +86,12 @@ class Note {
|
|
|
86
86
|
writable: true,
|
|
87
87
|
value: void 0
|
|
88
88
|
});
|
|
89
|
+
Object.defineProperty(this, "pressure", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
configurable: true,
|
|
92
|
+
writable: true,
|
|
93
|
+
value: 0
|
|
94
|
+
});
|
|
89
95
|
this.noteNumber = noteNumber;
|
|
90
96
|
this.velocity = velocity;
|
|
91
97
|
this.startTime = startTime;
|
|
@@ -97,7 +103,7 @@ class Note {
|
|
|
97
103
|
const defaultControllerState = {
|
|
98
104
|
noteOnVelocity: { type: 2, defaultValue: 0 },
|
|
99
105
|
noteOnKeyNumber: { type: 3, defaultValue: 0 },
|
|
100
|
-
|
|
106
|
+
polyphonicKeyPressure: { type: 10, defaultValue: 0 },
|
|
101
107
|
channelPressure: { type: 13, defaultValue: 0 },
|
|
102
108
|
pitchWheel: { type: 14, defaultValue: 8192 / 16383 },
|
|
103
109
|
pitchWheelSensitivity: { type: 16, defaultValue: 2 / 128 },
|
|
@@ -429,12 +435,6 @@ export class Midy {
|
|
|
429
435
|
...this.setChannelAudioNodes(audioContext),
|
|
430
436
|
scheduledNotes: new Map(),
|
|
431
437
|
sostenutoNotes: new Map(),
|
|
432
|
-
polyphonicKeyPressure: {
|
|
433
|
-
...this.constructor.controllerDestinationSettings,
|
|
434
|
-
},
|
|
435
|
-
channelPressure: {
|
|
436
|
-
...this.constructor.controllerDestinationSettings,
|
|
437
|
-
},
|
|
438
438
|
};
|
|
439
439
|
});
|
|
440
440
|
return channels;
|
|
@@ -939,28 +939,31 @@ export class Midy {
|
|
|
939
939
|
const pitchWheel = channel.state.pitchWheel * 2 - 1;
|
|
940
940
|
const pitchWheelSensitivity = channel.state.pitchWheelSensitivity * 12800;
|
|
941
941
|
const pitch = pitchWheel * pitchWheelSensitivity;
|
|
942
|
-
const pressureDepth = (channel.
|
|
942
|
+
const pressureDepth = (channel.channelPressureTable[0] - 64) / 37.5; // 2400 / 64;
|
|
943
943
|
const pressure = pressureDepth * channel.state.channelPressure;
|
|
944
944
|
return tuning + pitch + pressure;
|
|
945
945
|
}
|
|
946
946
|
calcNoteDetune(channel, note) {
|
|
947
947
|
return channel.scaleOctaveTuningTable[note.noteNumber % 12];
|
|
948
948
|
}
|
|
949
|
-
|
|
950
|
-
const now = this.audioContext.currentTime;
|
|
949
|
+
updateChannelDetune(channel) {
|
|
951
950
|
channel.scheduledNotes.forEach((noteList) => {
|
|
952
951
|
for (let i = 0; i < noteList.length; i++) {
|
|
953
952
|
const note = noteList[i];
|
|
954
953
|
if (!note)
|
|
955
954
|
continue;
|
|
956
|
-
|
|
957
|
-
const detune = channel.detune + noteDetune;
|
|
958
|
-
note.bufferSource.detune
|
|
959
|
-
.cancelScheduledValues(now)
|
|
960
|
-
.setValueAtTime(detune, now);
|
|
955
|
+
this.updateDetune(channel, note, 0);
|
|
961
956
|
}
|
|
962
957
|
});
|
|
963
958
|
}
|
|
959
|
+
updateDetune(channel, note, pressure) {
|
|
960
|
+
const now = this.audioContext.currentTime;
|
|
961
|
+
const noteDetune = this.calcNoteDetune(channel, note);
|
|
962
|
+
const detune = channel.detune + noteDetune + pressure;
|
|
963
|
+
note.bufferSource.detune
|
|
964
|
+
.cancelScheduledValues(now)
|
|
965
|
+
.setValueAtTime(detune, now);
|
|
966
|
+
}
|
|
964
967
|
getPortamentoTime(channel) {
|
|
965
968
|
const factor = 5 * Math.log(10) / 127;
|
|
966
969
|
const time = channel.state.portamentoTime;
|
|
@@ -978,14 +981,12 @@ export class Midy {
|
|
|
978
981
|
.setValueAtTime(0, volDelay)
|
|
979
982
|
.linearRampToValueAtTime(sustainVolume, portamentoTime);
|
|
980
983
|
}
|
|
981
|
-
setVolumeEnvelope(channel, note) {
|
|
984
|
+
setVolumeEnvelope(channel, note, pressure) {
|
|
982
985
|
const now = this.audioContext.currentTime;
|
|
983
986
|
const state = channel.state;
|
|
984
987
|
const { voiceParams, startTime } = note;
|
|
985
|
-
const pressureDepth = channel.pressureTable[2] / 64;
|
|
986
|
-
const pressure = 1 + pressureDepth * channel.state.channelPressure;
|
|
987
988
|
const attackVolume = this.cbToRatio(-voiceParams.initialAttenuation) *
|
|
988
|
-
pressure;
|
|
989
|
+
(1 + pressure);
|
|
989
990
|
const sustainVolume = attackVolume * (1 - voiceParams.volSustain);
|
|
990
991
|
const volDelay = startTime + voiceParams.volDelay;
|
|
991
992
|
const volAttack = volDelay + voiceParams.volAttack * state.attackTime * 2;
|
|
@@ -1033,10 +1034,8 @@ export class Midy {
|
|
|
1033
1034
|
const { voiceParams, noteNumber, startTime } = note;
|
|
1034
1035
|
const softPedalFactor = 1 -
|
|
1035
1036
|
(0.1 + (noteNumber / 127) * 0.2) * state.softPedal;
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1038
|
-
const baseCent = voiceParams.initialFilterFc + pressure;
|
|
1039
|
-
const baseFreq = this.centToHz(baseCent) * softPedalFactor *
|
|
1037
|
+
const baseFreq = this.centToHz(voiceParams.initialFilterFc) *
|
|
1038
|
+
softPedalFactor *
|
|
1040
1039
|
state.brightness * 2;
|
|
1041
1040
|
const peekFreq = this.centToHz(voiceParams.initialFilterFc + voiceParams.modEnvToFilterFc) * softPedalFactor * state.brightness * 2;
|
|
1042
1041
|
const sustainFreq = baseFreq +
|
|
@@ -1051,15 +1050,17 @@ export class Midy {
|
|
|
1051
1050
|
.setValueAtTime(adjustedBaseFreq, modDelay)
|
|
1052
1051
|
.linearRampToValueAtTime(adjustedSustainFreq, portamentoTime);
|
|
1053
1052
|
}
|
|
1054
|
-
setFilterEnvelope(channel, note) {
|
|
1053
|
+
setFilterEnvelope(channel, note, pressure) {
|
|
1055
1054
|
const now = this.audioContext.currentTime;
|
|
1056
1055
|
const state = channel.state;
|
|
1057
1056
|
const { voiceParams, noteNumber, startTime } = note;
|
|
1058
1057
|
const softPedalFactor = 1 -
|
|
1059
1058
|
(0.1 + (noteNumber / 127) * 0.2) * state.softPedal;
|
|
1060
|
-
const
|
|
1059
|
+
const baseCent = voiceParams.initialFilterFc + pressure;
|
|
1060
|
+
const baseFreq = this.centToHz(baseCent) * softPedalFactor *
|
|
1061
|
+
state.brightness * 2;
|
|
1062
|
+
const peekFreq = this.centToHz(baseCent + voiceParams.modEnvToFilterFc) *
|
|
1061
1063
|
softPedalFactor * state.brightness * 2;
|
|
1062
|
-
const peekFreq = this.centToHz(voiceParams.initialFilterFc + voiceParams.modEnvToFilterFc) * softPedalFactor * state.brightness * 2;
|
|
1063
1064
|
const sustainFreq = baseFreq +
|
|
1064
1065
|
(peekFreq - baseFreq) * (1 - voiceParams.modSustain);
|
|
1065
1066
|
const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
|
|
@@ -1086,9 +1087,9 @@ export class Midy {
|
|
|
1086
1087
|
gain: voiceParams.modLfoToFilterFc,
|
|
1087
1088
|
});
|
|
1088
1089
|
note.modulationDepth = new GainNode(this.audioContext);
|
|
1089
|
-
this.setModLfoToPitch(channel, note);
|
|
1090
|
+
this.setModLfoToPitch(channel, note, 0);
|
|
1090
1091
|
note.volumeDepth = new GainNode(this.audioContext);
|
|
1091
|
-
this.setModLfoToVolume(
|
|
1092
|
+
this.setModLfoToVolume(note, 0);
|
|
1092
1093
|
note.modulationLFO.start(startTime + voiceParams.delayModLFO);
|
|
1093
1094
|
note.modulationLFO.connect(note.filterDepth);
|
|
1094
1095
|
note.filterDepth.connect(note.filterNode.frequency);
|
|
@@ -1101,8 +1102,7 @@ export class Midy {
|
|
|
1101
1102
|
const { voiceParams } = note;
|
|
1102
1103
|
const state = channel.state;
|
|
1103
1104
|
note.vibratoLFO = new OscillatorNode(this.audioContext, {
|
|
1104
|
-
frequency: this.centToHz(voiceParams.freqVibLFO) *
|
|
1105
|
-
state.vibratoRate,
|
|
1105
|
+
frequency: this.centToHz(voiceParams.freqVibLFO) * state.vibratoRate * 2,
|
|
1106
1106
|
});
|
|
1107
1107
|
note.vibratoLFO.start(startTime + voiceParams.delayVibLFO * state.vibratoDelay * 2);
|
|
1108
1108
|
note.vibratoDepth = new GainNode(this.audioContext);
|
|
@@ -1131,8 +1131,8 @@ export class Midy {
|
|
|
1131
1131
|
}
|
|
1132
1132
|
else {
|
|
1133
1133
|
note.portamento = false;
|
|
1134
|
-
this.setVolumeEnvelope(channel, note);
|
|
1135
|
-
this.setFilterEnvelope(channel, note);
|
|
1134
|
+
this.setVolumeEnvelope(channel, note, 0);
|
|
1135
|
+
this.setFilterEnvelope(channel, note, 0);
|
|
1136
1136
|
}
|
|
1137
1137
|
if (0 < state.vibratoDepth) {
|
|
1138
1138
|
this.startVibrato(channel, note, startTime);
|
|
@@ -1347,16 +1347,12 @@ export class Midy {
|
|
|
1347
1347
|
handlePolyphonicKeyPressure(channelNumber, noteNumber, pressure) {
|
|
1348
1348
|
const now = this.audioContext.currentTime;
|
|
1349
1349
|
const channel = this.channels[channelNumber];
|
|
1350
|
-
pressure
|
|
1350
|
+
channel.state.polyphonicKeyPressure = pressure / 127;
|
|
1351
|
+
const table = channel.polyphonicKeyPressureTable;
|
|
1351
1352
|
const activeNotes = this.getActiveNotes(channel, now);
|
|
1352
|
-
if (
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
const gain = activeNote.gainL.gain.value;
|
|
1356
|
-
activeNote.volumeNode.gain
|
|
1357
|
-
.cancelScheduledValues(now)
|
|
1358
|
-
.setValueAtTime(gain * pressure, now);
|
|
1359
|
-
}
|
|
1353
|
+
if (activeNotes.has(noteNumber)) {
|
|
1354
|
+
const note = activeNotes.get(noteNumber);
|
|
1355
|
+
this.applyDestinationSettings(channel, note, table);
|
|
1360
1356
|
}
|
|
1361
1357
|
// this.applyVoiceParams(channel, 10);
|
|
1362
1358
|
}
|
|
@@ -1370,11 +1366,11 @@ export class Midy {
|
|
|
1370
1366
|
const prev = channel.state.channelPressure;
|
|
1371
1367
|
const next = value / 127;
|
|
1372
1368
|
channel.state.channelPressure = next;
|
|
1373
|
-
if (channel.
|
|
1374
|
-
const pressureDepth = (channel.
|
|
1369
|
+
if (channel.channelPressureTable[0] !== 64) {
|
|
1370
|
+
const pressureDepth = (channel.channelPressureTable[0] - 64) / 37.5; // 2400 / 64;
|
|
1375
1371
|
channel.detune += pressureDepth * (next - prev);
|
|
1376
1372
|
}
|
|
1377
|
-
const table = channel.
|
|
1373
|
+
const table = channel.channelPressureTable;
|
|
1378
1374
|
channel.scheduledNotes.forEach((noteList) => {
|
|
1379
1375
|
for (let i = 0; i < noteList.length; i++) {
|
|
1380
1376
|
const note = noteList[i];
|
|
@@ -1396,16 +1392,13 @@ export class Midy {
|
|
|
1396
1392
|
const next = (value - 8192) / 8192;
|
|
1397
1393
|
state.pitchWheel = value / 16383;
|
|
1398
1394
|
channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
|
|
1399
|
-
this.
|
|
1395
|
+
this.updateChannelDetune(channel);
|
|
1400
1396
|
this.applyVoiceParams(channel, 14);
|
|
1401
1397
|
}
|
|
1402
|
-
setModLfoToPitch(channel, note) {
|
|
1398
|
+
setModLfoToPitch(channel, note, pressure) {
|
|
1403
1399
|
const now = this.audioContext.currentTime;
|
|
1404
|
-
const pressureDepth = channel.pressureTable[3] / 127 * 600;
|
|
1405
|
-
const pressure = pressureDepth * channel.state.channelPressure;
|
|
1406
1400
|
const modLfoToPitch = note.voiceParams.modLfoToPitch + pressure;
|
|
1407
|
-
const baseDepth = Math.abs(modLfoToPitch) +
|
|
1408
|
-
channel.state.modulationDepth;
|
|
1401
|
+
const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
|
|
1409
1402
|
const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
|
|
1410
1403
|
note.modulationDepth.gain
|
|
1411
1404
|
.cancelScheduledValues(now)
|
|
@@ -1421,22 +1414,18 @@ export class Midy {
|
|
|
1421
1414
|
.cancelScheduledValues(now)
|
|
1422
1415
|
.setValueAtTime(vibratoDepth * vibratoDepthSign, now);
|
|
1423
1416
|
}
|
|
1424
|
-
setModLfoToFilterFc(
|
|
1417
|
+
setModLfoToFilterFc(note, pressure) {
|
|
1425
1418
|
const now = this.audioContext.currentTime;
|
|
1426
|
-
const pressureDepth = channel.pressureTable[4] / 127 * 2400;
|
|
1427
|
-
const pressure = pressureDepth * channel.state.channelPressure;
|
|
1428
1419
|
const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc + pressure;
|
|
1429
1420
|
note.filterDepth.gain
|
|
1430
1421
|
.cancelScheduledValues(now)
|
|
1431
1422
|
.setValueAtTime(modLfoToFilterFc, now);
|
|
1432
1423
|
}
|
|
1433
|
-
setModLfoToVolume(
|
|
1424
|
+
setModLfoToVolume(note, pressure) {
|
|
1434
1425
|
const now = this.audioContext.currentTime;
|
|
1435
1426
|
const modLfoToVolume = note.voiceParams.modLfoToVolume;
|
|
1436
1427
|
const baseDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
|
|
1437
|
-
const
|
|
1438
|
-
const pressure = 1 + pressureDepth * channel.state.channelPressure;
|
|
1439
|
-
const volumeDepth = baseDepth * Math.sign(modLfoToVolume) * pressure;
|
|
1428
|
+
const volumeDepth = baseDepth * Math.sign(modLfoToVolume) * (1 + pressure);
|
|
1440
1429
|
note.volumeDepth.gain
|
|
1441
1430
|
.cancelScheduledValues(now)
|
|
1442
1431
|
.setValueAtTime(volumeDepth, now);
|
|
@@ -1509,11 +1498,18 @@ export class Midy {
|
|
|
1509
1498
|
.cancelScheduledValues(now)
|
|
1510
1499
|
.setValueAtTime(freqModLFO, now);
|
|
1511
1500
|
}
|
|
1501
|
+
setFreqVibLFO(channel, note) {
|
|
1502
|
+
const now = this.audioContext.currentTime;
|
|
1503
|
+
const freqVibLFO = note.voiceParams.freqVibLFO;
|
|
1504
|
+
note.vibratoLFO.frequency
|
|
1505
|
+
.cancelScheduledValues(now)
|
|
1506
|
+
.setValueAtTime(freqVibLFO * channel.state.vibratoRate * 2, now);
|
|
1507
|
+
}
|
|
1512
1508
|
createVoiceParamsHandlers() {
|
|
1513
1509
|
return {
|
|
1514
1510
|
modLfoToPitch: (channel, note, _prevValue) => {
|
|
1515
1511
|
if (0 < channel.state.modulationDepth) {
|
|
1516
|
-
this.setModLfoToPitch(channel, note);
|
|
1512
|
+
this.setModLfoToPitch(channel, note, 0);
|
|
1517
1513
|
}
|
|
1518
1514
|
},
|
|
1519
1515
|
vibLfoToPitch: (channel, note, _prevValue) => {
|
|
@@ -1523,12 +1519,12 @@ export class Midy {
|
|
|
1523
1519
|
},
|
|
1524
1520
|
modLfoToFilterFc: (channel, note, _prevValue) => {
|
|
1525
1521
|
if (0 < channel.state.modulationDepth) {
|
|
1526
|
-
this.setModLfoToFilterFc(
|
|
1522
|
+
this.setModLfoToFilterFc(note, 0);
|
|
1527
1523
|
}
|
|
1528
1524
|
},
|
|
1529
1525
|
modLfoToVolume: (channel, note, _prevValue) => {
|
|
1530
1526
|
if (0 < channel.state.modulationDepth) {
|
|
1531
|
-
this.setModLfoToVolume(
|
|
1527
|
+
this.setModLfoToVolume(note, 0);
|
|
1532
1528
|
}
|
|
1533
1529
|
},
|
|
1534
1530
|
chorusEffectsSend: (channel, note, prevValue) => {
|
|
@@ -1554,11 +1550,7 @@ export class Midy {
|
|
|
1554
1550
|
},
|
|
1555
1551
|
freqVibLFO: (channel, note, _prevValue) => {
|
|
1556
1552
|
if (0 < channel.state.vibratoDepth) {
|
|
1557
|
-
|
|
1558
|
-
const freqVibLFO = note.voiceParams.freqVibLFO;
|
|
1559
|
-
note.vibratoLFO.frequency
|
|
1560
|
-
.cancelScheduledValues(now)
|
|
1561
|
-
.setValueAtTime(freqVibLFO * channel.state.vibratoRate, now);
|
|
1553
|
+
this.setFreqVibLFO(channel, note);
|
|
1562
1554
|
}
|
|
1563
1555
|
},
|
|
1564
1556
|
};
|
|
@@ -1602,7 +1594,7 @@ export class Midy {
|
|
|
1602
1594
|
this.setPortamentoStartFilterEnvelope(channel, note);
|
|
1603
1595
|
}
|
|
1604
1596
|
else {
|
|
1605
|
-
this.setFilterEnvelope(channel, note);
|
|
1597
|
+
this.setFilterEnvelope(channel, note, 0);
|
|
1606
1598
|
}
|
|
1607
1599
|
this.setPitchEnvelope(note);
|
|
1608
1600
|
}
|
|
@@ -1616,7 +1608,7 @@ export class Midy {
|
|
|
1616
1608
|
if (key in voiceParams)
|
|
1617
1609
|
noteVoiceParams[key] = voiceParams[key];
|
|
1618
1610
|
}
|
|
1619
|
-
this.setVolumeEnvelope(channel, note);
|
|
1611
|
+
this.setVolumeEnvelope(channel, note, 0);
|
|
1620
1612
|
}
|
|
1621
1613
|
}
|
|
1622
1614
|
}
|
|
@@ -1837,7 +1829,7 @@ export class Midy {
|
|
|
1837
1829
|
continue;
|
|
1838
1830
|
if (note.startTime < now)
|
|
1839
1831
|
continue;
|
|
1840
|
-
this.setVolumeEnvelope(channel, note);
|
|
1832
|
+
this.setVolumeEnvelope(channel, note, 0);
|
|
1841
1833
|
}
|
|
1842
1834
|
});
|
|
1843
1835
|
}
|
|
@@ -1849,7 +1841,12 @@ export class Midy {
|
|
|
1849
1841
|
const note = noteList[i];
|
|
1850
1842
|
if (!note)
|
|
1851
1843
|
continue;
|
|
1852
|
-
|
|
1844
|
+
if (note.portamento) {
|
|
1845
|
+
this.setPortamentoStartFilterEnvelope(channel, note);
|
|
1846
|
+
}
|
|
1847
|
+
else {
|
|
1848
|
+
this.setFilterEnvelope(channel, note, 0);
|
|
1849
|
+
}
|
|
1853
1850
|
}
|
|
1854
1851
|
});
|
|
1855
1852
|
}
|
|
@@ -1861,7 +1858,7 @@ export class Midy {
|
|
|
1861
1858
|
const note = noteList[i];
|
|
1862
1859
|
if (!note)
|
|
1863
1860
|
continue;
|
|
1864
|
-
this.setVolumeEnvelope(channel, note);
|
|
1861
|
+
this.setVolumeEnvelope(channel, note, 0);
|
|
1865
1862
|
}
|
|
1866
1863
|
});
|
|
1867
1864
|
}
|
|
@@ -1870,21 +1867,53 @@ export class Midy {
|
|
|
1870
1867
|
channel.state.vibratoRate = vibratoRate / 64;
|
|
1871
1868
|
if (channel.vibratoDepth <= 0)
|
|
1872
1869
|
return;
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
.
|
|
1870
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1871
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1872
|
+
const note = noteList[i];
|
|
1873
|
+
if (!note)
|
|
1874
|
+
continue;
|
|
1875
|
+
this.setVibLfoToPitch(channel, note);
|
|
1876
|
+
}
|
|
1879
1877
|
});
|
|
1880
1878
|
}
|
|
1881
1879
|
setVibratoDepth(channelNumber, vibratoDepth) {
|
|
1882
1880
|
const channel = this.channels[channelNumber];
|
|
1881
|
+
const prev = channel.state.vibratoDepth;
|
|
1883
1882
|
channel.state.vibratoDepth = vibratoDepth / 64;
|
|
1883
|
+
if (0 < prev) {
|
|
1884
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1885
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1886
|
+
const note = noteList[i];
|
|
1887
|
+
if (!note)
|
|
1888
|
+
continue;
|
|
1889
|
+
this.setFreqVibLFO(channel, note);
|
|
1890
|
+
}
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1893
|
+
else {
|
|
1894
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1895
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1896
|
+
const note = noteList[i];
|
|
1897
|
+
if (!note)
|
|
1898
|
+
continue;
|
|
1899
|
+
this.startVibrato(channel, note, note.startTime);
|
|
1900
|
+
}
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1884
1903
|
}
|
|
1885
1904
|
setVibratoDelay(channelNumber, vibratoDelay) {
|
|
1886
1905
|
const channel = this.channels[channelNumber];
|
|
1887
1906
|
channel.state.vibratoDelay = vibratoDelay / 64;
|
|
1907
|
+
if (0 < channel.state.vibratoDepth) {
|
|
1908
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1909
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1910
|
+
const note = noteList[i];
|
|
1911
|
+
if (!note)
|
|
1912
|
+
continue;
|
|
1913
|
+
this.startVibrato(channel, note, note.startTime);
|
|
1914
|
+
}
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1888
1917
|
}
|
|
1889
1918
|
setReverbSendLevel(channelNumber, reverbSendLevel) {
|
|
1890
1919
|
const channel = this.channels[channelNumber];
|
|
@@ -2049,7 +2078,7 @@ export class Midy {
|
|
|
2049
2078
|
const next = value / 128;
|
|
2050
2079
|
state.pitchWheelSensitivity = next;
|
|
2051
2080
|
channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
|
|
2052
|
-
this.
|
|
2081
|
+
this.updateChannelDetune(channel);
|
|
2053
2082
|
this.applyVoiceParams(channel, 16);
|
|
2054
2083
|
}
|
|
2055
2084
|
handleFineTuningRPN(channelNumber) {
|
|
@@ -2064,7 +2093,7 @@ export class Midy {
|
|
|
2064
2093
|
const next = (value - 8192) / 8.192; // cent
|
|
2065
2094
|
channel.fineTuning = next;
|
|
2066
2095
|
channel.detune += next - prev;
|
|
2067
|
-
this.
|
|
2096
|
+
this.updateChannelDetune(channel);
|
|
2068
2097
|
}
|
|
2069
2098
|
handleCoarseTuningRPN(channelNumber) {
|
|
2070
2099
|
const channel = this.channels[channelNumber];
|
|
@@ -2078,7 +2107,7 @@ export class Midy {
|
|
|
2078
2107
|
const next = (value - 64) * 100; // cent
|
|
2079
2108
|
channel.coarseTuning = next;
|
|
2080
2109
|
channel.detune += next - prev;
|
|
2081
|
-
this.
|
|
2110
|
+
this.updateChannelDetune(channel);
|
|
2082
2111
|
}
|
|
2083
2112
|
handleModulationDepthRangeRPN(channelNumber) {
|
|
2084
2113
|
const channel = this.channels[channelNumber];
|
|
@@ -2109,7 +2138,7 @@ export class Midy {
|
|
|
2109
2138
|
const state = channel.state;
|
|
2110
2139
|
for (let i = 0; i < stateTypes.length; i++) {
|
|
2111
2140
|
const type = stateTypes[i];
|
|
2112
|
-
state[type] = defaultControllerState[type];
|
|
2141
|
+
state[type] = defaultControllerState[type].defaultValue;
|
|
2113
2142
|
}
|
|
2114
2143
|
const settingTypes = [
|
|
2115
2144
|
"rpnMSB",
|
|
@@ -2212,7 +2241,9 @@ export class Midy {
|
|
|
2212
2241
|
case 9:
|
|
2213
2242
|
switch (data[3]) {
|
|
2214
2243
|
case 1: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
|
|
2215
|
-
return this.
|
|
2244
|
+
return this.handlePressureSysEx(data, "channelPressureTable");
|
|
2245
|
+
case 2: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
|
|
2246
|
+
return this.handlePressureSysEx(data, "polyphonicKeyPressureTable");
|
|
2216
2247
|
case 3: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
|
|
2217
2248
|
return this.handleControlChangeSysEx(data);
|
|
2218
2249
|
default:
|
|
@@ -2254,7 +2285,7 @@ export class Midy {
|
|
|
2254
2285
|
const next = (value - 8192) / 8.192; // cent
|
|
2255
2286
|
this.masterFineTuning = next;
|
|
2256
2287
|
channel.detune += next - prev;
|
|
2257
|
-
this.
|
|
2288
|
+
this.updateChannelDetune(channel);
|
|
2258
2289
|
}
|
|
2259
2290
|
handleMasterCoarseTuningSysEx(data) {
|
|
2260
2291
|
const coarseTuning = data[4];
|
|
@@ -2265,7 +2296,7 @@ export class Midy {
|
|
|
2265
2296
|
const next = (value - 64) * 100; // cent
|
|
2266
2297
|
this.masterCoarseTuning = next;
|
|
2267
2298
|
channel.detune += next - prev;
|
|
2268
|
-
this.
|
|
2299
|
+
this.updateChannelDetune(channel);
|
|
2269
2300
|
}
|
|
2270
2301
|
handleGlobalParameterControlSysEx(data) {
|
|
2271
2302
|
if (data[7] === 1) {
|
|
@@ -2489,29 +2520,63 @@ export class Midy {
|
|
|
2489
2520
|
}
|
|
2490
2521
|
applyDestinationSettings(channel, note, table) {
|
|
2491
2522
|
if (table[0] !== 64) {
|
|
2492
|
-
|
|
2523
|
+
const polyphonicKeyPressure = (0 < note.pressure)
|
|
2524
|
+
? channel.polyphonicKeyPressureTable[0] * note.pressure
|
|
2525
|
+
: 0;
|
|
2526
|
+
const pressure = (polyphonicKeyPressure - 64) / 37.5; // 2400 / 64;
|
|
2527
|
+
this.updateDetune(channel, note, pressure);
|
|
2493
2528
|
}
|
|
2494
2529
|
if (!note.portamento) {
|
|
2495
2530
|
if (table[1] !== 64) {
|
|
2496
|
-
|
|
2531
|
+
const channelPressure = channel.channelPressureTable[1] *
|
|
2532
|
+
channel.state.channelPressure;
|
|
2533
|
+
const polyphonicKeyPressure = (0 < note.pressure)
|
|
2534
|
+
? channel.polyphonicKeyPressureTable[1] * note.pressure
|
|
2535
|
+
: 0;
|
|
2536
|
+
const pressure = (channelPressure + polyphonicKeyPressure - 128) * 15;
|
|
2537
|
+
this.setFilterEnvelope(channel, note, pressure);
|
|
2497
2538
|
}
|
|
2498
2539
|
if (table[2] !== 64) {
|
|
2499
|
-
|
|
2540
|
+
const channelPressure = channel.channelPressureTable[2] *
|
|
2541
|
+
channel.state.channelPressure;
|
|
2542
|
+
const polyphonicKeyPressure = (0 < note.pressure)
|
|
2543
|
+
? channel.polyphonicKeyPressureTable[2] * note.pressure
|
|
2544
|
+
: 0;
|
|
2545
|
+
const pressure = (channelPressure + polyphonicKeyPressure) / 128;
|
|
2546
|
+
this.setVolumeEnvelope(channel, note, pressure);
|
|
2500
2547
|
}
|
|
2501
2548
|
}
|
|
2502
2549
|
if (table[3] !== 0) {
|
|
2503
|
-
|
|
2550
|
+
const channelPressure = channel.channelPressureTable[3] *
|
|
2551
|
+
channel.state.channelPressure;
|
|
2552
|
+
const polyphonicKeyPressure = (0 < note.pressure)
|
|
2553
|
+
? channel.polyphonicKeyPressureTable[3] * note.pressure
|
|
2554
|
+
: 0;
|
|
2555
|
+
const pressure = (channelPressure + polyphonicKeyPressure) / 254 * 600;
|
|
2556
|
+
this.setModLfoToPitch(channel, note, pressure);
|
|
2504
2557
|
}
|
|
2505
2558
|
if (table[4] !== 0) {
|
|
2506
|
-
|
|
2559
|
+
const channelPressure = channel.channelPressureTable[4] *
|
|
2560
|
+
channel.state.channelPressure;
|
|
2561
|
+
const polyphonicKeyPressure = (0 < note.pressure)
|
|
2562
|
+
? channel.polyphonicKeyPressureTable[4] * note.pressure
|
|
2563
|
+
: 0;
|
|
2564
|
+
const pressure = (channelPressure + polyphonicKeyPressure) / 254 * 2400;
|
|
2565
|
+
this.setModLfoToFilterFc(note, pressure);
|
|
2507
2566
|
}
|
|
2508
2567
|
if (table[5] !== 0) {
|
|
2509
|
-
|
|
2568
|
+
const channelPressure = channel.channelPressureTable[5] *
|
|
2569
|
+
channel.state.channelPressure;
|
|
2570
|
+
const polyphonicKeyPressure = (0 < note.pressure)
|
|
2571
|
+
? channel.polyphonicKeyPressureTable[5] * note.pressure
|
|
2572
|
+
: 0;
|
|
2573
|
+
const pressure = (channelPressure + polyphonicKeyPressure) / 254;
|
|
2574
|
+
this.setModLfoToVolume(note, pressure);
|
|
2510
2575
|
}
|
|
2511
2576
|
}
|
|
2512
|
-
handleChannelPressureSysEx(data) {
|
|
2577
|
+
handleChannelPressureSysEx(data, tableName) {
|
|
2513
2578
|
const channelNumber = data[4];
|
|
2514
|
-
const table = this.channels[channelNumber]
|
|
2579
|
+
const table = this.channels[channelNumber][tableName];
|
|
2515
2580
|
for (let i = 5; i < data.length - 1; i += 2) {
|
|
2516
2581
|
const pp = data[i];
|
|
2517
2582
|
const rr = data[i + 1];
|
|
@@ -2602,7 +2667,8 @@ Object.defineProperty(Midy, "channelSettings", {
|
|
|
2602
2667
|
currentBufferSource: null,
|
|
2603
2668
|
detune: 0,
|
|
2604
2669
|
scaleOctaveTuningTable: new Array(12).fill(0), // cent
|
|
2605
|
-
|
|
2670
|
+
channelPressureTable: new Uint8Array([64, 64, 64, 0, 0, 0]),
|
|
2671
|
+
polyphonicKeyPressureTable: new Uint8Array([64, 64, 64, 0, 0, 0]),
|
|
2606
2672
|
keyBasedInstrumentControlTable: new Int8Array(128 * 128), // [-64, 63]
|
|
2607
2673
|
program: 0,
|
|
2608
2674
|
bank: 121 * 128,
|
|
@@ -2617,16 +2683,3 @@ Object.defineProperty(Midy, "channelSettings", {
|
|
|
2617
2683
|
modulationDepthRange: 50, // cent
|
|
2618
2684
|
}
|
|
2619
2685
|
});
|
|
2620
|
-
Object.defineProperty(Midy, "controllerDestinationSettings", {
|
|
2621
|
-
enumerable: true,
|
|
2622
|
-
configurable: true,
|
|
2623
|
-
writable: true,
|
|
2624
|
-
value: {
|
|
2625
|
-
pitchControl: 0,
|
|
2626
|
-
filterCutoffControl: 0,
|
|
2627
|
-
amplitudeControl: 1,
|
|
2628
|
-
lfoPitchDepth: 0,
|
|
2629
|
-
lfoFilterDepth: 0,
|
|
2630
|
-
lfoAmplitudeDepth: 0,
|
|
2631
|
-
}
|
|
2632
|
-
});
|
package/package.json
CHANGED
package/script/midy-GM1.d.ts
CHANGED
|
@@ -97,7 +97,8 @@ export class MidyGM1 {
|
|
|
97
97
|
centToRate(cent: any): number;
|
|
98
98
|
centToHz(cent: any): number;
|
|
99
99
|
calcChannelDetune(channel: any): any;
|
|
100
|
-
|
|
100
|
+
updateChannelDetune(channel: any): void;
|
|
101
|
+
updateDetune(channel: any, note: any): void;
|
|
101
102
|
setVolumeEnvelope(note: any): void;
|
|
102
103
|
setPitchEnvelope(note: any): void;
|
|
103
104
|
clampCutoffFrequency(frequency: any): number;
|
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":"AAqFA;IAoBE;;;;;;;;;;;;MAYE;IAEF,+BAQC;IAzCD,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;IAClB,iCAA8B;IAiB5B,kBAAgC;IAChC,kBAA8C;IAC9C;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,6DA2BC;IAED,iEAUC;IAED,2EA+CC;IAED,mCAOC;IAED,0BAkDC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgEC;IAED,+EAmBC;IAED,qDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,
|
|
1
|
+
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAqFA;IAoBE;;;;;;;;;;;;MAYE;IAEF,+BAQC;IAzCD,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;IAClB,iCAA8B;IAiB5B,kBAAgC;IAChC,kBAA8C;IAC9C;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,6DA2BC;IAED,iEAUC;IAED,2EA+CC;IAED,mCAOC;IAED,0BAkDC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgEC;IAED,+EAmBC;IAED,qDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,wCAQC;IAED,4CAKC;IAED,mCAgBC;IAED,kCAqBC;IAED,6CAIC;IAED,mCAuBC;IAED,+DAoBC;IAED,gHA2BC;IAED,kGAgDC;IAED,0EAGC;IAED,qFA4BC;IAED,6HAuBC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,mDASC;IAED,gDASC;IAED,gDASC;IAED,qCAMC;IAED,mCAQC;IAED,gCAOC;IAED,+BAMC;IAED;;;;;;;;;;;MA4CC;IAED,oFAMC;IAED,0DA6CC;IAED;;;;;;;;;;;;;MAeC;IAED,+EAWC;IAED,qCAeC;IAED,8DAIC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,wCAWC;IAED,sDAKC;IAED,kFAeC;IAED,2DAMC;IAED,oCAkBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,kDAKC;IAED,wDASC;IAED,8CAKC;IAED,oDAOC;IAED,gDAKC;IAED,sDAOC;IAED,+CAEC;IAED,8CAqBC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAMC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AArzCD;IAUE,0FAMC;IAfD,kBAAa;IACb,gBAAW;IACX,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
|