@marmooo/midy 0.0.3 → 0.0.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 +4 -3
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +41 -38
- package/esm/midy-GM2.d.ts +14 -100
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +79 -40
- package/esm/midy-GMLite.d.ts +4 -3
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +40 -37
- package/esm/midy.d.ts +45 -3
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +96 -34
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +4 -3
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +41 -38
- package/script/midy-GM2.d.ts +14 -100
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +79 -40
- package/script/midy-GMLite.d.ts +4 -3
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +40 -37
- package/script/midy.d.ts +45 -3
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +96 -34
package/script/midy.js
CHANGED
|
@@ -209,6 +209,12 @@ class Midy {
|
|
|
209
209
|
...this.setChannelAudioNodes(audioContext),
|
|
210
210
|
scheduledNotes: new Map(),
|
|
211
211
|
sostenutoNotes: new Map(),
|
|
212
|
+
polyphonicKeyPressure: {
|
|
213
|
+
...Midy.controllerDestinationSettings,
|
|
214
|
+
},
|
|
215
|
+
channelPressure: {
|
|
216
|
+
...Midy.controllerDestinationSettings,
|
|
217
|
+
},
|
|
212
218
|
};
|
|
213
219
|
});
|
|
214
220
|
return channels;
|
|
@@ -263,9 +269,6 @@ class Midy {
|
|
|
263
269
|
if (event.startTime > t + this.lookAhead)
|
|
264
270
|
break;
|
|
265
271
|
switch (event.type) {
|
|
266
|
-
case "controller":
|
|
267
|
-
this.handleControlChange(this.omni ? 0 : event.channel, event.controllerType, event.value);
|
|
268
|
-
break;
|
|
269
272
|
case "noteOn":
|
|
270
273
|
if (event.velocity !== 0) {
|
|
271
274
|
await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, event.startTime + this.startDelay - offset);
|
|
@@ -279,9 +282,21 @@ class Midy {
|
|
|
279
282
|
}
|
|
280
283
|
break;
|
|
281
284
|
}
|
|
285
|
+
case "noteAftertouch":
|
|
286
|
+
this.handlePolyphonicKeyPressure(event.channel, event.noteNumber, event.amount);
|
|
287
|
+
break;
|
|
288
|
+
case "controller":
|
|
289
|
+
this.handleControlChange(this.omni ? 0 : event.channel, event.controllerType, event.value);
|
|
290
|
+
break;
|
|
282
291
|
case "programChange":
|
|
283
292
|
this.handleProgramChange(event.channel, event.programNumber);
|
|
284
293
|
break;
|
|
294
|
+
case "channelAftertouch":
|
|
295
|
+
this.handleChannelPressure(event.channel, event.amount);
|
|
296
|
+
break;
|
|
297
|
+
case "pitchBend":
|
|
298
|
+
this.handlePitchBend(event.channel, event.value);
|
|
299
|
+
break;
|
|
285
300
|
case "sysEx":
|
|
286
301
|
this.handleSysEx(event.data);
|
|
287
302
|
}
|
|
@@ -645,15 +660,19 @@ class Midy {
|
|
|
645
660
|
centToHz(cent) {
|
|
646
661
|
return 8.176 * Math.pow(2, cent / 1200);
|
|
647
662
|
}
|
|
648
|
-
|
|
663
|
+
calcSemitoneOffset(channel) {
|
|
649
664
|
const masterTuning = this.masterCoarseTuning + this.masterFineTuning;
|
|
650
665
|
const channelTuning = channel.coarseTuning + channel.fineTuning;
|
|
651
666
|
const tuning = masterTuning + channelTuning;
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
667
|
+
return channel.pitchBend * channel.pitchBendRange + tuning;
|
|
668
|
+
}
|
|
669
|
+
calcPlaybackRate(noteInfo, noteNumber, semitoneOffset) {
|
|
670
|
+
return noteInfo.playbackRate(noteNumber) * Math.pow(2, semitoneOffset / 12);
|
|
671
|
+
}
|
|
672
|
+
async createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3) {
|
|
655
673
|
const bufferSource = await this.createNoteBufferNode(noteInfo, isSF3);
|
|
656
|
-
|
|
674
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
675
|
+
bufferSource.playbackRate.value = this.calcPlaybackRate(noteInfo, noteNumber, semitoneOffset);
|
|
657
676
|
// volume envelope
|
|
658
677
|
const gainNode = new GainNode(this.audioContext, {
|
|
659
678
|
gain: 0,
|
|
@@ -717,7 +736,7 @@ class Midy {
|
|
|
717
736
|
channel.currentBufferSource = bufferSource;
|
|
718
737
|
}
|
|
719
738
|
bufferSource.start(startTime, noteInfo.start / noteInfo.sampleRate);
|
|
720
|
-
return { bufferSource, gainNode, filterNode };
|
|
739
|
+
return { bufferSource, gainNode, filterNode, lfoGain };
|
|
721
740
|
}
|
|
722
741
|
calcBank(channel, channelNumber) {
|
|
723
742
|
if (channel.bankMSB === 121) {
|
|
@@ -739,7 +758,7 @@ class Midy {
|
|
|
739
758
|
const noteInfo = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber);
|
|
740
759
|
if (!noteInfo)
|
|
741
760
|
return;
|
|
742
|
-
const { bufferSource, gainNode, filterNode } = await this
|
|
761
|
+
const { bufferSource, gainNode, filterNode, lfoGain } = await this
|
|
743
762
|
.createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3);
|
|
744
763
|
this.connectNoteEffects(channel, gainNode);
|
|
745
764
|
if (channel.sostenutoPedal) {
|
|
@@ -859,7 +878,7 @@ class Midy {
|
|
|
859
878
|
case 0x90:
|
|
860
879
|
return this.noteOn(channelNumber, data1, data2);
|
|
861
880
|
case 0xA0:
|
|
862
|
-
return this.handlePolyphonicKeyPressure(channelNumber, data1, data2);
|
|
881
|
+
return; // this.handlePolyphonicKeyPressure(channelNumber, data1, data2);
|
|
863
882
|
case 0xB0:
|
|
864
883
|
return this.handleControlChange(channelNumber, data1, data2);
|
|
865
884
|
case 0xC0:
|
|
@@ -867,7 +886,7 @@ class Midy {
|
|
|
867
886
|
case 0xD0:
|
|
868
887
|
return this.handleChannelPressure(channelNumber, data1);
|
|
869
888
|
case 0xE0:
|
|
870
|
-
return this.
|
|
889
|
+
return this.handlePitchBendMessage(channelNumber, data1, data2);
|
|
871
890
|
default:
|
|
872
891
|
console.warn(`Unsupported MIDI message: ${messageType.toString(16)}`);
|
|
873
892
|
}
|
|
@@ -875,17 +894,16 @@ class Midy {
|
|
|
875
894
|
handlePolyphonicKeyPressure(channelNumber, noteNumber, pressure) {
|
|
876
895
|
const now = this.audioContext.currentTime;
|
|
877
896
|
const channel = this.channels[channelNumber];
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
if (
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
});
|
|
897
|
+
pressure /= 64;
|
|
898
|
+
const activeNotes = this.getActiveNotes(channel);
|
|
899
|
+
if (channel.polyphonicKeyPressure.amplitudeControl !== 1) {
|
|
900
|
+
if (activeNotes.has(noteNumber)) {
|
|
901
|
+
const activeNote = activeNotes.get(noteNumber);
|
|
902
|
+
const gain = activeNote.gainNode.gain.value;
|
|
903
|
+
activeNote.gainNode.gain
|
|
904
|
+
.cancelScheduledValues(now)
|
|
905
|
+
.setValueAtTime(gain * pressure, now);
|
|
906
|
+
}
|
|
889
907
|
}
|
|
890
908
|
}
|
|
891
909
|
handleProgramChange(channelNumber, program) {
|
|
@@ -894,11 +912,37 @@ class Midy {
|
|
|
894
912
|
channel.program = program;
|
|
895
913
|
}
|
|
896
914
|
handleChannelPressure(channelNumber, pressure) {
|
|
897
|
-
this.
|
|
915
|
+
const now = this.audioContext.currentTime;
|
|
916
|
+
const channel = this.channels[channelNumber];
|
|
917
|
+
pressure /= 64;
|
|
918
|
+
channel.channelPressure = pressure;
|
|
919
|
+
const activeNotes = this.getActiveNotes(channel);
|
|
920
|
+
if (channel.channelPressure.amplitudeControl !== 1) {
|
|
921
|
+
activeNotes.forEach((activeNote) => {
|
|
922
|
+
const gain = activeNote.gainNode.gain.value;
|
|
923
|
+
activeNote.gainNode.gain
|
|
924
|
+
.cancelScheduledValues(now)
|
|
925
|
+
.setValueAtTime(gain * pressure, now);
|
|
926
|
+
});
|
|
927
|
+
}
|
|
898
928
|
}
|
|
899
|
-
|
|
900
|
-
const pitchBend =
|
|
901
|
-
this.
|
|
929
|
+
handlePitchBendMessage(channelNumber, lsb, msb) {
|
|
930
|
+
const pitchBend = msb * 128 + lsb;
|
|
931
|
+
this.handlePitchBend(channelNumber, pitchBend);
|
|
932
|
+
}
|
|
933
|
+
handlePitchBend(channelNumber, pitchBend) {
|
|
934
|
+
const now = this.audioContext.currentTime;
|
|
935
|
+
const channel = this.channels[channelNumber];
|
|
936
|
+
channel.pitchBend = (pitchBend - 8192) / 8192;
|
|
937
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
938
|
+
const activeNotes = this.getActiveNotes(channel);
|
|
939
|
+
activeNotes.forEach((activeNote) => {
|
|
940
|
+
const { bufferSource, noteInfo, noteNumber } = activeNote;
|
|
941
|
+
const playbackRate = calcPlaybackRate(noteInfo, noteNumber, semitoneOffset);
|
|
942
|
+
bufferSource.playbackRate
|
|
943
|
+
.cancelScheduledValues(now)
|
|
944
|
+
.setValueAtTime(playbackRate * pressure, now);
|
|
945
|
+
});
|
|
902
946
|
}
|
|
903
947
|
handleControlChange(channelNumber, controller, value) {
|
|
904
948
|
switch (controller) {
|
|
@@ -1243,10 +1287,10 @@ class Midy {
|
|
|
1243
1287
|
switch (data[3]) {
|
|
1244
1288
|
// case 1:
|
|
1245
1289
|
// // TODO
|
|
1246
|
-
// return this.
|
|
1290
|
+
// return this.setChannelPressure();
|
|
1247
1291
|
// case 3:
|
|
1248
1292
|
// // TODO
|
|
1249
|
-
// return this.
|
|
1293
|
+
// return this.setControlChange();
|
|
1250
1294
|
default:
|
|
1251
1295
|
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1252
1296
|
}
|
|
@@ -1265,20 +1309,25 @@ class Midy {
|
|
|
1265
1309
|
}
|
|
1266
1310
|
}
|
|
1267
1311
|
handleMasterVolumeSysEx(data) {
|
|
1268
|
-
const volume = (data[5] * 128 + data[4]
|
|
1312
|
+
const volume = (data[5] * 128 + data[4]) / 16383;
|
|
1269
1313
|
this.handleMasterVolume(volume);
|
|
1270
1314
|
}
|
|
1271
1315
|
handleMasterVolume(volume) {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1316
|
+
if (volume < 0 && 1 < volume) {
|
|
1317
|
+
console.error("Master Volume is out of range");
|
|
1318
|
+
}
|
|
1319
|
+
else {
|
|
1320
|
+
const now = this.audioContext.currentTime;
|
|
1321
|
+
this.masterGain.gain.cancelScheduledValues(now);
|
|
1322
|
+
this.masterGain.gain.setValueAtTime(volume * volume, now);
|
|
1323
|
+
}
|
|
1275
1324
|
}
|
|
1276
1325
|
handleMasterFineTuningSysEx(data) {
|
|
1277
1326
|
const fineTuning = (data[5] * 128 + data[4] - 8192) / 8192;
|
|
1278
1327
|
this.handleMasterFineTuning(fineTuning);
|
|
1279
1328
|
}
|
|
1280
1329
|
handleMasterFineTuning(fineTuning) {
|
|
1281
|
-
if (fineTuning <
|
|
1330
|
+
if (fineTuning < -1 && 1 < fineTuning) {
|
|
1282
1331
|
console.error("Master Fine Tuning value is out of range");
|
|
1283
1332
|
}
|
|
1284
1333
|
else {
|
|
@@ -1366,3 +1415,16 @@ Object.defineProperty(Midy, "effectSettings", {
|
|
|
1366
1415
|
pitchBendRange: 2,
|
|
1367
1416
|
}
|
|
1368
1417
|
});
|
|
1418
|
+
Object.defineProperty(Midy, "controllerDestinationSettings", {
|
|
1419
|
+
enumerable: true,
|
|
1420
|
+
configurable: true,
|
|
1421
|
+
writable: true,
|
|
1422
|
+
value: {
|
|
1423
|
+
pitchControl: 0,
|
|
1424
|
+
filterCutoffControl: 0,
|
|
1425
|
+
amplitudeControl: 1,
|
|
1426
|
+
lfoPitchDepth: 0,
|
|
1427
|
+
lfoFilterDepth: 0,
|
|
1428
|
+
lfoAmplitudeDepth: 0,
|
|
1429
|
+
}
|
|
1430
|
+
});
|