@marmooo/midy 0.1.5 → 0.1.6
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 +7 -7
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +62 -59
- package/esm/midy-GM2.d.ts +12 -9
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +156 -79
- package/esm/midy-GMLite.d.ts +7 -7
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +62 -59
- package/esm/midy.d.ts +12 -9
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +156 -83
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +7 -7
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +62 -59
- package/script/midy-GM2.d.ts +12 -9
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +156 -79
- package/script/midy-GMLite.d.ts +7 -7
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +62 -59
- package/script/midy.d.ts +12 -9
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +156 -83
package/esm/midy.js
CHANGED
|
@@ -249,12 +249,14 @@ export class Midy {
|
|
|
249
249
|
addSoundFont(soundFont) {
|
|
250
250
|
const index = this.soundFonts.length;
|
|
251
251
|
this.soundFonts.push(soundFont);
|
|
252
|
-
soundFont.parsed.presetHeaders
|
|
252
|
+
const presetHeaders = soundFont.parsed.presetHeaders;
|
|
253
|
+
for (let i = 0; i < presetHeaders.length; i++) {
|
|
254
|
+
const presetHeader = presetHeaders[i];
|
|
253
255
|
if (!presetHeader.presetName.startsWith("\u0000")) { // TODO: Only SF3 generated by PolyPone?
|
|
254
256
|
const banks = this.soundFontTable[presetHeader.preset];
|
|
255
257
|
banks.set(presetHeader.bank, index);
|
|
256
258
|
}
|
|
257
|
-
}
|
|
259
|
+
}
|
|
258
260
|
}
|
|
259
261
|
async loadSoundFont(soundFontUrl) {
|
|
260
262
|
const response = await fetch(soundFontUrl);
|
|
@@ -306,27 +308,25 @@ export class Midy {
|
|
|
306
308
|
return channels;
|
|
307
309
|
}
|
|
308
310
|
async createNoteBuffer(instrumentKey, isSF3) {
|
|
311
|
+
const sampleStart = instrumentKey.start;
|
|
309
312
|
const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
|
|
310
313
|
if (isSF3) {
|
|
311
|
-
const sample =
|
|
312
|
-
sample.set(instrumentKey.sample);
|
|
314
|
+
const sample = instrumentKey.sample.slice(sampleStart, sampleEnd);
|
|
313
315
|
const audioBuffer = await this.audioContext.decodeAudioData(sample.buffer);
|
|
314
|
-
for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {
|
|
315
|
-
const channelData = audioBuffer.getChannelData(channel);
|
|
316
|
-
channelData.set(channelData.subarray(0, sampleEnd));
|
|
317
|
-
}
|
|
318
316
|
return audioBuffer;
|
|
319
317
|
}
|
|
320
318
|
else {
|
|
321
|
-
const sample = instrumentKey.sample.subarray(
|
|
322
|
-
const floatSample = this.convertToFloat32Array(sample);
|
|
319
|
+
const sample = instrumentKey.sample.subarray(sampleStart, sampleEnd);
|
|
323
320
|
const audioBuffer = new AudioBuffer({
|
|
324
321
|
numberOfChannels: 1,
|
|
325
322
|
length: sample.length,
|
|
326
323
|
sampleRate: instrumentKey.sampleRate,
|
|
327
324
|
});
|
|
328
325
|
const channelData = audioBuffer.getChannelData(0);
|
|
329
|
-
|
|
326
|
+
const int16Array = new Int16Array(sample.buffer);
|
|
327
|
+
for (let i = 0; i < int16Array.length; i++) {
|
|
328
|
+
channelData[i] = int16Array[i] / 32768;
|
|
329
|
+
}
|
|
330
330
|
return audioBuffer;
|
|
331
331
|
}
|
|
332
332
|
}
|
|
@@ -342,13 +342,23 @@ export class Midy {
|
|
|
342
342
|
}
|
|
343
343
|
return bufferSource;
|
|
344
344
|
}
|
|
345
|
-
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
345
|
+
findPortamentoTarget(queueIndex) {
|
|
346
|
+
const endEvent = this.timeline[queueIndex];
|
|
347
|
+
if (!this.channels[endEvent.channel].portamento)
|
|
348
|
+
return;
|
|
349
|
+
const endTime = endEvent.startTime;
|
|
350
|
+
let target;
|
|
351
|
+
while (++queueIndex < this.timeline.length) {
|
|
352
|
+
const event = this.timeline[queueIndex];
|
|
353
|
+
if (endTime !== event.startTime)
|
|
354
|
+
break;
|
|
355
|
+
if (event.type !== "noteOn")
|
|
356
|
+
continue;
|
|
357
|
+
if (!target || event.noteNumber < target.noteNumber) {
|
|
358
|
+
target = event;
|
|
359
|
+
}
|
|
350
360
|
}
|
|
351
|
-
return
|
|
361
|
+
return target;
|
|
352
362
|
}
|
|
353
363
|
async scheduleTimelineEvents(t, offset, queueIndex) {
|
|
354
364
|
while (queueIndex < this.timeline.length) {
|
|
@@ -358,12 +368,15 @@ export class Midy {
|
|
|
358
368
|
switch (event.type) {
|
|
359
369
|
case "noteOn":
|
|
360
370
|
if (event.velocity !== 0) {
|
|
361
|
-
await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, event.startTime + this.startDelay - offset);
|
|
371
|
+
await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, event.startTime + this.startDelay - offset, event.portamento);
|
|
362
372
|
break;
|
|
363
373
|
}
|
|
364
374
|
/* falls through */
|
|
365
375
|
case "noteOff": {
|
|
366
|
-
const
|
|
376
|
+
const portamentoTarget = this.findPortamentoTarget(queueIndex);
|
|
377
|
+
if (portamentoTarget)
|
|
378
|
+
portamentoTarget.portamento = true;
|
|
379
|
+
const notePromise = this.scheduleNoteRelease(this.omni ? 0 : event.channel, event.noteNumber, event.velocity, event.startTime + this.startDelay - offset, portamentoTarget?.noteNumber, false);
|
|
367
380
|
if (notePromise) {
|
|
368
381
|
this.notePromises.push(notePromise);
|
|
369
382
|
}
|
|
@@ -467,9 +480,11 @@ export class Midy {
|
|
|
467
480
|
bankLSB: this.channels[i].bankLSB,
|
|
468
481
|
};
|
|
469
482
|
}
|
|
470
|
-
midi.tracks.
|
|
483
|
+
for (let i = 0; i < midi.tracks.length; i++) {
|
|
484
|
+
const track = midi.tracks[i];
|
|
471
485
|
let currentTicks = 0;
|
|
472
|
-
track.
|
|
486
|
+
for (let j = 0; j < track.length; j++) {
|
|
487
|
+
const event = track[j];
|
|
473
488
|
currentTicks += event.deltaTime;
|
|
474
489
|
event.ticks = currentTicks;
|
|
475
490
|
switch (event.type) {
|
|
@@ -522,16 +537,18 @@ export class Midy {
|
|
|
522
537
|
}
|
|
523
538
|
delete event.deltaTime;
|
|
524
539
|
timeline.push(event);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
527
542
|
const priority = {
|
|
528
543
|
controller: 0,
|
|
529
544
|
sysEx: 1,
|
|
545
|
+
noteOff: 2, // for portamento
|
|
546
|
+
noteOn: 3,
|
|
530
547
|
};
|
|
531
548
|
timeline.sort((a, b) => {
|
|
532
549
|
if (a.ticks !== b.ticks)
|
|
533
550
|
return a.ticks - b.ticks;
|
|
534
|
-
return (priority[a.type] ||
|
|
551
|
+
return (priority[a.type] || 4) - (priority[b.type] || 4);
|
|
535
552
|
});
|
|
536
553
|
let prevTempoTime = 0;
|
|
537
554
|
let prevTempoTicks = 0;
|
|
@@ -548,7 +565,7 @@ export class Midy {
|
|
|
548
565
|
}
|
|
549
566
|
return { instruments, timeline };
|
|
550
567
|
}
|
|
551
|
-
async stopChannelNotes(channelNumber, velocity,
|
|
568
|
+
async stopChannelNotes(channelNumber, velocity, force) {
|
|
552
569
|
const now = this.audioContext.currentTime;
|
|
553
570
|
const channel = this.channels[channelNumber];
|
|
554
571
|
channel.scheduledNotes.forEach((noteList) => {
|
|
@@ -556,16 +573,17 @@ export class Midy {
|
|
|
556
573
|
const note = noteList[i];
|
|
557
574
|
if (!note)
|
|
558
575
|
continue;
|
|
559
|
-
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now,
|
|
576
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, undefined, // portamentoNoteNumber
|
|
577
|
+
force);
|
|
560
578
|
this.notePromises.push(promise);
|
|
561
579
|
}
|
|
562
580
|
});
|
|
563
581
|
channel.scheduledNotes.clear();
|
|
564
582
|
await Promise.all(this.notePromises);
|
|
565
583
|
}
|
|
566
|
-
stopNotes(velocity,
|
|
584
|
+
stopNotes(velocity, force) {
|
|
567
585
|
for (let i = 0; i < this.channels.length; i++) {
|
|
568
|
-
this.stopChannelNotes(i, velocity,
|
|
586
|
+
this.stopChannelNotes(i, velocity, force);
|
|
569
587
|
}
|
|
570
588
|
return Promise.all(this.notePromises);
|
|
571
589
|
}
|
|
@@ -779,6 +797,17 @@ export class Midy {
|
|
|
779
797
|
return instrumentKey.playbackRate(noteNumber) *
|
|
780
798
|
Math.pow(2, semitoneOffset / 12);
|
|
781
799
|
}
|
|
800
|
+
setPortamentoStartVolumeEnvelope(channel, note) {
|
|
801
|
+
const { instrumentKey, startTime } = note;
|
|
802
|
+
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
803
|
+
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
804
|
+
const volDelay = startTime + instrumentKey.volDelay;
|
|
805
|
+
const portamentoTime = volDelay + channel.portamentoTime;
|
|
806
|
+
note.volumeNode.gain
|
|
807
|
+
.cancelScheduledValues(startTime)
|
|
808
|
+
.setValueAtTime(0, volDelay)
|
|
809
|
+
.linearRampToValueAtTime(sustainVolume, portamentoTime);
|
|
810
|
+
}
|
|
782
811
|
setVolumeEnvelope(channel, note) {
|
|
783
812
|
const { instrumentKey, startTime } = note;
|
|
784
813
|
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
@@ -818,6 +847,25 @@ export class Midy {
|
|
|
818
847
|
const maxFrequency = 20000; // max Hz of initialFilterFc
|
|
819
848
|
return Math.max(minFrequency, Math.min(frequency, maxFrequency));
|
|
820
849
|
}
|
|
850
|
+
setPortamentoStartFilterEnvelope(channel, note) {
|
|
851
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
852
|
+
const softPedalFactor = 1 -
|
|
853
|
+
(0.1 + (noteNumber / 127) * 0.2) * channel.softPedal;
|
|
854
|
+
const baseFreq = this.centToHz(instrumentKey.initialFilterFc) *
|
|
855
|
+
softPedalFactor * channel.brightness;
|
|
856
|
+
const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc) * softPedalFactor * channel.brightness;
|
|
857
|
+
const sustainFreq = baseFreq +
|
|
858
|
+
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
|
|
859
|
+
const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
|
|
860
|
+
const adjustedSustainFreq = this.clampCutoffFrequency(sustainFreq);
|
|
861
|
+
const portamentoTime = startTime + channel.portamentoTime;
|
|
862
|
+
const modDelay = startTime + instrumentKey.modDelay;
|
|
863
|
+
note.filterNode.frequency
|
|
864
|
+
.cancelScheduledValues(startTime)
|
|
865
|
+
.setValueAtTime(adjustedBaseFreq, startTime)
|
|
866
|
+
.setValueAtTime(adjustedBaseFreq, modDelay)
|
|
867
|
+
.linearRampToValueAtTime(adjustedSustainFreq, portamentoTime);
|
|
868
|
+
}
|
|
821
869
|
setFilterEnvelope(channel, note) {
|
|
822
870
|
const { instrumentKey, noteNumber, startTime } = note;
|
|
823
871
|
const softPedalFactor = 1 -
|
|
@@ -885,7 +933,7 @@ export class Midy {
|
|
|
885
933
|
note.vibratoLFO.connect(note.vibratoDepth);
|
|
886
934
|
note.vibratoDepth.connect(note.bufferSource.detune);
|
|
887
935
|
}
|
|
888
|
-
async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
|
|
936
|
+
async createNote(channel, instrumentKey, noteNumber, velocity, startTime, portamento, isSF3) {
|
|
889
937
|
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
890
938
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
891
939
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
@@ -894,8 +942,14 @@ export class Midy {
|
|
|
894
942
|
type: "lowpass",
|
|
895
943
|
Q: instrumentKey.initialFilterQ / 10 * channel.filterResonance, // dB
|
|
896
944
|
});
|
|
897
|
-
|
|
898
|
-
|
|
945
|
+
if (portamento) {
|
|
946
|
+
this.setPortamentoStartVolumeEnvelope(channel, note);
|
|
947
|
+
this.setPortamentoStartFilterEnvelope(channel, note);
|
|
948
|
+
}
|
|
949
|
+
else {
|
|
950
|
+
this.setVolumeEnvelope(channel, note);
|
|
951
|
+
this.setFilterEnvelope(channel, note);
|
|
952
|
+
}
|
|
899
953
|
if (0 < channel.vibratoDepth) {
|
|
900
954
|
this.startVibrato(channel, note, startTime);
|
|
901
955
|
}
|
|
@@ -912,7 +966,7 @@ export class Midy {
|
|
|
912
966
|
}
|
|
913
967
|
note.bufferSource.connect(note.filterNode);
|
|
914
968
|
note.filterNode.connect(note.volumeNode);
|
|
915
|
-
note.bufferSource.start(startTime
|
|
969
|
+
note.bufferSource.start(startTime);
|
|
916
970
|
return note;
|
|
917
971
|
}
|
|
918
972
|
calcBank(channel, channelNumber) {
|
|
@@ -924,7 +978,7 @@ export class Midy {
|
|
|
924
978
|
}
|
|
925
979
|
return channel.bank;
|
|
926
980
|
}
|
|
927
|
-
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
|
|
981
|
+
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime, portamento) {
|
|
928
982
|
const channel = this.channels[channelNumber];
|
|
929
983
|
const bankNumber = this.calcBank(channel, channelNumber);
|
|
930
984
|
const soundFontIndex = this.soundFontTable[channel.program].get(bankNumber);
|
|
@@ -935,7 +989,7 @@ export class Midy {
|
|
|
935
989
|
const instrumentKey = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber, velocity);
|
|
936
990
|
if (!instrumentKey)
|
|
937
991
|
return;
|
|
938
|
-
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
992
|
+
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, portamento, isSF3);
|
|
939
993
|
note.volumeNode.connect(channel.gainL);
|
|
940
994
|
note.volumeNode.connect(channel.gainR);
|
|
941
995
|
if (channel.sostenutoPedal) {
|
|
@@ -949,13 +1003,42 @@ export class Midy {
|
|
|
949
1003
|
scheduledNotes.set(noteNumber, [note]);
|
|
950
1004
|
}
|
|
951
1005
|
}
|
|
952
|
-
noteOn(channelNumber, noteNumber, velocity) {
|
|
1006
|
+
noteOn(channelNumber, noteNumber, velocity, portamento) {
|
|
953
1007
|
const now = this.audioContext.currentTime;
|
|
954
|
-
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
1008
|
+
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now, portamento);
|
|
955
1009
|
}
|
|
956
|
-
|
|
1010
|
+
stopNote(stopTime, endTime, scheduledNotes, index) {
|
|
1011
|
+
const note = scheduledNotes[index];
|
|
1012
|
+
note.volumeNode.gain
|
|
1013
|
+
.cancelScheduledValues(stopTime)
|
|
1014
|
+
.linearRampToValueAtTime(0, endTime);
|
|
1015
|
+
note.ending = true;
|
|
1016
|
+
this.scheduleTask(() => {
|
|
1017
|
+
note.bufferSource.loop = false;
|
|
1018
|
+
}, endTime);
|
|
1019
|
+
return new Promise((resolve) => {
|
|
1020
|
+
note.bufferSource.onended = () => {
|
|
1021
|
+
scheduledNotes[index] = null;
|
|
1022
|
+
note.bufferSource.disconnect();
|
|
1023
|
+
note.volumeNode.disconnect();
|
|
1024
|
+
note.filterNode.disconnect();
|
|
1025
|
+
if (note.modulationDepth) {
|
|
1026
|
+
note.volumeDepth.disconnect();
|
|
1027
|
+
note.modulationDepth.disconnect();
|
|
1028
|
+
note.modulationLFO.stop();
|
|
1029
|
+
}
|
|
1030
|
+
if (note.vibratoDepth) {
|
|
1031
|
+
note.vibratoDepth.disconnect();
|
|
1032
|
+
note.vibratoLFO.stop();
|
|
1033
|
+
}
|
|
1034
|
+
resolve();
|
|
1035
|
+
};
|
|
1036
|
+
note.bufferSource.stop(endTime);
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, portamentoNoteNumber, force) {
|
|
957
1040
|
const channel = this.channels[channelNumber];
|
|
958
|
-
if (
|
|
1041
|
+
if (!force) {
|
|
959
1042
|
if (channel.sustainPedal)
|
|
960
1043
|
return;
|
|
961
1044
|
if (channel.sostenutoNotes.has(noteNumber))
|
|
@@ -970,43 +1053,29 @@ export class Midy {
|
|
|
970
1053
|
continue;
|
|
971
1054
|
if (note.ending)
|
|
972
1055
|
continue;
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
.
|
|
977
|
-
.
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
.
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
note.filterNode.disconnect();
|
|
992
|
-
if (note.modulationDepth) {
|
|
993
|
-
note.volumeDepth.disconnect();
|
|
994
|
-
note.modulationDepth.disconnect();
|
|
995
|
-
note.modulationLFO.stop();
|
|
996
|
-
}
|
|
997
|
-
if (note.vibratoDepth) {
|
|
998
|
-
note.vibratoDepth.disconnect();
|
|
999
|
-
note.vibratoLFO.stop();
|
|
1000
|
-
}
|
|
1001
|
-
resolve();
|
|
1002
|
-
};
|
|
1003
|
-
note.bufferSource.stop(volEndTime);
|
|
1004
|
-
});
|
|
1056
|
+
if (portamentoNoteNumber === undefined) {
|
|
1057
|
+
const volEndTime = stopTime +
|
|
1058
|
+
note.instrumentKey.volRelease * channel.releaseTime;
|
|
1059
|
+
const modRelease = stopTime + note.instrumentKey.modRelease;
|
|
1060
|
+
note.filterNode.frequency
|
|
1061
|
+
.cancelScheduledValues(stopTime)
|
|
1062
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
1063
|
+
return this.stopNote(stopTime, volEndTime, scheduledNotes, i);
|
|
1064
|
+
}
|
|
1065
|
+
else {
|
|
1066
|
+
const portamentoTime = stopTime + channel.portamentoTime;
|
|
1067
|
+
const detuneChange = (portamentoNoteNumber - noteNumber) * 100;
|
|
1068
|
+
const detune = note.bufferSource.detune.value + detuneChange;
|
|
1069
|
+
note.bufferSource.detune
|
|
1070
|
+
.cancelScheduledValues(stopTime)
|
|
1071
|
+
.linearRampToValueAtTime(detune, portamentoTime);
|
|
1072
|
+
return this.stopNote(stopTime, portamentoTime, scheduledNotes, i);
|
|
1073
|
+
}
|
|
1005
1074
|
}
|
|
1006
1075
|
}
|
|
1007
|
-
releaseNote(channelNumber, noteNumber, velocity) {
|
|
1076
|
+
releaseNote(channelNumber, noteNumber, velocity, portamentoNoteNumber) {
|
|
1008
1077
|
const now = this.audioContext.currentTime;
|
|
1009
|
-
return this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now);
|
|
1078
|
+
return this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, portamentoNoteNumber, false);
|
|
1010
1079
|
}
|
|
1011
1080
|
releaseSustainPedal(channelNumber, halfVelocity) {
|
|
1012
1081
|
const velocity = halfVelocity * 2;
|
|
@@ -1181,12 +1250,14 @@ export class Midy {
|
|
|
1181
1250
|
this.updateModulation(channel);
|
|
1182
1251
|
}
|
|
1183
1252
|
setPortamentoTime(channelNumber, portamentoTime) {
|
|
1184
|
-
this.channels[channelNumber]
|
|
1253
|
+
const channel = this.channels[channelNumber];
|
|
1254
|
+
const factor = 5 * Math.log(10) / 127;
|
|
1255
|
+
channel.portamentoTime = Math.exp(factor * portamentoTime);
|
|
1185
1256
|
}
|
|
1186
1257
|
setVolume(channelNumber, volume) {
|
|
1187
1258
|
const channel = this.channels[channelNumber];
|
|
1188
1259
|
channel.volume = volume / 127;
|
|
1189
|
-
this.
|
|
1260
|
+
this.updateChannelVolume(channel);
|
|
1190
1261
|
}
|
|
1191
1262
|
panToGain(pan) {
|
|
1192
1263
|
const theta = Math.PI / 2 * Math.max(0, pan - 1) / 126;
|
|
@@ -1198,12 +1269,12 @@ export class Midy {
|
|
|
1198
1269
|
setPan(channelNumber, pan) {
|
|
1199
1270
|
const channel = this.channels[channelNumber];
|
|
1200
1271
|
channel.pan = pan;
|
|
1201
|
-
this.
|
|
1272
|
+
this.updateChannelVolume(channel);
|
|
1202
1273
|
}
|
|
1203
1274
|
setExpression(channelNumber, expression) {
|
|
1204
1275
|
const channel = this.channels[channelNumber];
|
|
1205
1276
|
channel.expression = expression / 127;
|
|
1206
|
-
this.
|
|
1277
|
+
this.updateChannelVolume(channel);
|
|
1207
1278
|
}
|
|
1208
1279
|
setBankLSB(channelNumber, lsb) {
|
|
1209
1280
|
this.channels[channelNumber].bankLSB = lsb;
|
|
@@ -1212,7 +1283,7 @@ export class Midy {
|
|
|
1212
1283
|
this.channels[channelNumber].dataLSB = value;
|
|
1213
1284
|
this.handleRPN(channelNumber, 0);
|
|
1214
1285
|
}
|
|
1215
|
-
|
|
1286
|
+
updateChannelVolume(channel) {
|
|
1216
1287
|
const now = this.audioContext.currentTime;
|
|
1217
1288
|
const volume = channel.volume * channel.expression;
|
|
1218
1289
|
const { gainLeft, gainRight } = this.panToGain(channel.pan);
|
|
@@ -1230,12 +1301,12 @@ export class Midy {
|
|
|
1230
1301
|
this.releaseSustainPedal(channelNumber, value);
|
|
1231
1302
|
}
|
|
1232
1303
|
}
|
|
1233
|
-
// TODO
|
|
1234
1304
|
setPortamento(channelNumber, value) {
|
|
1235
1305
|
this.channels[channelNumber].portamento = value >= 64;
|
|
1236
1306
|
}
|
|
1237
1307
|
setReverbSendLevel(channelNumber, reverbSendLevel) {
|
|
1238
1308
|
const channel = this.channels[channelNumber];
|
|
1309
|
+
const reverbEffect = this.reverbEffect;
|
|
1239
1310
|
if (0 < channel.reverbSendLevel) {
|
|
1240
1311
|
if (0 < reverbSendLevel) {
|
|
1241
1312
|
const now = this.audioContext.currentTime;
|
|
@@ -1554,20 +1625,22 @@ export class Midy {
|
|
|
1554
1625
|
}
|
|
1555
1626
|
}
|
|
1556
1627
|
GM1SystemOn() {
|
|
1557
|
-
this.channels.
|
|
1628
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
1629
|
+
const channel = this.channels[i];
|
|
1558
1630
|
channel.bankMSB = 0;
|
|
1559
1631
|
channel.bankLSB = 0;
|
|
1560
1632
|
channel.bank = 0;
|
|
1561
|
-
}
|
|
1633
|
+
}
|
|
1562
1634
|
this.channels[9].bankMSB = 1;
|
|
1563
1635
|
this.channels[9].bank = 128;
|
|
1564
1636
|
}
|
|
1565
1637
|
GM2SystemOn() {
|
|
1566
|
-
this.channels.
|
|
1638
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
1639
|
+
const channel = this.channels[i];
|
|
1567
1640
|
channel.bankMSB = 121;
|
|
1568
1641
|
channel.bankLSB = 0;
|
|
1569
1642
|
channel.bank = 121 * 128;
|
|
1570
|
-
}
|
|
1643
|
+
}
|
|
1571
1644
|
this.channels[9].bankMSB = 120;
|
|
1572
1645
|
this.channels[9].bank = 120 * 128;
|
|
1573
1646
|
}
|
|
@@ -1876,7 +1949,7 @@ Object.defineProperty(Midy, "channelSettings", {
|
|
|
1876
1949
|
currentBufferSource: null,
|
|
1877
1950
|
volume: 100 / 127,
|
|
1878
1951
|
pan: 64,
|
|
1879
|
-
portamentoTime:
|
|
1952
|
+
portamentoTime: 1, // sec
|
|
1880
1953
|
filterResonance: 1,
|
|
1881
1954
|
releaseTime: 1,
|
|
1882
1955
|
attackTime: 1,
|
package/package.json
CHANGED
package/script/midy-GM1.d.ts
CHANGED
|
@@ -66,7 +66,6 @@ export class MidyGM1 {
|
|
|
66
66
|
createChannels(audioContext: any): any[];
|
|
67
67
|
createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
|
|
68
68
|
createNoteBufferNode(instrumentKey: any, isSF3: any): Promise<any>;
|
|
69
|
-
convertToFloat32Array(uint8Array: any): Float32Array;
|
|
70
69
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
71
70
|
getQueueIndex(second: any): number;
|
|
72
71
|
playNotes(): Promise<any>;
|
|
@@ -76,8 +75,8 @@ export class MidyGM1 {
|
|
|
76
75
|
instruments: Set<any>;
|
|
77
76
|
timeline: any[];
|
|
78
77
|
};
|
|
79
|
-
stopChannelNotes(channelNumber: any, velocity: any,
|
|
80
|
-
stopNotes(velocity: any,
|
|
78
|
+
stopChannelNotes(channelNumber: any, velocity: any, force: any): Promise<void>;
|
|
79
|
+
stopNotes(velocity: any, force: any): Promise<any[]>;
|
|
81
80
|
start(): Promise<void>;
|
|
82
81
|
stop(): void;
|
|
83
82
|
pause(): void;
|
|
@@ -99,10 +98,11 @@ export class MidyGM1 {
|
|
|
99
98
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
100
99
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
101
100
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
stopNote(stopTime: any, endTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
102
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, force: any): void;
|
|
103
|
+
releaseNote(channelNumber: any, noteNumber: any, velocity: any): void;
|
|
104
104
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
105
|
-
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<
|
|
105
|
+
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<void>;
|
|
106
106
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
107
107
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
108
108
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
@@ -131,7 +131,7 @@ export class MidyGM1 {
|
|
|
131
131
|
setPan(channelNumber: any, pan: any): void;
|
|
132
132
|
setExpression(channelNumber: any, expression: any): void;
|
|
133
133
|
dataEntryLSB(channelNumber: any, value: any): void;
|
|
134
|
-
|
|
134
|
+
updateChannelVolume(channel: any): void;
|
|
135
135
|
setSustainPedal(channelNumber: any, value: any): void;
|
|
136
136
|
limitData(channel: any, minMSB: any, maxMSB: any, minLSB: any, maxLSB: any): void;
|
|
137
137
|
limitDataMSB(channel: any, minMSB: any, maxMSB: any): void;
|
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":"AAwBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAOC;IA/CD,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;IAyBhB,kBAAgC;IAChC,gBAA4C;IAC5C;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,
|
|
1
|
+
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAwBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAOC;IA/CD,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;IAyBhB,kBAAgC;IAChC,gBAA4C;IAC5C;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,+DAuBC;IAED,mEAWC;IAED,2EA+CC;IAED,mCAOC;IAED,0BA+CC;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,4BAEC;IAED,sCAGC;IAED,mFAGC;IAED,mCAeC;IAED,+CAwBC;IAED,6CAIC;IAED,mCAsBC;IAED,+DA0BC;IAED,wHAgCC;IAED,kGA8BC;IAED,0EAGC;IAED,qFA4BC;IAED,0GAsBC;IAED,sEAGC;IAED,kEAeC;IAED,iFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,uDAOC;IAED;;;;;;;;;;;;;MAeC;IAED,2EASC;IAED,qCAkBC;IAED,8DAIC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,wCAUC;IAED,sDAMC;IAED,kFAeC;IAED,2DAMC;IAED,oCAkBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAaC;IAED,kDAKC;IAED,iEAOC;IAED,8CAKC;IAED,yDAMC;IAED,gDAKC;IAED,6DAMC;IAED,+CAEC;IAED,8CAEC;IAED,+CAEC;IAED,4DAgBC;IAED,oBASC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAnjCD;IAUE,gFAKC;IAdD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|