@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/esm/midy-GM2.js
CHANGED
|
@@ -68,13 +68,13 @@ class Note {
|
|
|
68
68
|
writable: true,
|
|
69
69
|
value: void 0
|
|
70
70
|
});
|
|
71
|
-
Object.defineProperty(this, "
|
|
71
|
+
Object.defineProperty(this, "reverbSend", {
|
|
72
72
|
enumerable: true,
|
|
73
73
|
configurable: true,
|
|
74
74
|
writable: true,
|
|
75
75
|
value: void 0
|
|
76
76
|
});
|
|
77
|
-
Object.defineProperty(this, "
|
|
77
|
+
Object.defineProperty(this, "chorusSend", {
|
|
78
78
|
enumerable: true,
|
|
79
79
|
configurable: true,
|
|
80
80
|
writable: true,
|
|
@@ -362,17 +362,17 @@ export class MidyGM2 {
|
|
|
362
362
|
writable: true,
|
|
363
363
|
value: []
|
|
364
364
|
});
|
|
365
|
-
Object.defineProperty(this, "
|
|
365
|
+
Object.defineProperty(this, "notePromises", {
|
|
366
366
|
enumerable: true,
|
|
367
367
|
configurable: true,
|
|
368
368
|
writable: true,
|
|
369
369
|
value: []
|
|
370
370
|
});
|
|
371
|
-
Object.defineProperty(this, "
|
|
371
|
+
Object.defineProperty(this, "instruments", {
|
|
372
372
|
enumerable: true,
|
|
373
373
|
configurable: true,
|
|
374
374
|
writable: true,
|
|
375
|
-
value:
|
|
375
|
+
value: new Set()
|
|
376
376
|
});
|
|
377
377
|
Object.defineProperty(this, "exclusiveClassNotes", {
|
|
378
378
|
enumerable: true,
|
|
@@ -504,7 +504,7 @@ export class MidyGM2 {
|
|
|
504
504
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
505
505
|
const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
|
|
506
506
|
const { instrument, sampleID } = voice.generators;
|
|
507
|
-
return
|
|
507
|
+
return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
|
|
508
508
|
}
|
|
509
509
|
createChannelAudioNodes(audioContext) {
|
|
510
510
|
const { gainLeft, gainRight } = this.panToGain(defaultControllerState.pan.defaultValue);
|
|
@@ -904,13 +904,11 @@ export class MidyGM2 {
|
|
|
904
904
|
return impulse;
|
|
905
905
|
}
|
|
906
906
|
createConvolutionReverb(audioContext, impulse) {
|
|
907
|
-
const input = new GainNode(audioContext);
|
|
908
907
|
const convolverNode = new ConvolverNode(audioContext, {
|
|
909
908
|
buffer: impulse,
|
|
910
909
|
});
|
|
911
|
-
input.connect(convolverNode);
|
|
912
910
|
return {
|
|
913
|
-
input,
|
|
911
|
+
input: convolverNode,
|
|
914
912
|
output: convolverNode,
|
|
915
913
|
convolverNode,
|
|
916
914
|
};
|
|
@@ -1340,12 +1338,8 @@ export class MidyGM2 {
|
|
|
1340
1338
|
}
|
|
1341
1339
|
note.bufferSource.connect(note.filterNode);
|
|
1342
1340
|
note.filterNode.connect(note.volumeEnvelopeNode);
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
}
|
|
1346
|
-
if (0 < state.reverbSendLevel) {
|
|
1347
|
-
this.setReverbEffectsSend(channel, note, 0, now);
|
|
1348
|
-
}
|
|
1341
|
+
this.setChorusSend(channel, note, now);
|
|
1342
|
+
this.setReverbSend(channel, note, now);
|
|
1349
1343
|
note.bufferSource.start(startTime);
|
|
1350
1344
|
return note;
|
|
1351
1345
|
}
|
|
@@ -1411,10 +1405,14 @@ export class MidyGM2 {
|
|
|
1411
1405
|
return;
|
|
1412
1406
|
const note = await this.createNote(channel, voice, noteNumber, velocity, startTime);
|
|
1413
1407
|
if (channel.isDrum) {
|
|
1414
|
-
const
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1408
|
+
const { keyBasedGainLs, keyBasedGainRs } = channel;
|
|
1409
|
+
let gainL = keyBasedGainLs[noteNumber];
|
|
1410
|
+
let gainR = keyBasedGainRs[noteNumber];
|
|
1411
|
+
if (!gainL) {
|
|
1412
|
+
const audioNodes = this.createChannelAudioNodes(this.audioContext);
|
|
1413
|
+
gainL = keyBasedGainLs[noteNumber] = audioNodes.gainL;
|
|
1414
|
+
gainR = keyBasedGainRs[noteNumber] = audioNodes.gainR;
|
|
1415
|
+
}
|
|
1418
1416
|
note.volumeEnvelopeNode.connect(gainL);
|
|
1419
1417
|
note.volumeEnvelopeNode.connect(gainR);
|
|
1420
1418
|
}
|
|
@@ -1448,11 +1446,11 @@ export class MidyGM2 {
|
|
|
1448
1446
|
note.vibratoDepth.disconnect();
|
|
1449
1447
|
note.vibratoLFO.stop();
|
|
1450
1448
|
}
|
|
1451
|
-
if (note.
|
|
1452
|
-
note.
|
|
1449
|
+
if (note.reverbSend) {
|
|
1450
|
+
note.reverbSend.disconnect();
|
|
1453
1451
|
}
|
|
1454
|
-
if (note.
|
|
1455
|
-
note.
|
|
1452
|
+
if (note.chorusSend) {
|
|
1453
|
+
note.chorusSend.disconnect();
|
|
1456
1454
|
}
|
|
1457
1455
|
}
|
|
1458
1456
|
releaseNote(channel, note, endTime) {
|
|
@@ -1603,7 +1601,7 @@ export class MidyGM2 {
|
|
|
1603
1601
|
}
|
|
1604
1602
|
const table = channel.channelPressureTable;
|
|
1605
1603
|
this.processActiveNotes(channel, scheduleTime, (note) => {
|
|
1606
|
-
this.
|
|
1604
|
+
this.setEffects(channel, note, table);
|
|
1607
1605
|
});
|
|
1608
1606
|
this.applyVoiceParams(channel, 13);
|
|
1609
1607
|
}
|
|
@@ -1625,13 +1623,18 @@ export class MidyGM2 {
|
|
|
1625
1623
|
this.applyVoiceParams(channel, 14, scheduleTime);
|
|
1626
1624
|
}
|
|
1627
1625
|
setModLfoToPitch(channel, note, scheduleTime) {
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
.
|
|
1634
|
-
|
|
1626
|
+
if (note.modulationDepth) {
|
|
1627
|
+
const modLfoToPitch = note.voiceParams.modLfoToPitch +
|
|
1628
|
+
this.getLFOPitchDepth(channel, note);
|
|
1629
|
+
const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
|
|
1630
|
+
const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
|
|
1631
|
+
note.modulationDepth.gain
|
|
1632
|
+
.cancelScheduledValues(scheduleTime)
|
|
1633
|
+
.setValueAtTime(modulationDepth, scheduleTime);
|
|
1634
|
+
}
|
|
1635
|
+
else {
|
|
1636
|
+
this.startModulation(channel, note, scheduleTime);
|
|
1637
|
+
}
|
|
1635
1638
|
}
|
|
1636
1639
|
setVibLfoToPitch(channel, note, scheduleTime) {
|
|
1637
1640
|
const vibLfoToPitch = note.voiceParams.vibLfoToPitch;
|
|
@@ -1658,63 +1661,63 @@ export class MidyGM2 {
|
|
|
1658
1661
|
.cancelScheduledValues(scheduleTime)
|
|
1659
1662
|
.setValueAtTime(volumeDepth, scheduleTime);
|
|
1660
1663
|
}
|
|
1661
|
-
|
|
1662
|
-
let value = note.voiceParams.reverbEffectsSend
|
|
1664
|
+
setReverbSend(channel, note, scheduleTime) {
|
|
1665
|
+
let value = note.voiceParams.reverbEffectsSend *
|
|
1666
|
+
channel.state.reverbSendLevel;
|
|
1663
1667
|
if (channel.isDrum) {
|
|
1664
1668
|
const keyBasedValue = this.getKeyBasedValue(channel, note.noteNumber, 91);
|
|
1665
|
-
if (0 <= keyBasedValue)
|
|
1666
|
-
value
|
|
1667
|
-
}
|
|
1669
|
+
if (0 <= keyBasedValue)
|
|
1670
|
+
value = keyBasedValue / 127;
|
|
1668
1671
|
}
|
|
1669
|
-
if (
|
|
1672
|
+
if (!note.reverbSend) {
|
|
1670
1673
|
if (0 < value) {
|
|
1671
|
-
note.
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
}
|
|
1675
|
-
else {
|
|
1676
|
-
note.reverbEffectsSend.disconnect();
|
|
1674
|
+
note.reverbSend = new GainNode(this.audioContext, { gain: value });
|
|
1675
|
+
note.volumeEnvelopeNode.connect(note.reverbSend);
|
|
1676
|
+
note.reverbSend.connect(this.reverbEffect.input);
|
|
1677
1677
|
}
|
|
1678
1678
|
}
|
|
1679
1679
|
else {
|
|
1680
|
+
note.reverbSend.gain
|
|
1681
|
+
.cancelScheduledValues(scheduleTime)
|
|
1682
|
+
.setValueAtTime(value, scheduleTime);
|
|
1680
1683
|
if (0 < value) {
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
note.
|
|
1684
|
+
note.volumeEnvelopeNode.connect(note.reverbSend);
|
|
1685
|
+
}
|
|
1686
|
+
else {
|
|
1687
|
+
try {
|
|
1688
|
+
note.volumeEnvelopeNode.disconnect(note.reverbSend);
|
|
1686
1689
|
}
|
|
1687
|
-
|
|
1690
|
+
catch { /* empty */ }
|
|
1688
1691
|
}
|
|
1689
1692
|
}
|
|
1690
1693
|
}
|
|
1691
|
-
|
|
1692
|
-
let value = note.voiceParams.chorusEffectsSend
|
|
1694
|
+
setChorusSend(channel, note, scheduleTime) {
|
|
1695
|
+
let value = note.voiceParams.chorusEffectsSend *
|
|
1696
|
+
channel.state.chorusSendLevel;
|
|
1693
1697
|
if (channel.isDrum) {
|
|
1694
1698
|
const keyBasedValue = this.getKeyBasedValue(channel, note.noteNumber, 93);
|
|
1695
|
-
if (0 <= keyBasedValue)
|
|
1696
|
-
value
|
|
1697
|
-
}
|
|
1699
|
+
if (0 <= keyBasedValue)
|
|
1700
|
+
value = keyBasedValue / 127;
|
|
1698
1701
|
}
|
|
1699
|
-
if (
|
|
1702
|
+
if (!note.chorusSend) {
|
|
1700
1703
|
if (0 < value) {
|
|
1701
|
-
note.
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
}
|
|
1705
|
-
else {
|
|
1706
|
-
note.chorusEffectsSend.disconnect();
|
|
1704
|
+
note.chorusSend = new GainNode(this.audioContext, { gain: value });
|
|
1705
|
+
note.volumeEnvelopeNode.connect(note.chorusSend);
|
|
1706
|
+
note.chorusSend.connect(this.chorusEffect.input);
|
|
1707
1707
|
}
|
|
1708
1708
|
}
|
|
1709
1709
|
else {
|
|
1710
|
+
note.chorusSend.gain
|
|
1711
|
+
.cancelScheduledValues(scheduleTime)
|
|
1712
|
+
.setValueAtTime(value, scheduleTime);
|
|
1710
1713
|
if (0 < value) {
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
note.volumeEnvelopeNode.
|
|
1714
|
+
note.volumeEnvelopeNode.connect(note.chorusSend);
|
|
1715
|
+
}
|
|
1716
|
+
else {
|
|
1717
|
+
try {
|
|
1718
|
+
note.volumeEnvelopeNode.disconnect(note.chorusSend);
|
|
1716
1719
|
}
|
|
1717
|
-
|
|
1720
|
+
catch { /* empty */ }
|
|
1718
1721
|
}
|
|
1719
1722
|
}
|
|
1720
1723
|
}
|
|
@@ -1863,7 +1866,7 @@ export class MidyGM2 {
|
|
|
1863
1866
|
handler.call(this, channelNumber, value, scheduleTime);
|
|
1864
1867
|
const channel = this.channels[channelNumber];
|
|
1865
1868
|
this.applyVoiceParams(channel, controllerType + 128, scheduleTime);
|
|
1866
|
-
this.
|
|
1869
|
+
this.setControlChangeEffects(channel, controllerType, scheduleTime);
|
|
1867
1870
|
}
|
|
1868
1871
|
else {
|
|
1869
1872
|
console.warn(`Unsupported Control change: controllerType=${controllerType} value=${value}`);
|
|
@@ -1879,7 +1882,6 @@ export class MidyGM2 {
|
|
|
1879
1882
|
note.modulationDepth.gain.setValueAtTime(depth, scheduleTime);
|
|
1880
1883
|
}
|
|
1881
1884
|
else {
|
|
1882
|
-
this.setPitchEnvelope(note, scheduleTime);
|
|
1883
1885
|
this.startModulation(channel, note, scheduleTime);
|
|
1884
1886
|
}
|
|
1885
1887
|
});
|
|
@@ -1924,8 +1926,14 @@ export class MidyGM2 {
|
|
|
1924
1926
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1925
1927
|
const channel = this.channels[channelNumber];
|
|
1926
1928
|
channel.state.volume = volume / 127;
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
+
if (channel.isDrum) {
|
|
1930
|
+
for (let i = 0; i < 128; i++) {
|
|
1931
|
+
this.updateKeyBasedVolume(channel, i, scheduleTime);
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
else {
|
|
1935
|
+
this.updateChannelVolume(channel, scheduleTime);
|
|
1936
|
+
}
|
|
1929
1937
|
}
|
|
1930
1938
|
panToGain(pan) {
|
|
1931
1939
|
const theta = Math.PI / 2 * Math.max(0, pan * 127 - 1) / 126;
|
|
@@ -1938,8 +1946,14 @@ export class MidyGM2 {
|
|
|
1938
1946
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1939
1947
|
const channel = this.channels[channelNumber];
|
|
1940
1948
|
channel.state.pan = pan / 127;
|
|
1941
|
-
|
|
1942
|
-
|
|
1949
|
+
if (channel.isDrum) {
|
|
1950
|
+
for (let i = 0; i < 128; i++) {
|
|
1951
|
+
this.updateKeyBasedVolume(channel, i, scheduleTime);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
else {
|
|
1955
|
+
this.updateChannelVolume(channel, scheduleTime);
|
|
1956
|
+
}
|
|
1943
1957
|
}
|
|
1944
1958
|
setExpression(channelNumber, expression, scheduleTime) {
|
|
1945
1959
|
scheduleTime ??= this.audioContext.currentTime;
|
|
@@ -1965,33 +1979,27 @@ export class MidyGM2 {
|
|
|
1965
1979
|
.cancelScheduledValues(scheduleTime)
|
|
1966
1980
|
.setValueAtTime(volume * gainRight, scheduleTime);
|
|
1967
1981
|
}
|
|
1968
|
-
updateKeyBasedVolume(channel, scheduleTime) {
|
|
1969
|
-
if (!channel.isDrum)
|
|
1970
|
-
return;
|
|
1982
|
+
updateKeyBasedVolume(channel, keyNumber, scheduleTime) {
|
|
1971
1983
|
const state = channel.state;
|
|
1972
1984
|
const defaultVolume = state.volume * state.expression;
|
|
1973
1985
|
const defaultPan = state.pan;
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
gainR.gain
|
|
1992
|
-
.cancelScheduledValues(scheduleTime)
|
|
1993
|
-
.setValueAtTime(volume * gainRight, scheduleTime);
|
|
1994
|
-
}
|
|
1986
|
+
const gainL = channel.keyBasedGainLs[keyNumber];
|
|
1987
|
+
const gainR = channel.keyBasedGainRs[keyNumber];
|
|
1988
|
+
if (!gainL)
|
|
1989
|
+
return;
|
|
1990
|
+
const keyBasedVolume = this.getKeyBasedValue(channel, keyNumber, 7);
|
|
1991
|
+
const volume = (0 <= keyBasedVolume)
|
|
1992
|
+
? defaultVolume * keyBasedVolume / 64
|
|
1993
|
+
: defaultVolume;
|
|
1994
|
+
const keyBasedPan = this.getKeyBasedValue(channel, keyNumber, 10);
|
|
1995
|
+
const pan = (0 <= keyBasedPan) ? keyBasedPan / 127 : defaultPan;
|
|
1996
|
+
const { gainLeft, gainRight } = this.panToGain(pan);
|
|
1997
|
+
gainL.gain
|
|
1998
|
+
.cancelScheduledValues(scheduleTime)
|
|
1999
|
+
.setValueAtTime(volume * gainLeft, scheduleTime);
|
|
2000
|
+
gainR.gain
|
|
2001
|
+
.cancelScheduledValues(scheduleTime)
|
|
2002
|
+
.setValueAtTime(volume * gainRight, scheduleTime);
|
|
1995
2003
|
}
|
|
1996
2004
|
setSustainPedal(channelNumber, value, scheduleTime) {
|
|
1997
2005
|
const channel = this.channels[channelNumber];
|
|
@@ -2058,67 +2066,19 @@ export class MidyGM2 {
|
|
|
2058
2066
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2059
2067
|
const channel = this.channels[channelNumber];
|
|
2060
2068
|
const state = channel.state;
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
reverbEffect.input.gain
|
|
2066
|
-
.cancelScheduledValues(scheduleTime)
|
|
2067
|
-
.setValueAtTime(state.reverbSendLevel, scheduleTime);
|
|
2068
|
-
}
|
|
2069
|
-
else {
|
|
2070
|
-
this.processScheduledNotes(channel, (note) => {
|
|
2071
|
-
if (note.voiceParams.reverbEffectsSend <= 0)
|
|
2072
|
-
return false;
|
|
2073
|
-
if (note.reverbEffectsSend)
|
|
2074
|
-
note.reverbEffectsSend.disconnect();
|
|
2075
|
-
});
|
|
2076
|
-
}
|
|
2077
|
-
}
|
|
2078
|
-
else {
|
|
2079
|
-
if (0 < reverbSendLevel) {
|
|
2080
|
-
this.processScheduledNotes(channel, (note) => {
|
|
2081
|
-
this.setReverbEffectsSend(channel, note, 0, scheduleTime);
|
|
2082
|
-
});
|
|
2083
|
-
state.reverbSendLevel = reverbSendLevel / 127;
|
|
2084
|
-
reverbEffect.input.gain
|
|
2085
|
-
.cancelScheduledValues(scheduleTime)
|
|
2086
|
-
.setValueAtTime(state.reverbSendLevel, scheduleTime);
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2069
|
+
state.reverbSendLevel = reverbSendLevel / 127;
|
|
2070
|
+
this.processScheduledNotes(channel, (note) => {
|
|
2071
|
+
this.setReverbSend(channel, note, scheduleTime);
|
|
2072
|
+
});
|
|
2089
2073
|
}
|
|
2090
2074
|
setChorusSendLevel(channelNumber, chorusSendLevel, scheduleTime) {
|
|
2091
2075
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2092
2076
|
const channel = this.channels[channelNumber];
|
|
2093
2077
|
const state = channel.state;
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
chorusEffect.input.gain
|
|
2099
|
-
.cancelScheduledValues(scheduleTime)
|
|
2100
|
-
.setValueAtTime(state.chorusSendLevel, scheduleTime);
|
|
2101
|
-
}
|
|
2102
|
-
else {
|
|
2103
|
-
this.processScheduledNotes(channel, (note) => {
|
|
2104
|
-
if (note.voiceParams.chorusEffectsSend <= 0)
|
|
2105
|
-
return false;
|
|
2106
|
-
if (note.chorusEffectsSend)
|
|
2107
|
-
note.chorusEffectsSend.disconnect();
|
|
2108
|
-
});
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
else {
|
|
2112
|
-
if (0 < chorusSendLevel) {
|
|
2113
|
-
this.processScheduledNotes(channel, (note) => {
|
|
2114
|
-
this.setChorusEffectsSend(channel, note, 0, scheduleTime);
|
|
2115
|
-
});
|
|
2116
|
-
state.chorusSendLevel = chorusSendLevel / 127;
|
|
2117
|
-
chorusEffect.input.gain
|
|
2118
|
-
.cancelScheduledValues(scheduleTime)
|
|
2119
|
-
.setValueAtTime(state.chorusSendLevel, scheduleTime);
|
|
2120
|
-
}
|
|
2121
|
-
}
|
|
2078
|
+
state.chorusSendLevel = chorusSendLevel / 127;
|
|
2079
|
+
this.processScheduledNotes(channel, (note) => {
|
|
2080
|
+
this.setChorusSend(channel, note, scheduleTime);
|
|
2081
|
+
});
|
|
2122
2082
|
}
|
|
2123
2083
|
limitData(channel, minMSB, maxMSB, minLSB, maxLSB) {
|
|
2124
2084
|
if (maxLSB < channel.dataLSB) {
|
|
@@ -2400,9 +2360,9 @@ export class MidyGM2 {
|
|
|
2400
2360
|
case 9:
|
|
2401
2361
|
switch (data[3]) {
|
|
2402
2362
|
case 1: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
|
|
2403
|
-
return this.handlePressureSysEx(data, "channelPressureTable");
|
|
2363
|
+
return this.handlePressureSysEx(data, "channelPressureTable", scheduleTime);
|
|
2404
2364
|
case 3: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
|
|
2405
|
-
return this.handleControlChangeSysEx(data);
|
|
2365
|
+
return this.handleControlChangeSysEx(data, scheduleTime);
|
|
2406
2366
|
default:
|
|
2407
2367
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
2408
2368
|
}
|
|
@@ -2721,9 +2681,9 @@ export class MidyGM2 {
|
|
|
2721
2681
|
: 0;
|
|
2722
2682
|
return channelPressure / 127;
|
|
2723
2683
|
}
|
|
2724
|
-
|
|
2684
|
+
setEffects(channel, note, table, scheduleTime) {
|
|
2725
2685
|
if (0 <= table[0])
|
|
2726
|
-
this.updateDetune(channel, note,
|
|
2686
|
+
this.updateDetune(channel, note, scheduleTime);
|
|
2727
2687
|
if (0.5 <= channel.state.portamemento && 0 <= note.portamentoNoteNumber) {
|
|
2728
2688
|
if (0 <= table[1]) {
|
|
2729
2689
|
this.setPortamentoFilterEnvelope(channel, note, scheduleTime);
|
|
@@ -2745,7 +2705,7 @@ export class MidyGM2 {
|
|
|
2745
2705
|
if (0 <= table[5])
|
|
2746
2706
|
this.setModLfoToVolume(channel, note, scheduleTime);
|
|
2747
2707
|
}
|
|
2748
|
-
handlePressureSysEx(data, tableName) {
|
|
2708
|
+
handlePressureSysEx(data, tableName, scheduleTime) {
|
|
2749
2709
|
const channelNumber = data[4];
|
|
2750
2710
|
const channel = this.channels[channelNumber];
|
|
2751
2711
|
if (channel.isDrum)
|
|
@@ -2756,32 +2716,38 @@ export class MidyGM2 {
|
|
|
2756
2716
|
const rr = data[i + 1];
|
|
2757
2717
|
table[pp] = rr;
|
|
2758
2718
|
}
|
|
2719
|
+
this.processActiveNotes(channel, scheduleTime, (note) => {
|
|
2720
|
+
this.setEffects(channel, note, table, scheduleTime);
|
|
2721
|
+
});
|
|
2759
2722
|
}
|
|
2760
2723
|
initControlTable() {
|
|
2761
2724
|
const ccCount = 128;
|
|
2762
2725
|
const slotSize = 6;
|
|
2763
2726
|
return new Int8Array(ccCount * slotSize).fill(-1);
|
|
2764
2727
|
}
|
|
2765
|
-
|
|
2728
|
+
setControlChangeEffects(channel, controllerType, scheduleTime) {
|
|
2766
2729
|
const slotSize = 6;
|
|
2767
2730
|
const offset = controllerType * slotSize;
|
|
2768
2731
|
const table = channel.controlTable.subarray(offset, offset + slotSize);
|
|
2769
2732
|
this.processScheduledNotes(channel, (note) => {
|
|
2770
|
-
this.
|
|
2733
|
+
this.setEffects(channel, note, table, scheduleTime);
|
|
2771
2734
|
});
|
|
2772
2735
|
}
|
|
2773
|
-
handleControlChangeSysEx(data) {
|
|
2736
|
+
handleControlChangeSysEx(data, scheduleTime) {
|
|
2774
2737
|
const channelNumber = data[4];
|
|
2775
2738
|
const channel = this.channels[channelNumber];
|
|
2776
2739
|
if (channel.isDrum)
|
|
2777
2740
|
return;
|
|
2741
|
+
const slotSize = 6;
|
|
2778
2742
|
const controllerType = data[5];
|
|
2779
|
-
const
|
|
2780
|
-
|
|
2743
|
+
const offset = controllerType * slotSize;
|
|
2744
|
+
const table = channel.controlTable;
|
|
2745
|
+
for (let i = 6; i < data.length; i += 2) {
|
|
2781
2746
|
const pp = data[i];
|
|
2782
2747
|
const rr = data[i + 1];
|
|
2783
|
-
table[pp] = rr;
|
|
2748
|
+
table[offset + pp] = rr;
|
|
2784
2749
|
}
|
|
2750
|
+
this.setControlChangeEffects(channel, controllerType, scheduleTime);
|
|
2785
2751
|
}
|
|
2786
2752
|
getKeyBasedValue(channel, keyNumber, controllerType) {
|
|
2787
2753
|
const index = keyNumber * 128 + controllerType;
|
|
@@ -2795,13 +2761,20 @@ export class MidyGM2 {
|
|
|
2795
2761
|
return;
|
|
2796
2762
|
const keyNumber = data[5];
|
|
2797
2763
|
const table = channel.keyBasedInstrumentControlTable;
|
|
2798
|
-
for (let i = 6; i < data.length
|
|
2764
|
+
for (let i = 6; i < data.length; i += 2) {
|
|
2799
2765
|
const controllerType = data[i];
|
|
2800
2766
|
const value = data[i + 1];
|
|
2801
2767
|
const index = keyNumber * 128 + controllerType;
|
|
2802
2768
|
table[index] = value;
|
|
2769
|
+
switch (controllerType) {
|
|
2770
|
+
case 7:
|
|
2771
|
+
case 10:
|
|
2772
|
+
this.updateKeyBasedVolume(channel, keyNumber, scheduleTime);
|
|
2773
|
+
break;
|
|
2774
|
+
default: // TODO
|
|
2775
|
+
this.setControlChange(channelNumber, controllerType, value, scheduleTime);
|
|
2776
|
+
}
|
|
2803
2777
|
}
|
|
2804
|
-
this.setChannelPressure(channelNumber, channel.state.channelPressure * 127, scheduleTime);
|
|
2805
2778
|
}
|
|
2806
2779
|
handleSysEx(data, scheduleTime) {
|
|
2807
2780
|
switch (data[0]) {
|
package/esm/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;
|
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":"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/esm/midy-GMLite.js
CHANGED
|
@@ -263,17 +263,17 @@ export class MidyGMLite {
|
|
|
263
263
|
writable: true,
|
|
264
264
|
value: []
|
|
265
265
|
});
|
|
266
|
-
Object.defineProperty(this, "
|
|
266
|
+
Object.defineProperty(this, "notePromises", {
|
|
267
267
|
enumerable: true,
|
|
268
268
|
configurable: true,
|
|
269
269
|
writable: true,
|
|
270
270
|
value: []
|
|
271
271
|
});
|
|
272
|
-
Object.defineProperty(this, "
|
|
272
|
+
Object.defineProperty(this, "instruments", {
|
|
273
273
|
enumerable: true,
|
|
274
274
|
configurable: true,
|
|
275
275
|
writable: true,
|
|
276
|
-
value:
|
|
276
|
+
value: new Set()
|
|
277
277
|
});
|
|
278
278
|
Object.defineProperty(this, "exclusiveClassNotes", {
|
|
279
279
|
enumerable: true,
|
|
@@ -401,7 +401,7 @@ export class MidyGMLite {
|
|
|
401
401
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
402
402
|
const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
|
|
403
403
|
const { instrument, sampleID } = voice.generators;
|
|
404
|
-
return
|
|
404
|
+
return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
|
|
405
405
|
}
|
|
406
406
|
createChannelAudioNodes(audioContext) {
|
|
407
407
|
const { gainLeft, gainRight } = this.panToGain(defaultControllerState.pan.defaultValue);
|
|
@@ -1055,13 +1055,17 @@ export class MidyGMLite {
|
|
|
1055
1055
|
this.applyVoiceParams(channel, 14, scheduleTime);
|
|
1056
1056
|
}
|
|
1057
1057
|
setModLfoToPitch(channel, note, scheduleTime) {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
channel.state.modulationDepth;
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1058
|
+
if (note.modulationDepth) {
|
|
1059
|
+
const modLfoToPitch = note.voiceParams.modLfoToPitch;
|
|
1060
|
+
const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
|
|
1061
|
+
const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
|
|
1062
|
+
note.modulationDepth.gain
|
|
1063
|
+
.cancelScheduledValues(scheduleTime)
|
|
1064
|
+
.setValueAtTime(modulationDepth, scheduleTime);
|
|
1065
|
+
}
|
|
1066
|
+
else {
|
|
1067
|
+
this.startModulation(channel, note, scheduleTime);
|
|
1068
|
+
}
|
|
1065
1069
|
}
|
|
1066
1070
|
setModLfoToFilterFc(note, scheduleTime) {
|
|
1067
1071
|
const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc;
|
|
@@ -1190,7 +1194,6 @@ export class MidyGMLite {
|
|
|
1190
1194
|
note.modulationDepth.gain.setValueAtTime(depth, scheduleTime);
|
|
1191
1195
|
}
|
|
1192
1196
|
else {
|
|
1193
|
-
this.setPitchEnvelope(note, scheduleTime);
|
|
1194
1197
|
this.startModulation(channel, note, scheduleTime);
|
|
1195
1198
|
}
|
|
1196
1199
|
});
|