@marmooo/midy 0.3.5 → 0.3.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 +2 -2
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +15 -12
- package/esm/midy-GM2.d.ts +11 -11
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +139 -166
- package/esm/midy-GMLite.d.ts +2 -2
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +15 -12
- package/esm/midy.d.ts +15 -15
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +145 -172
- package/package.json +2 -2
- package/script/midy-GM1.d.ts +2 -2
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +15 -12
- package/script/midy-GM2.d.ts +11 -11
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +139 -166
- package/script/midy-GMLite.d.ts +2 -2
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +15 -12
- package/script/midy.d.ts +15 -15
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +145 -172
package/script/midy-GM2.js
CHANGED
|
@@ -71,13 +71,13 @@ class Note {
|
|
|
71
71
|
writable: true,
|
|
72
72
|
value: void 0
|
|
73
73
|
});
|
|
74
|
-
Object.defineProperty(this, "
|
|
74
|
+
Object.defineProperty(this, "reverbSend", {
|
|
75
75
|
enumerable: true,
|
|
76
76
|
configurable: true,
|
|
77
77
|
writable: true,
|
|
78
78
|
value: void 0
|
|
79
79
|
});
|
|
80
|
-
Object.defineProperty(this, "
|
|
80
|
+
Object.defineProperty(this, "chorusSend", {
|
|
81
81
|
enumerable: true,
|
|
82
82
|
configurable: true,
|
|
83
83
|
writable: true,
|
|
@@ -365,17 +365,17 @@ class MidyGM2 {
|
|
|
365
365
|
writable: true,
|
|
366
366
|
value: []
|
|
367
367
|
});
|
|
368
|
-
Object.defineProperty(this, "
|
|
368
|
+
Object.defineProperty(this, "notePromises", {
|
|
369
369
|
enumerable: true,
|
|
370
370
|
configurable: true,
|
|
371
371
|
writable: true,
|
|
372
372
|
value: []
|
|
373
373
|
});
|
|
374
|
-
Object.defineProperty(this, "
|
|
374
|
+
Object.defineProperty(this, "instruments", {
|
|
375
375
|
enumerable: true,
|
|
376
376
|
configurable: true,
|
|
377
377
|
writable: true,
|
|
378
|
-
value:
|
|
378
|
+
value: new Set()
|
|
379
379
|
});
|
|
380
380
|
Object.defineProperty(this, "exclusiveClassNotes", {
|
|
381
381
|
enumerable: true,
|
|
@@ -507,7 +507,7 @@ class MidyGM2 {
|
|
|
507
507
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
508
508
|
const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
|
|
509
509
|
const { instrument, sampleID } = voice.generators;
|
|
510
|
-
return
|
|
510
|
+
return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
|
|
511
511
|
}
|
|
512
512
|
createChannelAudioNodes(audioContext) {
|
|
513
513
|
const { gainLeft, gainRight } = this.panToGain(defaultControllerState.pan.defaultValue);
|
|
@@ -907,13 +907,11 @@ class MidyGM2 {
|
|
|
907
907
|
return impulse;
|
|
908
908
|
}
|
|
909
909
|
createConvolutionReverb(audioContext, impulse) {
|
|
910
|
-
const input = new GainNode(audioContext);
|
|
911
910
|
const convolverNode = new ConvolverNode(audioContext, {
|
|
912
911
|
buffer: impulse,
|
|
913
912
|
});
|
|
914
|
-
input.connect(convolverNode);
|
|
915
913
|
return {
|
|
916
|
-
input,
|
|
914
|
+
input: convolverNode,
|
|
917
915
|
output: convolverNode,
|
|
918
916
|
convolverNode,
|
|
919
917
|
};
|
|
@@ -1343,12 +1341,8 @@ class MidyGM2 {
|
|
|
1343
1341
|
}
|
|
1344
1342
|
note.bufferSource.connect(note.filterNode);
|
|
1345
1343
|
note.filterNode.connect(note.volumeEnvelopeNode);
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
}
|
|
1349
|
-
if (0 < state.reverbSendLevel) {
|
|
1350
|
-
this.setReverbEffectsSend(channel, note, 0, now);
|
|
1351
|
-
}
|
|
1344
|
+
this.setChorusSend(channel, note, now);
|
|
1345
|
+
this.setReverbSend(channel, note, now);
|
|
1352
1346
|
note.bufferSource.start(startTime);
|
|
1353
1347
|
return note;
|
|
1354
1348
|
}
|
|
@@ -1414,10 +1408,14 @@ class MidyGM2 {
|
|
|
1414
1408
|
return;
|
|
1415
1409
|
const note = await this.createNote(channel, voice, noteNumber, velocity, startTime);
|
|
1416
1410
|
if (channel.isDrum) {
|
|
1417
|
-
const
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1411
|
+
const { keyBasedGainLs, keyBasedGainRs } = channel;
|
|
1412
|
+
let gainL = keyBasedGainLs[noteNumber];
|
|
1413
|
+
let gainR = keyBasedGainRs[noteNumber];
|
|
1414
|
+
if (!gainL) {
|
|
1415
|
+
const audioNodes = this.createChannelAudioNodes(this.audioContext);
|
|
1416
|
+
gainL = keyBasedGainLs[noteNumber] = audioNodes.gainL;
|
|
1417
|
+
gainR = keyBasedGainRs[noteNumber] = audioNodes.gainR;
|
|
1418
|
+
}
|
|
1421
1419
|
note.volumeEnvelopeNode.connect(gainL);
|
|
1422
1420
|
note.volumeEnvelopeNode.connect(gainR);
|
|
1423
1421
|
}
|
|
@@ -1451,11 +1449,11 @@ class MidyGM2 {
|
|
|
1451
1449
|
note.vibratoDepth.disconnect();
|
|
1452
1450
|
note.vibratoLFO.stop();
|
|
1453
1451
|
}
|
|
1454
|
-
if (note.
|
|
1455
|
-
note.
|
|
1452
|
+
if (note.reverbSend) {
|
|
1453
|
+
note.reverbSend.disconnect();
|
|
1456
1454
|
}
|
|
1457
|
-
if (note.
|
|
1458
|
-
note.
|
|
1455
|
+
if (note.chorusSend) {
|
|
1456
|
+
note.chorusSend.disconnect();
|
|
1459
1457
|
}
|
|
1460
1458
|
}
|
|
1461
1459
|
releaseNote(channel, note, endTime) {
|
|
@@ -1606,7 +1604,7 @@ class MidyGM2 {
|
|
|
1606
1604
|
}
|
|
1607
1605
|
const table = channel.channelPressureTable;
|
|
1608
1606
|
this.processActiveNotes(channel, scheduleTime, (note) => {
|
|
1609
|
-
this.
|
|
1607
|
+
this.setEffects(channel, note, table);
|
|
1610
1608
|
});
|
|
1611
1609
|
this.applyVoiceParams(channel, 13);
|
|
1612
1610
|
}
|
|
@@ -1628,13 +1626,18 @@ class MidyGM2 {
|
|
|
1628
1626
|
this.applyVoiceParams(channel, 14, scheduleTime);
|
|
1629
1627
|
}
|
|
1630
1628
|
setModLfoToPitch(channel, note, scheduleTime) {
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
.
|
|
1637
|
-
|
|
1629
|
+
if (note.modulationDepth) {
|
|
1630
|
+
const modLfoToPitch = note.voiceParams.modLfoToPitch +
|
|
1631
|
+
this.getLFOPitchDepth(channel, note);
|
|
1632
|
+
const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
|
|
1633
|
+
const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
|
|
1634
|
+
note.modulationDepth.gain
|
|
1635
|
+
.cancelScheduledValues(scheduleTime)
|
|
1636
|
+
.setValueAtTime(modulationDepth, scheduleTime);
|
|
1637
|
+
}
|
|
1638
|
+
else {
|
|
1639
|
+
this.startModulation(channel, note, scheduleTime);
|
|
1640
|
+
}
|
|
1638
1641
|
}
|
|
1639
1642
|
setVibLfoToPitch(channel, note, scheduleTime) {
|
|
1640
1643
|
const vibLfoToPitch = note.voiceParams.vibLfoToPitch;
|
|
@@ -1661,63 +1664,63 @@ class MidyGM2 {
|
|
|
1661
1664
|
.cancelScheduledValues(scheduleTime)
|
|
1662
1665
|
.setValueAtTime(volumeDepth, scheduleTime);
|
|
1663
1666
|
}
|
|
1664
|
-
|
|
1665
|
-
let value = note.voiceParams.reverbEffectsSend
|
|
1667
|
+
setReverbSend(channel, note, scheduleTime) {
|
|
1668
|
+
let value = note.voiceParams.reverbEffectsSend *
|
|
1669
|
+
channel.state.reverbSendLevel;
|
|
1666
1670
|
if (channel.isDrum) {
|
|
1667
1671
|
const keyBasedValue = this.getKeyBasedValue(channel, note.noteNumber, 91);
|
|
1668
|
-
if (0 <= keyBasedValue)
|
|
1669
|
-
value
|
|
1670
|
-
}
|
|
1672
|
+
if (0 <= keyBasedValue)
|
|
1673
|
+
value = keyBasedValue / 127;
|
|
1671
1674
|
}
|
|
1672
|
-
if (
|
|
1675
|
+
if (!note.reverbSend) {
|
|
1673
1676
|
if (0 < value) {
|
|
1674
|
-
note.
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
}
|
|
1678
|
-
else {
|
|
1679
|
-
note.reverbEffectsSend.disconnect();
|
|
1677
|
+
note.reverbSend = new GainNode(this.audioContext, { gain: value });
|
|
1678
|
+
note.volumeEnvelopeNode.connect(note.reverbSend);
|
|
1679
|
+
note.reverbSend.connect(this.reverbEffect.input);
|
|
1680
1680
|
}
|
|
1681
1681
|
}
|
|
1682
1682
|
else {
|
|
1683
|
+
note.reverbSend.gain
|
|
1684
|
+
.cancelScheduledValues(scheduleTime)
|
|
1685
|
+
.setValueAtTime(value, scheduleTime);
|
|
1683
1686
|
if (0 < value) {
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
note.
|
|
1687
|
+
note.volumeEnvelopeNode.connect(note.reverbSend);
|
|
1688
|
+
}
|
|
1689
|
+
else {
|
|
1690
|
+
try {
|
|
1691
|
+
note.volumeEnvelopeNode.disconnect(note.reverbSend);
|
|
1689
1692
|
}
|
|
1690
|
-
|
|
1693
|
+
catch { /* empty */ }
|
|
1691
1694
|
}
|
|
1692
1695
|
}
|
|
1693
1696
|
}
|
|
1694
|
-
|
|
1695
|
-
let value = note.voiceParams.chorusEffectsSend
|
|
1697
|
+
setChorusSend(channel, note, scheduleTime) {
|
|
1698
|
+
let value = note.voiceParams.chorusEffectsSend *
|
|
1699
|
+
channel.state.chorusSendLevel;
|
|
1696
1700
|
if (channel.isDrum) {
|
|
1697
1701
|
const keyBasedValue = this.getKeyBasedValue(channel, note.noteNumber, 93);
|
|
1698
|
-
if (0 <= keyBasedValue)
|
|
1699
|
-
value
|
|
1700
|
-
}
|
|
1702
|
+
if (0 <= keyBasedValue)
|
|
1703
|
+
value = keyBasedValue / 127;
|
|
1701
1704
|
}
|
|
1702
|
-
if (
|
|
1705
|
+
if (!note.chorusSend) {
|
|
1703
1706
|
if (0 < value) {
|
|
1704
|
-
note.
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
}
|
|
1708
|
-
else {
|
|
1709
|
-
note.chorusEffectsSend.disconnect();
|
|
1707
|
+
note.chorusSend = new GainNode(this.audioContext, { gain: value });
|
|
1708
|
+
note.volumeEnvelopeNode.connect(note.chorusSend);
|
|
1709
|
+
note.chorusSend.connect(this.chorusEffect.input);
|
|
1710
1710
|
}
|
|
1711
1711
|
}
|
|
1712
1712
|
else {
|
|
1713
|
+
note.chorusSend.gain
|
|
1714
|
+
.cancelScheduledValues(scheduleTime)
|
|
1715
|
+
.setValueAtTime(value, scheduleTime);
|
|
1713
1716
|
if (0 < value) {
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
note.volumeEnvelopeNode.
|
|
1717
|
+
note.volumeEnvelopeNode.connect(note.chorusSend);
|
|
1718
|
+
}
|
|
1719
|
+
else {
|
|
1720
|
+
try {
|
|
1721
|
+
note.volumeEnvelopeNode.disconnect(note.chorusSend);
|
|
1719
1722
|
}
|
|
1720
|
-
|
|
1723
|
+
catch { /* empty */ }
|
|
1721
1724
|
}
|
|
1722
1725
|
}
|
|
1723
1726
|
}
|
|
@@ -1866,7 +1869,7 @@ class MidyGM2 {
|
|
|
1866
1869
|
handler.call(this, channelNumber, value, scheduleTime);
|
|
1867
1870
|
const channel = this.channels[channelNumber];
|
|
1868
1871
|
this.applyVoiceParams(channel, controllerType + 128, scheduleTime);
|
|
1869
|
-
this.
|
|
1872
|
+
this.setControlChangeEffects(channel, controllerType, scheduleTime);
|
|
1870
1873
|
}
|
|
1871
1874
|
else {
|
|
1872
1875
|
console.warn(`Unsupported Control change: controllerType=${controllerType} value=${value}`);
|
|
@@ -1882,7 +1885,6 @@ class MidyGM2 {
|
|
|
1882
1885
|
note.modulationDepth.gain.setValueAtTime(depth, scheduleTime);
|
|
1883
1886
|
}
|
|
1884
1887
|
else {
|
|
1885
|
-
this.setPitchEnvelope(note, scheduleTime);
|
|
1886
1888
|
this.startModulation(channel, note, scheduleTime);
|
|
1887
1889
|
}
|
|
1888
1890
|
});
|
|
@@ -1927,8 +1929,14 @@ class MidyGM2 {
|
|
|
1927
1929
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1928
1930
|
const channel = this.channels[channelNumber];
|
|
1929
1931
|
channel.state.volume = volume / 127;
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
+
if (channel.isDrum) {
|
|
1933
|
+
for (let i = 0; i < 128; i++) {
|
|
1934
|
+
this.updateKeyBasedVolume(channel, i, scheduleTime);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
else {
|
|
1938
|
+
this.updateChannelVolume(channel, scheduleTime);
|
|
1939
|
+
}
|
|
1932
1940
|
}
|
|
1933
1941
|
panToGain(pan) {
|
|
1934
1942
|
const theta = Math.PI / 2 * Math.max(0, pan * 127 - 1) / 126;
|
|
@@ -1941,8 +1949,14 @@ class MidyGM2 {
|
|
|
1941
1949
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1942
1950
|
const channel = this.channels[channelNumber];
|
|
1943
1951
|
channel.state.pan = pan / 127;
|
|
1944
|
-
|
|
1945
|
-
|
|
1952
|
+
if (channel.isDrum) {
|
|
1953
|
+
for (let i = 0; i < 128; i++) {
|
|
1954
|
+
this.updateKeyBasedVolume(channel, i, scheduleTime);
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
else {
|
|
1958
|
+
this.updateChannelVolume(channel, scheduleTime);
|
|
1959
|
+
}
|
|
1946
1960
|
}
|
|
1947
1961
|
setExpression(channelNumber, expression, scheduleTime) {
|
|
1948
1962
|
scheduleTime ??= this.audioContext.currentTime;
|
|
@@ -1968,33 +1982,27 @@ class MidyGM2 {
|
|
|
1968
1982
|
.cancelScheduledValues(scheduleTime)
|
|
1969
1983
|
.setValueAtTime(volume * gainRight, scheduleTime);
|
|
1970
1984
|
}
|
|
1971
|
-
updateKeyBasedVolume(channel, scheduleTime) {
|
|
1972
|
-
if (!channel.isDrum)
|
|
1973
|
-
return;
|
|
1985
|
+
updateKeyBasedVolume(channel, keyNumber, scheduleTime) {
|
|
1974
1986
|
const state = channel.state;
|
|
1975
1987
|
const defaultVolume = state.volume * state.expression;
|
|
1976
1988
|
const defaultPan = state.pan;
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
gainR.gain
|
|
1995
|
-
.cancelScheduledValues(scheduleTime)
|
|
1996
|
-
.setValueAtTime(volume * gainRight, scheduleTime);
|
|
1997
|
-
}
|
|
1989
|
+
const gainL = channel.keyBasedGainLs[keyNumber];
|
|
1990
|
+
const gainR = channel.keyBasedGainRs[keyNumber];
|
|
1991
|
+
if (!gainL)
|
|
1992
|
+
return;
|
|
1993
|
+
const keyBasedVolume = this.getKeyBasedValue(channel, keyNumber, 7);
|
|
1994
|
+
const volume = (0 <= keyBasedVolume)
|
|
1995
|
+
? defaultVolume * keyBasedVolume / 64
|
|
1996
|
+
: defaultVolume;
|
|
1997
|
+
const keyBasedPan = this.getKeyBasedValue(channel, keyNumber, 10);
|
|
1998
|
+
const pan = (0 <= keyBasedPan) ? keyBasedPan / 127 : defaultPan;
|
|
1999
|
+
const { gainLeft, gainRight } = this.panToGain(pan);
|
|
2000
|
+
gainL.gain
|
|
2001
|
+
.cancelScheduledValues(scheduleTime)
|
|
2002
|
+
.setValueAtTime(volume * gainLeft, scheduleTime);
|
|
2003
|
+
gainR.gain
|
|
2004
|
+
.cancelScheduledValues(scheduleTime)
|
|
2005
|
+
.setValueAtTime(volume * gainRight, scheduleTime);
|
|
1998
2006
|
}
|
|
1999
2007
|
setSustainPedal(channelNumber, value, scheduleTime) {
|
|
2000
2008
|
const channel = this.channels[channelNumber];
|
|
@@ -2061,67 +2069,19 @@ class MidyGM2 {
|
|
|
2061
2069
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2062
2070
|
const channel = this.channels[channelNumber];
|
|
2063
2071
|
const state = channel.state;
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
reverbEffect.input.gain
|
|
2069
|
-
.cancelScheduledValues(scheduleTime)
|
|
2070
|
-
.setValueAtTime(state.reverbSendLevel, scheduleTime);
|
|
2071
|
-
}
|
|
2072
|
-
else {
|
|
2073
|
-
this.processScheduledNotes(channel, (note) => {
|
|
2074
|
-
if (note.voiceParams.reverbEffectsSend <= 0)
|
|
2075
|
-
return false;
|
|
2076
|
-
if (note.reverbEffectsSend)
|
|
2077
|
-
note.reverbEffectsSend.disconnect();
|
|
2078
|
-
});
|
|
2079
|
-
}
|
|
2080
|
-
}
|
|
2081
|
-
else {
|
|
2082
|
-
if (0 < reverbSendLevel) {
|
|
2083
|
-
this.processScheduledNotes(channel, (note) => {
|
|
2084
|
-
this.setReverbEffectsSend(channel, note, 0, scheduleTime);
|
|
2085
|
-
});
|
|
2086
|
-
state.reverbSendLevel = reverbSendLevel / 127;
|
|
2087
|
-
reverbEffect.input.gain
|
|
2088
|
-
.cancelScheduledValues(scheduleTime)
|
|
2089
|
-
.setValueAtTime(state.reverbSendLevel, scheduleTime);
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2072
|
+
state.reverbSendLevel = reverbSendLevel / 127;
|
|
2073
|
+
this.processScheduledNotes(channel, (note) => {
|
|
2074
|
+
this.setReverbSend(channel, note, scheduleTime);
|
|
2075
|
+
});
|
|
2092
2076
|
}
|
|
2093
2077
|
setChorusSendLevel(channelNumber, chorusSendLevel, scheduleTime) {
|
|
2094
2078
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2095
2079
|
const channel = this.channels[channelNumber];
|
|
2096
2080
|
const state = channel.state;
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
chorusEffect.input.gain
|
|
2102
|
-
.cancelScheduledValues(scheduleTime)
|
|
2103
|
-
.setValueAtTime(state.chorusSendLevel, scheduleTime);
|
|
2104
|
-
}
|
|
2105
|
-
else {
|
|
2106
|
-
this.processScheduledNotes(channel, (note) => {
|
|
2107
|
-
if (note.voiceParams.chorusEffectsSend <= 0)
|
|
2108
|
-
return false;
|
|
2109
|
-
if (note.chorusEffectsSend)
|
|
2110
|
-
note.chorusEffectsSend.disconnect();
|
|
2111
|
-
});
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
|
-
else {
|
|
2115
|
-
if (0 < chorusSendLevel) {
|
|
2116
|
-
this.processScheduledNotes(channel, (note) => {
|
|
2117
|
-
this.setChorusEffectsSend(channel, note, 0, scheduleTime);
|
|
2118
|
-
});
|
|
2119
|
-
state.chorusSendLevel = chorusSendLevel / 127;
|
|
2120
|
-
chorusEffect.input.gain
|
|
2121
|
-
.cancelScheduledValues(scheduleTime)
|
|
2122
|
-
.setValueAtTime(state.chorusSendLevel, scheduleTime);
|
|
2123
|
-
}
|
|
2124
|
-
}
|
|
2081
|
+
state.chorusSendLevel = chorusSendLevel / 127;
|
|
2082
|
+
this.processScheduledNotes(channel, (note) => {
|
|
2083
|
+
this.setChorusSend(channel, note, scheduleTime);
|
|
2084
|
+
});
|
|
2125
2085
|
}
|
|
2126
2086
|
limitData(channel, minMSB, maxMSB, minLSB, maxLSB) {
|
|
2127
2087
|
if (maxLSB < channel.dataLSB) {
|
|
@@ -2403,9 +2363,9 @@ class MidyGM2 {
|
|
|
2403
2363
|
case 9:
|
|
2404
2364
|
switch (data[3]) {
|
|
2405
2365
|
case 1: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
|
|
2406
|
-
return this.handlePressureSysEx(data, "channelPressureTable");
|
|
2366
|
+
return this.handlePressureSysEx(data, "channelPressureTable", scheduleTime);
|
|
2407
2367
|
case 3: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
|
|
2408
|
-
return this.handleControlChangeSysEx(data);
|
|
2368
|
+
return this.handleControlChangeSysEx(data, scheduleTime);
|
|
2409
2369
|
default:
|
|
2410
2370
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
2411
2371
|
}
|
|
@@ -2724,9 +2684,9 @@ class MidyGM2 {
|
|
|
2724
2684
|
: 0;
|
|
2725
2685
|
return channelPressure / 127;
|
|
2726
2686
|
}
|
|
2727
|
-
|
|
2687
|
+
setEffects(channel, note, table, scheduleTime) {
|
|
2728
2688
|
if (0 <= table[0])
|
|
2729
|
-
this.updateDetune(channel, note,
|
|
2689
|
+
this.updateDetune(channel, note, scheduleTime);
|
|
2730
2690
|
if (0.5 <= channel.state.portamemento && 0 <= note.portamentoNoteNumber) {
|
|
2731
2691
|
if (0 <= table[1]) {
|
|
2732
2692
|
this.setPortamentoFilterEnvelope(channel, note, scheduleTime);
|
|
@@ -2748,7 +2708,7 @@ class MidyGM2 {
|
|
|
2748
2708
|
if (0 <= table[5])
|
|
2749
2709
|
this.setModLfoToVolume(channel, note, scheduleTime);
|
|
2750
2710
|
}
|
|
2751
|
-
handlePressureSysEx(data, tableName) {
|
|
2711
|
+
handlePressureSysEx(data, tableName, scheduleTime) {
|
|
2752
2712
|
const channelNumber = data[4];
|
|
2753
2713
|
const channel = this.channels[channelNumber];
|
|
2754
2714
|
if (channel.isDrum)
|
|
@@ -2759,32 +2719,38 @@ class MidyGM2 {
|
|
|
2759
2719
|
const rr = data[i + 1];
|
|
2760
2720
|
table[pp] = rr;
|
|
2761
2721
|
}
|
|
2722
|
+
this.processActiveNotes(channel, scheduleTime, (note) => {
|
|
2723
|
+
this.setEffects(channel, note, table, scheduleTime);
|
|
2724
|
+
});
|
|
2762
2725
|
}
|
|
2763
2726
|
initControlTable() {
|
|
2764
2727
|
const ccCount = 128;
|
|
2765
2728
|
const slotSize = 6;
|
|
2766
2729
|
return new Int8Array(ccCount * slotSize).fill(-1);
|
|
2767
2730
|
}
|
|
2768
|
-
|
|
2731
|
+
setControlChangeEffects(channel, controllerType, scheduleTime) {
|
|
2769
2732
|
const slotSize = 6;
|
|
2770
2733
|
const offset = controllerType * slotSize;
|
|
2771
2734
|
const table = channel.controlTable.subarray(offset, offset + slotSize);
|
|
2772
2735
|
this.processScheduledNotes(channel, (note) => {
|
|
2773
|
-
this.
|
|
2736
|
+
this.setEffects(channel, note, table, scheduleTime);
|
|
2774
2737
|
});
|
|
2775
2738
|
}
|
|
2776
|
-
handleControlChangeSysEx(data) {
|
|
2739
|
+
handleControlChangeSysEx(data, scheduleTime) {
|
|
2777
2740
|
const channelNumber = data[4];
|
|
2778
2741
|
const channel = this.channels[channelNumber];
|
|
2779
2742
|
if (channel.isDrum)
|
|
2780
2743
|
return;
|
|
2744
|
+
const slotSize = 6;
|
|
2781
2745
|
const controllerType = data[5];
|
|
2782
|
-
const
|
|
2783
|
-
|
|
2746
|
+
const offset = controllerType * slotSize;
|
|
2747
|
+
const table = channel.controlTable;
|
|
2748
|
+
for (let i = 6; i < data.length; i += 2) {
|
|
2784
2749
|
const pp = data[i];
|
|
2785
2750
|
const rr = data[i + 1];
|
|
2786
|
-
table[pp] = rr;
|
|
2751
|
+
table[offset + pp] = rr;
|
|
2787
2752
|
}
|
|
2753
|
+
this.setControlChangeEffects(channel, controllerType, scheduleTime);
|
|
2788
2754
|
}
|
|
2789
2755
|
getKeyBasedValue(channel, keyNumber, controllerType) {
|
|
2790
2756
|
const index = keyNumber * 128 + controllerType;
|
|
@@ -2798,13 +2764,20 @@ class MidyGM2 {
|
|
|
2798
2764
|
return;
|
|
2799
2765
|
const keyNumber = data[5];
|
|
2800
2766
|
const table = channel.keyBasedInstrumentControlTable;
|
|
2801
|
-
for (let i = 6; i < data.length
|
|
2767
|
+
for (let i = 6; i < data.length; i += 2) {
|
|
2802
2768
|
const controllerType = data[i];
|
|
2803
2769
|
const value = data[i + 1];
|
|
2804
2770
|
const index = keyNumber * 128 + controllerType;
|
|
2805
2771
|
table[index] = value;
|
|
2772
|
+
switch (controllerType) {
|
|
2773
|
+
case 7:
|
|
2774
|
+
case 10:
|
|
2775
|
+
this.updateKeyBasedVolume(channel, keyNumber, scheduleTime);
|
|
2776
|
+
break;
|
|
2777
|
+
default: // TODO
|
|
2778
|
+
this.setControlChange(channelNumber, controllerType, value, scheduleTime);
|
|
2779
|
+
}
|
|
2806
2780
|
}
|
|
2807
|
-
this.setChannelPressure(channelNumber, channel.state.channelPressure * 127, scheduleTime);
|
|
2808
2781
|
}
|
|
2809
2782
|
handleSysEx(data, scheduleTime) {
|
|
2810
2783
|
switch (data[0]) {
|
package/script/midy-GMLite.d.ts
CHANGED
|
@@ -30,8 +30,8 @@ export class MidyGMLite {
|
|
|
30
30
|
isStopping: boolean;
|
|
31
31
|
isSeeking: boolean;
|
|
32
32
|
timeline: any[];
|
|
33
|
-
instruments: any[];
|
|
34
33
|
notePromises: any[];
|
|
34
|
+
instruments: Set<any>;
|
|
35
35
|
exclusiveClassNotes: any[];
|
|
36
36
|
drumExclusiveClassNotes: any[];
|
|
37
37
|
audioContext: any;
|
|
@@ -58,7 +58,7 @@ export class MidyGMLite {
|
|
|
58
58
|
loadSoundFont(input: any): Promise<void>;
|
|
59
59
|
loadMIDI(input: any): Promise<void>;
|
|
60
60
|
cacheVoiceIds(): void;
|
|
61
|
-
getVoiceId(channel: any, noteNumber: any, velocity: any):
|
|
61
|
+
getVoiceId(channel: any, noteNumber: any, velocity: any): any;
|
|
62
62
|
createChannelAudioNodes(audioContext: any): {
|
|
63
63
|
gainL: any;
|
|
64
64
|
gainR: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AA0GA;IA2BE;;;;;;;;;;MAUE;IAEF,+BAcC;IApDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,4BAAyB;IACzB,0BAAuB;IACvB,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,
|
|
1
|
+
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AA0GA;IA2BE;;;;;;;;;;MAUE;IAEF,+BAcC;IApDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,4BAAyB;IACzB,0BAAuB;IACvB,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IACrC,+BAEE;IAeA,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,gBAAiD;IAMnD,4BAMC;IAED,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAcC;IAED;;;;MAeC;IAED,yCAaC;IAED,kDAUC;IAED,0EAUC;IAED,+EAkDC;IAED,mCAOC;IAED,0BAiEC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgEC;IAED,kGAeC;IAED,mGAeC;IAED,wEAMC;IAED,uBAMC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,yEASC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,wCAIC;IAED,2DAIC;IAED,+DAIC;IAED,sDAeC;IAED,qDAoBC;IAED,6CAIC;IAED,sDAsBC;IAED,kEAoBC;IAED,6FAyBC;IAED,oGAuCC;IAED,0EAiBC;IAED,8EAiBC;IAED,kGAoCC;IAED,6FASC;IAED,gCASC;IAED,iEAoBC;IAED,qGAkBC;IAED,6CAUC;IAED,qDAUC;IAED,qFASC;IAED,sFAeC;IAED,oGA2BC;IAED,mFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAWC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MA2BC;IAED,oFAMC;IAED,6EAgCC;IAED,qCAeC;IAED,+FAWC;IAED,wDASC;IAED,iFAKC;IAED,oEAKC;IAED;;;MAMC;IAED,8DAKC;IAED,4EAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAWC;IAED,kFAeC;IAED,uDAYC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAUC;IAED,gFAGC;IAED,yCAqBC;IAGD,8EAgCC;IAED,gFAGC;IAED,+EAgBC;IAED,qCAWC;IAED,4EAaC;IAED,4DAGC;IAED,sDASC;IAED,gDAYC;IAGD,6DAgBC;CACF;AAx/CD;IAWE,0FAMC;IAhBD,cAAW;IACX,gBAAe;IACf,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
|
package/script/midy-GMLite.js
CHANGED
|
@@ -266,17 +266,17 @@ class MidyGMLite {
|
|
|
266
266
|
writable: true,
|
|
267
267
|
value: []
|
|
268
268
|
});
|
|
269
|
-
Object.defineProperty(this, "
|
|
269
|
+
Object.defineProperty(this, "notePromises", {
|
|
270
270
|
enumerable: true,
|
|
271
271
|
configurable: true,
|
|
272
272
|
writable: true,
|
|
273
273
|
value: []
|
|
274
274
|
});
|
|
275
|
-
Object.defineProperty(this, "
|
|
275
|
+
Object.defineProperty(this, "instruments", {
|
|
276
276
|
enumerable: true,
|
|
277
277
|
configurable: true,
|
|
278
278
|
writable: true,
|
|
279
|
-
value:
|
|
279
|
+
value: new Set()
|
|
280
280
|
});
|
|
281
281
|
Object.defineProperty(this, "exclusiveClassNotes", {
|
|
282
282
|
enumerable: true,
|
|
@@ -404,7 +404,7 @@ class MidyGMLite {
|
|
|
404
404
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
405
405
|
const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
|
|
406
406
|
const { instrument, sampleID } = voice.generators;
|
|
407
|
-
return
|
|
407
|
+
return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
|
|
408
408
|
}
|
|
409
409
|
createChannelAudioNodes(audioContext) {
|
|
410
410
|
const { gainLeft, gainRight } = this.panToGain(defaultControllerState.pan.defaultValue);
|
|
@@ -1058,13 +1058,17 @@ class MidyGMLite {
|
|
|
1058
1058
|
this.applyVoiceParams(channel, 14, scheduleTime);
|
|
1059
1059
|
}
|
|
1060
1060
|
setModLfoToPitch(channel, note, scheduleTime) {
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
channel.state.modulationDepth;
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1061
|
+
if (note.modulationDepth) {
|
|
1062
|
+
const modLfoToPitch = note.voiceParams.modLfoToPitch;
|
|
1063
|
+
const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
|
|
1064
|
+
const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
|
|
1065
|
+
note.modulationDepth.gain
|
|
1066
|
+
.cancelScheduledValues(scheduleTime)
|
|
1067
|
+
.setValueAtTime(modulationDepth, scheduleTime);
|
|
1068
|
+
}
|
|
1069
|
+
else {
|
|
1070
|
+
this.startModulation(channel, note, scheduleTime);
|
|
1071
|
+
}
|
|
1068
1072
|
}
|
|
1069
1073
|
setModLfoToFilterFc(note, scheduleTime) {
|
|
1070
1074
|
const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc;
|
|
@@ -1193,7 +1197,6 @@ class MidyGMLite {
|
|
|
1193
1197
|
note.modulationDepth.gain.setValueAtTime(depth, scheduleTime);
|
|
1194
1198
|
}
|
|
1195
1199
|
else {
|
|
1196
|
-
this.setPitchEnvelope(note, scheduleTime);
|
|
1197
1200
|
this.startModulation(channel, note, scheduleTime);
|
|
1198
1201
|
}
|
|
1199
1202
|
});
|