@marmooo/midy 0.2.0 → 0.2.1
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/LICENSE +201 -0
- package/README.md +118 -0
- package/esm/midy-GM1.d.ts +10 -8
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +73 -66
- package/esm/midy-GM2.d.ts +17 -11
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +148 -101
- package/esm/midy-GMLite.d.ts +7 -5
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +50 -47
- package/esm/midy.d.ts +19 -13
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +233 -177
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +10 -8
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +73 -66
- package/script/midy-GM2.d.ts +17 -11
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +148 -101
- package/script/midy-GMLite.d.ts +7 -5
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +50 -47
- package/script/midy.d.ts +19 -13
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +233 -177
package/esm/midy-GM2.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export class MidyGM2 {
|
|
2
2
|
static channelSettings: {
|
|
3
3
|
currentBufferSource: null;
|
|
4
|
+
detune: number;
|
|
5
|
+
scaleOctaveTuningTable: any[];
|
|
4
6
|
program: number;
|
|
5
7
|
bank: number;
|
|
6
8
|
bankMSB: number;
|
|
@@ -182,12 +184,15 @@ export class MidyGM2 {
|
|
|
182
184
|
feedbackGains: any[];
|
|
183
185
|
};
|
|
184
186
|
cbToRatio(cb: any): number;
|
|
187
|
+
rateToCent(rate: any): number;
|
|
188
|
+
centToRate(cent: any): number;
|
|
185
189
|
centToHz(cent: any): number;
|
|
186
|
-
|
|
190
|
+
calcDetune(channel: any, note: any): any;
|
|
191
|
+
calcNoteDetune(channel: any, note: any): any;
|
|
192
|
+
updateDetune(channel: any): void;
|
|
187
193
|
setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
|
|
188
194
|
setVolumeEnvelope(note: any): void;
|
|
189
|
-
|
|
190
|
-
setPitch(channel: any, note: any): void;
|
|
195
|
+
setPitchEnvelope(note: any): void;
|
|
191
196
|
clampCutoffFrequency(frequency: any): number;
|
|
192
197
|
setPortamentoStartFilterEnvelope(channel: any, note: any): void;
|
|
193
198
|
setFilterEnvelope(channel: any, note: any): void;
|
|
@@ -208,11 +213,11 @@ export class MidyGM2 {
|
|
|
208
213
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
209
214
|
setPitchBend(channelNumber: any, value: any): void;
|
|
210
215
|
setModLfoToPitch(channel: any, note: any): void;
|
|
216
|
+
setVibLfoToPitch(channel: any, note: any): void;
|
|
217
|
+
setModLfoToFilterFc(note: any): void;
|
|
211
218
|
setModLfoToVolume(note: any): void;
|
|
212
219
|
setChorusEffectsSend(note: any, prevValue: any): void;
|
|
213
220
|
setReverbEffectsSend(note: any, prevValue: any): void;
|
|
214
|
-
setVibLfoToPitch(channel: any, note: any): void;
|
|
215
|
-
setModLfoToFilterFc(note: any): void;
|
|
216
221
|
setDelayModLFO(note: any): void;
|
|
217
222
|
setFreqModLFO(note: any): void;
|
|
218
223
|
createVoiceParamsHandlers(): {
|
|
@@ -282,13 +287,12 @@ export class MidyGM2 {
|
|
|
282
287
|
setRPNMSB(channelNumber: any, value: any): void;
|
|
283
288
|
setRPNLSB(channelNumber: any, value: any): void;
|
|
284
289
|
dataEntryMSB(channelNumber: any, value: any): void;
|
|
285
|
-
updateDetune(channel: any, detune: any): void;
|
|
286
290
|
handlePitchBendRangeRPN(channelNumber: any): void;
|
|
287
|
-
setPitchBendRange(channelNumber: any,
|
|
291
|
+
setPitchBendRange(channelNumber: any, value: any): void;
|
|
288
292
|
handleFineTuningRPN(channelNumber: any): void;
|
|
289
|
-
setFineTuning(channelNumber: any,
|
|
293
|
+
setFineTuning(channelNumber: any, value: any): void;
|
|
290
294
|
handleCoarseTuningRPN(channelNumber: any): void;
|
|
291
|
-
setCoarseTuning(channelNumber: any,
|
|
295
|
+
setCoarseTuning(channelNumber: any, value: any): void;
|
|
292
296
|
handleModulationDepthRangeRPN(channelNumber: any): void;
|
|
293
297
|
setModulationDepthRange(channelNumber: any, modulationDepthRange: any): void;
|
|
294
298
|
allSoundOff(channelNumber: any): Promise<void>;
|
|
@@ -305,9 +309,11 @@ export class MidyGM2 {
|
|
|
305
309
|
handleMasterVolumeSysEx(data: any): void;
|
|
306
310
|
setMasterVolume(volume: any): void;
|
|
307
311
|
handleMasterFineTuningSysEx(data: any): void;
|
|
308
|
-
setMasterFineTuning(
|
|
312
|
+
setMasterFineTuning(value: any): void;
|
|
309
313
|
handleMasterCoarseTuningSysEx(data: any): void;
|
|
310
|
-
setMasterCoarseTuning(
|
|
314
|
+
setMasterCoarseTuning(value: any): void;
|
|
315
|
+
getChannelBitmap(data: any): any[];
|
|
316
|
+
handleScaleOctaveTuning1ByteFormat(data: any): void;
|
|
311
317
|
handleGlobalParameterControlSysEx(data: any): void;
|
|
312
318
|
handleReverbParameterSysEx(data: any): void;
|
|
313
319
|
setReverbType(type: any): void;
|
package/esm/midy-GM2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AA8GA;IAmCE
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}
|
package/esm/midy-GM2.js
CHANGED
|
@@ -898,16 +898,42 @@ export class MidyGM2 {
|
|
|
898
898
|
cbToRatio(cb) {
|
|
899
899
|
return Math.pow(10, cb / 200);
|
|
900
900
|
}
|
|
901
|
+
rateToCent(rate) {
|
|
902
|
+
return 1200 * Math.log2(rate);
|
|
903
|
+
}
|
|
904
|
+
centToRate(cent) {
|
|
905
|
+
return Math.pow(2, cent / 1200);
|
|
906
|
+
}
|
|
901
907
|
centToHz(cent) {
|
|
902
|
-
return 8.176 *
|
|
908
|
+
return 8.176 * this.centToRate(cent);
|
|
903
909
|
}
|
|
904
|
-
|
|
910
|
+
calcDetune(channel, note) {
|
|
905
911
|
const masterTuning = this.masterCoarseTuning + this.masterFineTuning;
|
|
906
912
|
const channelTuning = channel.coarseTuning + channel.fineTuning;
|
|
913
|
+
const scaleOctaveTuning = channel.scaleOctaveTuningTable[note.noteNumber % 12];
|
|
914
|
+
const tuning = masterTuning + channelTuning + scaleOctaveTuning;
|
|
907
915
|
const pitchWheel = channel.state.pitchWheel * 2 - 1;
|
|
908
|
-
const pitchWheelSensitivity = channel.state.pitchWheelSensitivity *
|
|
916
|
+
const pitchWheelSensitivity = channel.state.pitchWheelSensitivity * 12800;
|
|
909
917
|
const pitch = pitchWheel * pitchWheelSensitivity;
|
|
910
|
-
return
|
|
918
|
+
return tuning + pitch;
|
|
919
|
+
}
|
|
920
|
+
calcNoteDetune(channel, note) {
|
|
921
|
+
return channel.scaleOctaveTuningTable[note.noteNumber % 12];
|
|
922
|
+
}
|
|
923
|
+
updateDetune(channel) {
|
|
924
|
+
const now = this.audioContext.currentTime;
|
|
925
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
926
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
927
|
+
const note = noteList[i];
|
|
928
|
+
if (!note)
|
|
929
|
+
continue;
|
|
930
|
+
const noteDetune = this.calcNoteDetune(channel, note);
|
|
931
|
+
const detune = channel.detune + noteDetune;
|
|
932
|
+
note.bufferSource.detune
|
|
933
|
+
.cancelScheduledValues(now)
|
|
934
|
+
.setValueAtTime(detune, now);
|
|
935
|
+
}
|
|
936
|
+
});
|
|
911
937
|
}
|
|
912
938
|
setPortamentoStartVolumeEnvelope(channel, note) {
|
|
913
939
|
const now = this.audioContext.currentTime;
|
|
@@ -938,32 +964,28 @@ export class MidyGM2 {
|
|
|
938
964
|
.setValueAtTime(attackVolume, volHold)
|
|
939
965
|
.linearRampToValueAtTime(sustainVolume, volDecay);
|
|
940
966
|
}
|
|
941
|
-
|
|
967
|
+
setPitchEnvelope(note) {
|
|
942
968
|
const now = this.audioContext.currentTime;
|
|
969
|
+
const { voiceParams } = note;
|
|
970
|
+
const baseRate = voiceParams.playbackRate;
|
|
943
971
|
note.bufferSource.playbackRate
|
|
944
972
|
.cancelScheduledValues(now)
|
|
945
|
-
.setValueAtTime(
|
|
946
|
-
|
|
947
|
-
setPitch(channel, note) {
|
|
948
|
-
const now = this.audioContext.currentTime;
|
|
949
|
-
const { startTime } = note;
|
|
950
|
-
const basePitch = this.calcSemitoneOffset(channel) * 100;
|
|
951
|
-
note.bufferSource.detune
|
|
952
|
-
.cancelScheduledValues(now)
|
|
953
|
-
.setValueAtTime(basePitch, startTime);
|
|
954
|
-
const modEnvToPitch = note.voiceParams.modEnvToPitch;
|
|
973
|
+
.setValueAtTime(baseRate, now);
|
|
974
|
+
const modEnvToPitch = voiceParams.modEnvToPitch;
|
|
955
975
|
if (modEnvToPitch === 0)
|
|
956
976
|
return;
|
|
977
|
+
const basePitch = this.rateToCent(baseRate);
|
|
957
978
|
const peekPitch = basePitch + modEnvToPitch;
|
|
979
|
+
const peekRate = this.centToRate(peekPitch);
|
|
958
980
|
const modDelay = startTime + voiceParams.modDelay;
|
|
959
981
|
const modAttack = modDelay + voiceParams.modAttack;
|
|
960
982
|
const modHold = modAttack + voiceParams.modHold;
|
|
961
983
|
const modDecay = modHold + voiceParams.modDecay;
|
|
962
|
-
note.bufferSource.
|
|
963
|
-
.setValueAtTime(
|
|
964
|
-
.exponentialRampToValueAtTime(
|
|
965
|
-
.setValueAtTime(
|
|
966
|
-
.linearRampToValueAtTime(
|
|
984
|
+
note.bufferSource.playbackRate
|
|
985
|
+
.setValueAtTime(baseRate, modDelay)
|
|
986
|
+
.exponentialRampToValueAtTime(peekRate, modAttack)
|
|
987
|
+
.setValueAtTime(peekRate, modHold)
|
|
988
|
+
.linearRampToValueAtTime(baseRate, modDecay);
|
|
967
989
|
}
|
|
968
990
|
clampCutoffFrequency(frequency) {
|
|
969
991
|
const minFrequency = 20; // min Hz of initialFilterFc
|
|
@@ -1074,9 +1096,8 @@ export class MidyGM2 {
|
|
|
1074
1096
|
if (0 < state.vibratoDepth) {
|
|
1075
1097
|
this.startVibrato(channel, note, startTime);
|
|
1076
1098
|
}
|
|
1077
|
-
this.
|
|
1099
|
+
this.setPitchEnvelope(note);
|
|
1078
1100
|
if (0 < state.modulationDepth) {
|
|
1079
|
-
this.setPitch(channel, note);
|
|
1080
1101
|
this.startModulation(channel, note, startTime);
|
|
1081
1102
|
}
|
|
1082
1103
|
if (this.mono && channel.currentBufferSource) {
|
|
@@ -1209,11 +1230,12 @@ export class MidyGM2 {
|
|
|
1209
1230
|
}
|
|
1210
1231
|
else {
|
|
1211
1232
|
const portamentoTime = endTime + state.portamentoTime;
|
|
1212
|
-
const
|
|
1213
|
-
const
|
|
1214
|
-
|
|
1233
|
+
const deltaNote = portamentoNoteNumber - noteNumber;
|
|
1234
|
+
const baseRate = note.voiceParams.playbackRate;
|
|
1235
|
+
const targetRate = baseRate * Math.pow(2, deltaNote / 12);
|
|
1236
|
+
note.bufferSource.playbackRate
|
|
1215
1237
|
.cancelScheduledValues(endTime)
|
|
1216
|
-
.linearRampToValueAtTime(
|
|
1238
|
+
.linearRampToValueAtTime(targetRate, portamentoTime);
|
|
1217
1239
|
return this.stopNote(endTime, portamentoTime, scheduledNotes, i);
|
|
1218
1240
|
}
|
|
1219
1241
|
}
|
|
@@ -1300,10 +1322,11 @@ export class MidyGM2 {
|
|
|
1300
1322
|
setPitchBend(channelNumber, value) {
|
|
1301
1323
|
const channel = this.channels[channelNumber];
|
|
1302
1324
|
const state = channel.state;
|
|
1325
|
+
const prev = state.pitchWheel * 2 - 1;
|
|
1326
|
+
const next = (value - 8192) / 8192;
|
|
1303
1327
|
state.pitchWheel = value / 16383;
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
this.updateDetune(channel, detuneChange);
|
|
1328
|
+
channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
|
|
1329
|
+
this.updateDetune(channel);
|
|
1307
1330
|
this.applyVoiceParams(channel, 14);
|
|
1308
1331
|
}
|
|
1309
1332
|
setModLfoToPitch(channel, note) {
|
|
@@ -1316,6 +1339,23 @@ export class MidyGM2 {
|
|
|
1316
1339
|
.cancelScheduledValues(now)
|
|
1317
1340
|
.setValueAtTime(modulationDepth * modulationDepthSign, now);
|
|
1318
1341
|
}
|
|
1342
|
+
setVibLfoToPitch(channel, note) {
|
|
1343
|
+
const now = this.audioContext.currentTime;
|
|
1344
|
+
const vibLfoToPitch = note.voiceParams.vibLfoToPitch;
|
|
1345
|
+
const vibratoDepth = Math.abs(vibLfoToPitch) * channel.state.vibratoDepth *
|
|
1346
|
+
2;
|
|
1347
|
+
const vibratoDepthSign = 0 < vibLfoToPitch;
|
|
1348
|
+
note.vibratoDepth.gain
|
|
1349
|
+
.cancelScheduledValues(now)
|
|
1350
|
+
.setValueAtTime(vibratoDepth * vibratoDepthSign, now);
|
|
1351
|
+
}
|
|
1352
|
+
setModLfoToFilterFc(note) {
|
|
1353
|
+
const now = this.audioContext.currentTime;
|
|
1354
|
+
const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc;
|
|
1355
|
+
note.filterDepth.gain
|
|
1356
|
+
.cancelScheduledValues(now)
|
|
1357
|
+
.setValueAtTime(modLfoToFilterFc, now);
|
|
1358
|
+
}
|
|
1319
1359
|
setModLfoToVolume(note) {
|
|
1320
1360
|
const now = this.audioContext.currentTime;
|
|
1321
1361
|
const modLfoToVolume = note.voiceParams.modLfoToVolume;
|
|
@@ -1375,23 +1415,6 @@ export class MidyGM2 {
|
|
|
1375
1415
|
}
|
|
1376
1416
|
}
|
|
1377
1417
|
}
|
|
1378
|
-
setVibLfoToPitch(channel, note) {
|
|
1379
|
-
const now = this.audioContext.currentTime;
|
|
1380
|
-
const vibLfoToPitch = note.voiceParams.vibLfoToPitch;
|
|
1381
|
-
const vibratoDepth = Math.abs(vibLfoToPitch) * channel.state.vibratoDepth *
|
|
1382
|
-
2;
|
|
1383
|
-
const vibratoDepthSign = 0 < vibLfoToPitch;
|
|
1384
|
-
note.vibratoDepth.gain
|
|
1385
|
-
.cancelScheduledValues(now)
|
|
1386
|
-
.setValueAtTime(vibratoDepth * vibratoDepthSign, now);
|
|
1387
|
-
}
|
|
1388
|
-
setModLfoToFilterFc(note) {
|
|
1389
|
-
const now = this.audioContext.currentTime;
|
|
1390
|
-
const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc;
|
|
1391
|
-
note.filterDepth.gain
|
|
1392
|
-
.cancelScheduledValues(now)
|
|
1393
|
-
.setValueAtTime(modLfoToFilterFc, now);
|
|
1394
|
-
}
|
|
1395
1418
|
setDelayModLFO(note) {
|
|
1396
1419
|
const now = this.audioContext.currentTime;
|
|
1397
1420
|
const startTime = note.startTime;
|
|
@@ -1500,7 +1523,7 @@ export class MidyGM2 {
|
|
|
1500
1523
|
else {
|
|
1501
1524
|
this.setFilterEnvelope(channel, note);
|
|
1502
1525
|
}
|
|
1503
|
-
this.
|
|
1526
|
+
this.setPitchEnvelope(note);
|
|
1504
1527
|
}
|
|
1505
1528
|
else if (volumeEnvelopeKeySet.has(key)) {
|
|
1506
1529
|
if (appliedVolumeEnvelope)
|
|
@@ -1572,7 +1595,7 @@ export class MidyGM2 {
|
|
|
1572
1595
|
note.modulationDepth.gain.setValueAtTime(channel.state.modulationDepth, now);
|
|
1573
1596
|
}
|
|
1574
1597
|
else {
|
|
1575
|
-
this.
|
|
1598
|
+
this.setPitchEnvelope(note);
|
|
1576
1599
|
this.startModulation(channel, note, now);
|
|
1577
1600
|
}
|
|
1578
1601
|
}
|
|
@@ -1793,59 +1816,49 @@ export class MidyGM2 {
|
|
|
1793
1816
|
this.channels[channelNumber].dataMSB = value;
|
|
1794
1817
|
this.handleRPN(channelNumber);
|
|
1795
1818
|
}
|
|
1796
|
-
updateDetune(channel, detune) {
|
|
1797
|
-
const now = this.audioContext.currentTime;
|
|
1798
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
1799
|
-
for (let i = 0; i < noteList.length; i++) {
|
|
1800
|
-
const note = noteList[i];
|
|
1801
|
-
if (!note)
|
|
1802
|
-
continue;
|
|
1803
|
-
const { bufferSource } = note;
|
|
1804
|
-
bufferSource.detune
|
|
1805
|
-
.cancelScheduledValues(now)
|
|
1806
|
-
.setValueAtTime(detune, now);
|
|
1807
|
-
}
|
|
1808
|
-
});
|
|
1809
|
-
}
|
|
1810
1819
|
handlePitchBendRangeRPN(channelNumber) {
|
|
1811
1820
|
const channel = this.channels[channelNumber];
|
|
1812
1821
|
this.limitData(channel, 0, 127, 0, 99);
|
|
1813
1822
|
const pitchBendRange = channel.dataMSB + channel.dataLSB / 100;
|
|
1814
1823
|
this.setPitchBendRange(channelNumber, pitchBendRange);
|
|
1815
1824
|
}
|
|
1816
|
-
setPitchBendRange(channelNumber,
|
|
1825
|
+
setPitchBendRange(channelNumber, value) {
|
|
1817
1826
|
const channel = this.channels[channelNumber];
|
|
1818
1827
|
const state = channel.state;
|
|
1819
|
-
|
|
1820
|
-
const
|
|
1821
|
-
|
|
1828
|
+
const prev = state.pitchWheelSensitivity;
|
|
1829
|
+
const next = value / 128;
|
|
1830
|
+
state.pitchWheelSensitivity = next;
|
|
1831
|
+
channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
|
|
1832
|
+
this.updateDetune(channel);
|
|
1822
1833
|
this.applyVoiceParams(channel, 16);
|
|
1823
1834
|
}
|
|
1824
1835
|
handleFineTuningRPN(channelNumber) {
|
|
1825
1836
|
const channel = this.channels[channelNumber];
|
|
1826
1837
|
this.limitData(channel, 0, 127, 0, 127);
|
|
1827
|
-
const fineTuning =
|
|
1838
|
+
const fineTuning = channel.dataMSB * 128 + channel.dataLSB;
|
|
1828
1839
|
this.setFineTuning(channelNumber, fineTuning);
|
|
1829
1840
|
}
|
|
1830
|
-
setFineTuning(channelNumber,
|
|
1841
|
+
setFineTuning(channelNumber, value) {
|
|
1831
1842
|
const channel = this.channels[channelNumber];
|
|
1832
|
-
const
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1843
|
+
const prev = channel.fineTuning;
|
|
1844
|
+
const next = (value - 8192) / 8.192; // cent
|
|
1845
|
+
channel.fineTuning = next;
|
|
1846
|
+
channel.detune += next - prev;
|
|
1847
|
+
this.updateDetune(channel);
|
|
1836
1848
|
}
|
|
1837
1849
|
handleCoarseTuningRPN(channelNumber) {
|
|
1838
1850
|
const channel = this.channels[channelNumber];
|
|
1839
1851
|
this.limitDataMSB(channel, 0, 127);
|
|
1840
|
-
const coarseTuning = channel.dataMSB
|
|
1841
|
-
this.
|
|
1852
|
+
const coarseTuning = channel.dataMSB;
|
|
1853
|
+
this.setCoarseTuning(channelNumber, coarseTuning);
|
|
1842
1854
|
}
|
|
1843
|
-
setCoarseTuning(channelNumber,
|
|
1855
|
+
setCoarseTuning(channelNumber, value) {
|
|
1844
1856
|
const channel = this.channels[channelNumber];
|
|
1845
|
-
const
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1857
|
+
const prev = channel.coarseTuning;
|
|
1858
|
+
const next = (value - 64) * 100; // cent
|
|
1859
|
+
channel.coarseTuning = next;
|
|
1860
|
+
channel.detune += next - prev;
|
|
1861
|
+
this.updateDetune(channel);
|
|
1849
1862
|
}
|
|
1850
1863
|
handleModulationDepthRangeRPN(channelNumber) {
|
|
1851
1864
|
const channel = this.channels[channelNumber];
|
|
@@ -1905,6 +1918,15 @@ export class MidyGM2 {
|
|
|
1905
1918
|
}
|
|
1906
1919
|
handleUniversalNonRealTimeExclusiveMessage(data) {
|
|
1907
1920
|
switch (data[2]) {
|
|
1921
|
+
case 8:
|
|
1922
|
+
switch (data[3]) {
|
|
1923
|
+
case 8:
|
|
1924
|
+
// https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca21.pdf
|
|
1925
|
+
return this.handleScaleOctaveTuning1ByteFormat(data);
|
|
1926
|
+
default:
|
|
1927
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1928
|
+
}
|
|
1929
|
+
break;
|
|
1908
1930
|
case 9:
|
|
1909
1931
|
switch (data[3]) {
|
|
1910
1932
|
case 1:
|
|
@@ -1959,15 +1981,6 @@ export class MidyGM2 {
|
|
|
1959
1981
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1960
1982
|
}
|
|
1961
1983
|
break;
|
|
1962
|
-
case 8:
|
|
1963
|
-
switch (data[3]) {
|
|
1964
|
-
// case 8:
|
|
1965
|
-
// // TODO
|
|
1966
|
-
// return this.handleScaleOctaveTuning1ByteFormat();
|
|
1967
|
-
default:
|
|
1968
|
-
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1969
|
-
}
|
|
1970
|
-
break;
|
|
1971
1984
|
case 9:
|
|
1972
1985
|
switch (data[3]) {
|
|
1973
1986
|
// case 1:
|
|
@@ -2008,27 +2021,59 @@ export class MidyGM2 {
|
|
|
2008
2021
|
}
|
|
2009
2022
|
}
|
|
2010
2023
|
handleMasterFineTuningSysEx(data) {
|
|
2011
|
-
const fineTuning =
|
|
2024
|
+
const fineTuning = data[5] * 128 + data[4];
|
|
2012
2025
|
this.setMasterFineTuning(fineTuning);
|
|
2013
2026
|
}
|
|
2014
|
-
setMasterFineTuning(
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
}
|
|
2027
|
+
setMasterFineTuning(value) {
|
|
2028
|
+
const prev = this.masterFineTuning;
|
|
2029
|
+
const next = (value - 8192) / 8.192; // cent
|
|
2030
|
+
this.masterFineTuning = next;
|
|
2031
|
+
channel.detune += next - prev;
|
|
2032
|
+
this.updateDetune(channel);
|
|
2021
2033
|
}
|
|
2022
2034
|
handleMasterCoarseTuningSysEx(data) {
|
|
2023
2035
|
const coarseTuning = data[4];
|
|
2024
2036
|
this.setMasterCoarseTuning(coarseTuning);
|
|
2025
2037
|
}
|
|
2026
|
-
setMasterCoarseTuning(
|
|
2027
|
-
|
|
2028
|
-
|
|
2038
|
+
setMasterCoarseTuning(value) {
|
|
2039
|
+
const prev = this.masterCoarseTuning;
|
|
2040
|
+
const next = (value - 64) * 100; // cent
|
|
2041
|
+
this.masterCoarseTuning = next;
|
|
2042
|
+
channel.detune += next - prev;
|
|
2043
|
+
this.updateDetune(channel);
|
|
2044
|
+
}
|
|
2045
|
+
getChannelBitmap(data) {
|
|
2046
|
+
const bitmap = new Array(16).fill(false);
|
|
2047
|
+
const ff = data[4] & 0b11;
|
|
2048
|
+
const gg = data[5] & 0x7F;
|
|
2049
|
+
const hh = data[6] & 0x7F;
|
|
2050
|
+
for (let bit = 0; bit < 7; bit++) {
|
|
2051
|
+
if (hh & (1 << bit))
|
|
2052
|
+
bitmap[bit] = true;
|
|
2053
|
+
}
|
|
2054
|
+
for (let bit = 0; bit < 7; bit++) {
|
|
2055
|
+
if (gg & (1 << bit))
|
|
2056
|
+
bitmap[bit + 7] = true;
|
|
2057
|
+
}
|
|
2058
|
+
for (let bit = 0; bit < 2; bit++) {
|
|
2059
|
+
if (ff & (1 << bit))
|
|
2060
|
+
bitmap[bit + 14] = true;
|
|
2061
|
+
}
|
|
2062
|
+
return bitmap;
|
|
2063
|
+
}
|
|
2064
|
+
handleScaleOctaveTuning1ByteFormat(data) {
|
|
2065
|
+
if (data.length < 18) {
|
|
2066
|
+
console.error("Data length is too short");
|
|
2067
|
+
return;
|
|
2029
2068
|
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2069
|
+
const channelBitmap = this.getChannelBitmap(data);
|
|
2070
|
+
for (let i = 0; i < channelBitmap.length; i++) {
|
|
2071
|
+
if (!channelBitmap[i])
|
|
2072
|
+
continue;
|
|
2073
|
+
for (let j = 0; j < 12; j++) {
|
|
2074
|
+
const value = data[j + 7] - 64; // cent
|
|
2075
|
+
this.channels[i].scaleOctaveTuningTable[j] = value;
|
|
2076
|
+
}
|
|
2032
2077
|
}
|
|
2033
2078
|
}
|
|
2034
2079
|
handleGlobalParameterControlSysEx(data) {
|
|
@@ -2248,6 +2293,8 @@ Object.defineProperty(MidyGM2, "channelSettings", {
|
|
|
2248
2293
|
writable: true,
|
|
2249
2294
|
value: {
|
|
2250
2295
|
currentBufferSource: null,
|
|
2296
|
+
detune: 0,
|
|
2297
|
+
scaleOctaveTuningTable: new Array(12).fill(0), // cent
|
|
2251
2298
|
program: 0,
|
|
2252
2299
|
bank: 121 * 128,
|
|
2253
2300
|
bankMSB: 121,
|
package/esm/midy-GMLite.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export class MidyGMLite {
|
|
2
2
|
static channelSettings: {
|
|
3
3
|
currentBufferSource: null;
|
|
4
|
+
detune: number;
|
|
4
5
|
program: number;
|
|
5
6
|
bank: number;
|
|
6
7
|
dataMSB: number;
|
|
@@ -89,11 +90,13 @@ export class MidyGMLite {
|
|
|
89
90
|
getActiveNotes(channel: any, time: any): Map<any, any>;
|
|
90
91
|
getActiveNote(noteList: any, time: any): any;
|
|
91
92
|
cbToRatio(cb: any): number;
|
|
93
|
+
rateToCent(rate: any): number;
|
|
94
|
+
centToRate(cent: any): number;
|
|
92
95
|
centToHz(cent: any): number;
|
|
93
|
-
|
|
96
|
+
calcChannelDetune(channel: any): number;
|
|
97
|
+
updateDetune(channel: any): void;
|
|
94
98
|
setVolumeEnvelope(note: any): void;
|
|
95
|
-
|
|
96
|
-
setPitch(channel: any, note: any): void;
|
|
99
|
+
setPitchEnvelope(note: any): void;
|
|
97
100
|
clampCutoffFrequency(frequency: any): number;
|
|
98
101
|
setFilterEnvelope(note: any): void;
|
|
99
102
|
startModulation(channel: any, note: any, startTime: any): void;
|
|
@@ -109,8 +112,8 @@ export class MidyGMLite {
|
|
|
109
112
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
110
113
|
setPitchBend(channelNumber: any, value: any): void;
|
|
111
114
|
setModLfoToPitch(channel: any, note: any): void;
|
|
112
|
-
setModLfoToVolume(note: any): void;
|
|
113
115
|
setModLfoToFilterFc(note: any): void;
|
|
116
|
+
setModLfoToVolume(note: any): void;
|
|
114
117
|
setDelayModLFO(note: any): void;
|
|
115
118
|
setFreqModLFO(note: any): void;
|
|
116
119
|
createVoiceParamsHandlers(): {
|
|
@@ -159,7 +162,6 @@ export class MidyGMLite {
|
|
|
159
162
|
setRPNMSB(channelNumber: any, value: any): void;
|
|
160
163
|
setRPNLSB(channelNumber: any, value: any): void;
|
|
161
164
|
dataEntryMSB(channelNumber: any, value: any): void;
|
|
162
|
-
updateDetune(channel: any, detune: any): void;
|
|
163
165
|
handlePitchBendRangeRPN(channelNumber: any): void;
|
|
164
166
|
setPitchBendRange(channelNumber: any, pitchWheelSensitivity: any): void;
|
|
165
167
|
allSoundOff(channelNumber: any): Promise<void>;
|
package/esm/midy-GMLite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAmFA;IAoBE
|
|
1
|
+
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAmFA;IAoBE;;;;;;;;;MASE;IAEF,+BAQC;IAtCD,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;IAc5B,kBAAgC;IAChC,gBAA4C;IAC5C;;;;;;;;;;;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,wCAIC;IAED,iCAWC;IAED,mCAgBC;IAED,kCAqBC;IAED,6CAIC;IAED,mCAuBC;IAED,+DAoBC;IAED,gHA2BC;IAED,kGAgDC;IAED,0EAGC;IAED,qFAwBC;IAED,6HAuBC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,mDASC;IAED,gDASC;IAED,qCAMC;IAED,mCAQC;IAED,gCAOC;IAED,+BAMC;IAED;;;;;;;;;;;MAqBC;IAED,+EAMC;IAED,0DA6CC;IAED;;;;;;;;;;;;;MAeC;IAED,+EASC;IAED,qCAiBC;IAED,8DAKC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,wCAWC;IAED,sDAKC;IAED,kFAeC;IAED,oCAYC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,kDAKC;IAED,wEAOC;IAED,+CAEC;IAED,8CAqBC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAMC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AArtCD;IAQE,0FAMC;IAbD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
|