@marmooo/midy 0.1.3 → 0.1.5
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/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.4 → soundfont-parser@0.0.6}/+esm.d.ts +16 -20
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.d.ts.map +1 -0
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.js +180 -0
- package/esm/midy-GM1.d.ts +32 -3
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +93 -87
- package/esm/midy-GM2.d.ts +56 -3
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +142 -126
- package/esm/midy-GMLite.d.ts +32 -3
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +91 -85
- package/esm/midy.d.ts +87 -4
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +234 -140
- package/package.json +1 -1
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.4 → soundfont-parser@0.0.6}/+esm.d.ts +16 -20
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.d.ts.map +1 -0
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.js +190 -0
- package/script/midy-GM1.d.ts +32 -3
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +93 -87
- package/script/midy-GM2.d.ts +56 -3
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +142 -126
- package/script/midy-GMLite.d.ts +32 -3
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +91 -85
- package/script/midy.d.ts +87 -4
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +234 -140
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts.map +0 -1
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.js +0 -162
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts.map +0 -1
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.js +0 -169
package/script/midy-GM2.d.ts
CHANGED
|
@@ -92,6 +92,32 @@ export class MidyGM2 {
|
|
|
92
92
|
};
|
|
93
93
|
};
|
|
94
94
|
masterGain: any;
|
|
95
|
+
controlChangeHandlers: {
|
|
96
|
+
0: (channelNumber: any, msb: any) => void;
|
|
97
|
+
1: (channelNumber: any, modulation: any) => void;
|
|
98
|
+
5: (channelNumber: any, portamentoTime: any) => void;
|
|
99
|
+
6: (channelNumber: any, value: any) => void;
|
|
100
|
+
7: (channelNumber: any, volume: any) => void;
|
|
101
|
+
10: (channelNumber: any, pan: any) => void;
|
|
102
|
+
11: (channelNumber: any, expression: any) => void;
|
|
103
|
+
32: (channelNumber: any, lsb: any) => void;
|
|
104
|
+
38: (channelNumber: any, value: any) => void;
|
|
105
|
+
64: (channelNumber: any, value: any) => void;
|
|
106
|
+
65: (channelNumber: any, value: any) => void;
|
|
107
|
+
66: (channelNumber: any, value: any) => void;
|
|
108
|
+
67: (channelNumber: any, softPedal: any) => void;
|
|
109
|
+
91: (channelNumber: any, reverbSendLevel: any) => void;
|
|
110
|
+
93: (channelNumber: any, chorusSendLevel: any) => void;
|
|
111
|
+
100: (channelNumber: any, value: any) => void;
|
|
112
|
+
101: (channelNumber: any, value: any) => void;
|
|
113
|
+
120: (channelNumber: any) => Promise<void>;
|
|
114
|
+
121: (channelNumber: any) => void;
|
|
115
|
+
123: (channelNumber: any) => Promise<void>;
|
|
116
|
+
124: () => void;
|
|
117
|
+
125: () => void;
|
|
118
|
+
126: () => void;
|
|
119
|
+
127: () => void;
|
|
120
|
+
};
|
|
95
121
|
channels: any[];
|
|
96
122
|
reverbEffect: {
|
|
97
123
|
input: any;
|
|
@@ -167,14 +193,15 @@ export class MidyGM2 {
|
|
|
167
193
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
168
194
|
setVolumeEnvelope(note: any): void;
|
|
169
195
|
setPitch(note: any, semitoneOffset: any): void;
|
|
170
|
-
|
|
196
|
+
clampCutoffFrequency(frequency: any): number;
|
|
197
|
+
setFilterEnvelope(channel: any, note: any): void;
|
|
171
198
|
startModulation(channel: any, note: any, startTime: any): void;
|
|
172
199
|
startVibrato(channel: any, note: any, startTime: any): void;
|
|
173
200
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
174
201
|
calcBank(channel: any, channelNumber: any): any;
|
|
175
202
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
176
203
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
177
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any,
|
|
204
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
|
|
178
205
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
179
206
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
180
207
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
|
|
@@ -183,7 +210,33 @@ export class MidyGM2 {
|
|
|
183
210
|
handleChannelPressure(channelNumber: any, pressure: any): void;
|
|
184
211
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
185
212
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
186
|
-
|
|
213
|
+
createControlChangeHandlers(): {
|
|
214
|
+
0: (channelNumber: any, msb: any) => void;
|
|
215
|
+
1: (channelNumber: any, modulation: any) => void;
|
|
216
|
+
5: (channelNumber: any, portamentoTime: any) => void;
|
|
217
|
+
6: (channelNumber: any, value: any) => void;
|
|
218
|
+
7: (channelNumber: any, volume: any) => void;
|
|
219
|
+
10: (channelNumber: any, pan: any) => void;
|
|
220
|
+
11: (channelNumber: any, expression: any) => void;
|
|
221
|
+
32: (channelNumber: any, lsb: any) => void;
|
|
222
|
+
38: (channelNumber: any, value: any) => void;
|
|
223
|
+
64: (channelNumber: any, value: any) => void;
|
|
224
|
+
65: (channelNumber: any, value: any) => void;
|
|
225
|
+
66: (channelNumber: any, value: any) => void;
|
|
226
|
+
67: (channelNumber: any, softPedal: any) => void;
|
|
227
|
+
91: (channelNumber: any, reverbSendLevel: any) => void;
|
|
228
|
+
93: (channelNumber: any, chorusSendLevel: any) => void;
|
|
229
|
+
100: (channelNumber: any, value: any) => void;
|
|
230
|
+
101: (channelNumber: any, value: any) => void;
|
|
231
|
+
120: (channelNumber: any) => Promise<void>;
|
|
232
|
+
121: (channelNumber: any) => void;
|
|
233
|
+
123: (channelNumber: any) => Promise<void>;
|
|
234
|
+
124: () => void;
|
|
235
|
+
125: () => void;
|
|
236
|
+
126: () => void;
|
|
237
|
+
127: () => void;
|
|
238
|
+
};
|
|
239
|
+
handleControlChange(channelNumber: any, controller: any, value: any): void;
|
|
187
240
|
setBankMSB(channelNumber: any, msb: any): void;
|
|
188
241
|
updateModulation(channel: any): void;
|
|
189
242
|
setModulationDepth(channelNumber: any, modulation: any): void;
|
package/script/midy-GM2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAwBA;IAkCE;;;;;;;;;;;;;;;;;;;;MAoBE;IAEF;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAgCF;;;;;
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}
|
package/script/midy-GM2.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MidyGM2 = void 0;
|
|
4
4
|
const _esm_js_1 = require("./deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.js");
|
|
5
|
-
const _esm_js_2 = require("./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.
|
|
5
|
+
const _esm_js_2 = require("./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.js");
|
|
6
6
|
class Note {
|
|
7
7
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
8
8
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -233,6 +233,7 @@ class MidyGM2 {
|
|
|
233
233
|
this.audioContext = audioContext;
|
|
234
234
|
this.options = { ...this.defaultOptions, ...options };
|
|
235
235
|
this.masterGain = new GainNode(audioContext);
|
|
236
|
+
this.controlChangeHandlers = this.createControlChangeHandlers();
|
|
236
237
|
this.channels = this.createChannels(audioContext);
|
|
237
238
|
this.reverbEffect = this.options.reverbAlgorithm(audioContext);
|
|
238
239
|
this.chorusEffect = this.createChorusEffect(audioContext);
|
|
@@ -548,12 +549,13 @@ class MidyGM2 {
|
|
|
548
549
|
const now = this.audioContext.currentTime;
|
|
549
550
|
const channel = this.channels[channelNumber];
|
|
550
551
|
channel.scheduledNotes.forEach((noteList) => {
|
|
551
|
-
noteList.
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
552
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
553
|
+
const note = noteList[i];
|
|
554
|
+
if (!note)
|
|
555
|
+
continue;
|
|
556
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
|
|
557
|
+
this.notePromises.push(promise);
|
|
558
|
+
}
|
|
557
559
|
});
|
|
558
560
|
channel.scheduledNotes.clear();
|
|
559
561
|
await Promise.all(this.notePromises);
|
|
@@ -776,7 +778,6 @@ class MidyGM2 {
|
|
|
776
778
|
}
|
|
777
779
|
setVolumeEnvelope(note) {
|
|
778
780
|
const { instrumentKey, startTime } = note;
|
|
779
|
-
note.volumeNode = new GainNode(this.audioContext, { gain: 0 });
|
|
780
781
|
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
781
782
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
782
783
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
@@ -784,6 +785,8 @@ class MidyGM2 {
|
|
|
784
785
|
const volHold = volAttack + instrumentKey.volHold;
|
|
785
786
|
const volDecay = volHold + instrumentKey.volDecay;
|
|
786
787
|
note.volumeNode.gain
|
|
788
|
+
.cancelScheduledValues(startTime)
|
|
789
|
+
.setValueAtTime(0, startTime)
|
|
787
790
|
.setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
|
|
788
791
|
.exponentialRampToValueAtTime(attackVolume, volAttack)
|
|
789
792
|
.setValueAtTime(attackVolume, volHold)
|
|
@@ -807,29 +810,30 @@ class MidyGM2 {
|
|
|
807
810
|
.setValueAtTime(peekPitch, modHold)
|
|
808
811
|
.linearRampToValueAtTime(basePitch, modDecay);
|
|
809
812
|
}
|
|
810
|
-
|
|
813
|
+
clampCutoffFrequency(frequency) {
|
|
814
|
+
const minFrequency = 20; // min Hz of initialFilterFc
|
|
815
|
+
const maxFrequency = 20000; // max Hz of initialFilterFc
|
|
816
|
+
return Math.max(minFrequency, Math.min(frequency, maxFrequency));
|
|
817
|
+
}
|
|
818
|
+
setFilterEnvelope(channel, note) {
|
|
811
819
|
const { instrumentKey, noteNumber, startTime } = note;
|
|
812
820
|
const softPedalFactor = 1 -
|
|
813
821
|
(0.1 + (noteNumber / 127) * 0.2) * channel.softPedal;
|
|
814
|
-
const maxFreq = this.audioContext.sampleRate / 2;
|
|
815
822
|
const baseFreq = this.centToHz(instrumentKey.initialFilterFc) *
|
|
816
823
|
softPedalFactor;
|
|
817
824
|
const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc) * softPedalFactor;
|
|
818
825
|
const sustainFreq = baseFreq +
|
|
819
826
|
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
|
|
820
|
-
const adjustedBaseFreq =
|
|
821
|
-
const adjustedPeekFreq =
|
|
822
|
-
const adjustedSustainFreq =
|
|
827
|
+
const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
|
|
828
|
+
const adjustedPeekFreq = this.clampCutoffFrequency(peekFreq);
|
|
829
|
+
const adjustedSustainFreq = this.clampCutoffFrequency(sustainFreq);
|
|
823
830
|
const modDelay = startTime + instrumentKey.modDelay;
|
|
824
831
|
const modAttack = modDelay + instrumentKey.modAttack;
|
|
825
832
|
const modHold = modAttack + instrumentKey.modHold;
|
|
826
833
|
const modDecay = modHold + instrumentKey.modDecay;
|
|
827
|
-
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
828
|
-
type: "lowpass",
|
|
829
|
-
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
830
|
-
frequency: adjustedBaseFreq,
|
|
831
|
-
});
|
|
832
834
|
note.filterNode.frequency
|
|
835
|
+
.cancelScheduledValues(startTime)
|
|
836
|
+
.setValueAtTime(adjustedBaseFreq, startTime)
|
|
833
837
|
.setValueAtTime(adjustedBaseFreq, modDelay)
|
|
834
838
|
.exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
|
|
835
839
|
.setValueAtTime(adjustedPeekFreq, modHold)
|
|
@@ -882,8 +886,13 @@ class MidyGM2 {
|
|
|
882
886
|
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
883
887
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
884
888
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
885
|
-
this.
|
|
889
|
+
note.volumeNode = new GainNode(this.audioContext);
|
|
890
|
+
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
891
|
+
type: "lowpass",
|
|
892
|
+
Q: instrumentKey.initialFilterQ / 10 * channel.filterResonance, // dB
|
|
893
|
+
});
|
|
886
894
|
this.setVolumeEnvelope(note);
|
|
895
|
+
this.setFilterEnvelope(channel, note);
|
|
887
896
|
if (0 < channel.vibratoDepth) {
|
|
888
897
|
this.startVibrato(channel, note, startTime);
|
|
889
898
|
}
|
|
@@ -920,7 +929,7 @@ class MidyGM2 {
|
|
|
920
929
|
return;
|
|
921
930
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
922
931
|
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
923
|
-
const instrumentKey = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber);
|
|
932
|
+
const instrumentKey = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber, velocity);
|
|
924
933
|
if (!instrumentKey)
|
|
925
934
|
return;
|
|
926
935
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
@@ -941,12 +950,14 @@ class MidyGM2 {
|
|
|
941
950
|
const now = this.audioContext.currentTime;
|
|
942
951
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
943
952
|
}
|
|
944
|
-
scheduleNoteRelease(channelNumber, noteNumber,
|
|
953
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, stopPedal = false) {
|
|
945
954
|
const channel = this.channels[channelNumber];
|
|
946
|
-
if (stopPedal
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
955
|
+
if (stopPedal) {
|
|
956
|
+
if (channel.sustainPedal)
|
|
957
|
+
return;
|
|
958
|
+
if (channel.sostenutoNotes.has(noteNumber))
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
950
961
|
if (!channel.scheduledNotes.has(noteNumber))
|
|
951
962
|
return;
|
|
952
963
|
const scheduledNotes = channel.scheduledNotes.get(noteNumber);
|
|
@@ -956,14 +967,11 @@ class MidyGM2 {
|
|
|
956
967
|
continue;
|
|
957
968
|
if (note.ending)
|
|
958
969
|
continue;
|
|
959
|
-
const
|
|
960
|
-
const volEndTime = stopTime +
|
|
961
|
-
note.instrumentKey.volRelease * velocityRate;
|
|
970
|
+
const volEndTime = stopTime + note.instrumentKey.volRelease;
|
|
962
971
|
note.volumeNode.gain
|
|
963
972
|
.cancelScheduledValues(stopTime)
|
|
964
973
|
.linearRampToValueAtTime(0, volEndTime);
|
|
965
|
-
const modRelease = stopTime +
|
|
966
|
-
note.instrumentKey.modRelease * velocityRate;
|
|
974
|
+
const modRelease = stopTime + note.instrumentKey.modRelease;
|
|
967
975
|
note.filterNode.frequency
|
|
968
976
|
.cancelScheduledValues(stopTime)
|
|
969
977
|
.linearRampToValueAtTime(0, modRelease);
|
|
@@ -977,16 +985,11 @@ class MidyGM2 {
|
|
|
977
985
|
note.bufferSource.disconnect();
|
|
978
986
|
note.volumeNode.disconnect();
|
|
979
987
|
note.filterNode.disconnect();
|
|
980
|
-
if (note.
|
|
988
|
+
if (note.modulationDepth) {
|
|
981
989
|
note.volumeDepth.disconnect();
|
|
982
|
-
if (note.modulationDepth)
|
|
983
990
|
note.modulationDepth.disconnect();
|
|
984
|
-
if (note.modulationLFO)
|
|
985
991
|
note.modulationLFO.stop();
|
|
986
|
-
|
|
987
|
-
note.vibratoDepth.disconnect();
|
|
988
|
-
if (note.vibratoLFO)
|
|
989
|
-
note.vibratoLFO.stop();
|
|
992
|
+
}
|
|
990
993
|
resolve();
|
|
991
994
|
};
|
|
992
995
|
note.bufferSource.stop(volEndTime);
|
|
@@ -1003,13 +1006,14 @@ class MidyGM2 {
|
|
|
1003
1006
|
const promises = [];
|
|
1004
1007
|
channel.sustainPedal = false;
|
|
1005
1008
|
channel.scheduledNotes.forEach((noteList) => {
|
|
1006
|
-
noteList.
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1009
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1010
|
+
const note = noteList[i];
|
|
1011
|
+
if (!note)
|
|
1012
|
+
continue;
|
|
1013
|
+
const { noteNumber } = note;
|
|
1014
|
+
const promise = this.releaseNote(channelNumber, noteNumber, velocity);
|
|
1015
|
+
promises.push(promise);
|
|
1016
|
+
}
|
|
1013
1017
|
});
|
|
1014
1018
|
return promises;
|
|
1015
1019
|
}
|
|
@@ -1078,58 +1082,41 @@ class MidyGM2 {
|
|
|
1078
1082
|
channel.pitchBendRange * 100;
|
|
1079
1083
|
this.updateDetune(channel, detuneChange);
|
|
1080
1084
|
}
|
|
1085
|
+
createControlChangeHandlers() {
|
|
1086
|
+
return {
|
|
1087
|
+
0: this.setBankMSB,
|
|
1088
|
+
1: this.setModulationDepth,
|
|
1089
|
+
5: this.setPortamentoTime,
|
|
1090
|
+
6: this.dataEntryMSB,
|
|
1091
|
+
7: this.setVolume,
|
|
1092
|
+
10: this.setPan,
|
|
1093
|
+
11: this.setExpression,
|
|
1094
|
+
32: this.setBankLSB,
|
|
1095
|
+
38: this.dataEntryLSB,
|
|
1096
|
+
64: this.setSustainPedal,
|
|
1097
|
+
65: this.setPortamento,
|
|
1098
|
+
66: this.setSostenutoPedal,
|
|
1099
|
+
67: this.setSoftPedal,
|
|
1100
|
+
91: this.setReverbSendLevel,
|
|
1101
|
+
93: this.setChorusSendLevel,
|
|
1102
|
+
100: this.setRPNLSB,
|
|
1103
|
+
101: this.setRPNMSB,
|
|
1104
|
+
120: this.allSoundOff,
|
|
1105
|
+
121: this.resetAllControllers,
|
|
1106
|
+
123: this.allNotesOff,
|
|
1107
|
+
124: this.omniOff,
|
|
1108
|
+
125: this.omniOn,
|
|
1109
|
+
126: this.monoOn,
|
|
1110
|
+
127: this.polyOn,
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1081
1113
|
handleControlChange(channelNumber, controller, value) {
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
return this.setPortamentoTime(channelNumber, value);
|
|
1089
|
-
case 6:
|
|
1090
|
-
return this.dataEntryMSB(channelNumber, value);
|
|
1091
|
-
case 7:
|
|
1092
|
-
return this.setVolume(channelNumber, value);
|
|
1093
|
-
case 10:
|
|
1094
|
-
return this.setPan(channelNumber, value);
|
|
1095
|
-
case 11:
|
|
1096
|
-
return this.setExpression(channelNumber, value);
|
|
1097
|
-
case 32:
|
|
1098
|
-
return this.setBankLSB(channelNumber, value);
|
|
1099
|
-
case 38:
|
|
1100
|
-
return this.dataEntryLSB(channelNumber, value);
|
|
1101
|
-
case 64:
|
|
1102
|
-
return this.setSustainPedal(channelNumber, value);
|
|
1103
|
-
case 65:
|
|
1104
|
-
return this.setPortamento(channelNumber, value);
|
|
1105
|
-
case 66:
|
|
1106
|
-
return this.setSostenutoPedal(channelNumber, value);
|
|
1107
|
-
case 67:
|
|
1108
|
-
return this.setSoftPedal(channelNumber, value);
|
|
1109
|
-
case 91:
|
|
1110
|
-
return this.setReverbSendLevel(channelNumber, value);
|
|
1111
|
-
case 93:
|
|
1112
|
-
return this.setChorusSendLevel(channelNumber, value);
|
|
1113
|
-
case 100:
|
|
1114
|
-
return this.setRPNLSB(channelNumber, value);
|
|
1115
|
-
case 101:
|
|
1116
|
-
return this.setRPNMSB(channelNumber, value);
|
|
1117
|
-
case 120:
|
|
1118
|
-
return this.allSoundOff(channelNumber);
|
|
1119
|
-
case 121:
|
|
1120
|
-
return this.resetAllControllers(channelNumber);
|
|
1121
|
-
case 123:
|
|
1122
|
-
return this.allNotesOff(channelNumber);
|
|
1123
|
-
case 124:
|
|
1124
|
-
return this.omniOff();
|
|
1125
|
-
case 125:
|
|
1126
|
-
return this.omniOn();
|
|
1127
|
-
case 126:
|
|
1128
|
-
return this.monoOn();
|
|
1129
|
-
case 127:
|
|
1130
|
-
return this.polyOn();
|
|
1131
|
-
default:
|
|
1132
|
-
console.warn(`Unsupported Control change: controller=${controller} value=${value}`);
|
|
1114
|
+
const handler = this.controlChangeHandlers[controller];
|
|
1115
|
+
if (handler) {
|
|
1116
|
+
handler.call(this, channelNumber, value);
|
|
1117
|
+
}
|
|
1118
|
+
else {
|
|
1119
|
+
console.warn(`Unsupported Control change: controller=${controller} value=${value}`);
|
|
1133
1120
|
}
|
|
1134
1121
|
}
|
|
1135
1122
|
setBankMSB(channelNumber, msb) {
|
|
@@ -1137,15 +1124,19 @@ class MidyGM2 {
|
|
|
1137
1124
|
}
|
|
1138
1125
|
updateModulation(channel) {
|
|
1139
1126
|
const now = this.audioContext.currentTime;
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1127
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1128
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1129
|
+
const note = noteList[i];
|
|
1130
|
+
if (!note)
|
|
1131
|
+
continue;
|
|
1132
|
+
if (note.modulationDepth) {
|
|
1133
|
+
note.modulationDepth.gain.setValueAtTime(channel.modulationDepth, now);
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
1137
|
+
this.setPitch(note, semitoneOffset);
|
|
1138
|
+
this.startModulation(channel, note, now);
|
|
1139
|
+
}
|
|
1149
1140
|
}
|
|
1150
1141
|
});
|
|
1151
1142
|
}
|
|
@@ -1210,28 +1201,49 @@ class MidyGM2 {
|
|
|
1210
1201
|
}
|
|
1211
1202
|
setReverbSendLevel(channelNumber, reverbSendLevel) {
|
|
1212
1203
|
const channel = this.channels[channelNumber];
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1204
|
+
if (0 < channel.reverbSendLevel) {
|
|
1205
|
+
if (0 < reverbSendLevel) {
|
|
1206
|
+
const now = this.audioContext.currentTime;
|
|
1207
|
+
channel.reverbSendLevel = reverbSendLevel / 127;
|
|
1208
|
+
reverbEffect.output.gain.cancelScheduledValues(now);
|
|
1209
|
+
reverbEffect.output.gain.setValueAtTime(channel.reverbSendLevel, now);
|
|
1210
|
+
}
|
|
1211
|
+
else {
|
|
1212
|
+
channel.merger.disconnect(reverbEffect.input);
|
|
1213
|
+
}
|
|
1219
1214
|
}
|
|
1220
|
-
else
|
|
1221
|
-
|
|
1215
|
+
else {
|
|
1216
|
+
if (0 < reverbSendLevel) {
|
|
1217
|
+
channel.merger.connect(reverbEffect.input);
|
|
1218
|
+
const now = this.audioContext.currentTime;
|
|
1219
|
+
channel.reverbSendLevel = reverbSendLevel / 127;
|
|
1220
|
+
reverbEffect.output.gain.cancelScheduledValues(now);
|
|
1221
|
+
reverbEffect.output.gain.setValueAtTime(channel.reverbSendLevel, now);
|
|
1222
|
+
}
|
|
1222
1223
|
}
|
|
1223
1224
|
}
|
|
1224
1225
|
setChorusSendLevel(channelNumber, chorusSendLevel) {
|
|
1225
1226
|
const channel = this.channels[channelNumber];
|
|
1226
1227
|
const chorusEffect = this.chorusEffect;
|
|
1227
|
-
if (0 < chorusSendLevel) {
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1228
|
+
if (0 < channel.chorusSendLevel) {
|
|
1229
|
+
if (0 < chorusSendLevel) {
|
|
1230
|
+
const now = this.audioContext.currentTime;
|
|
1231
|
+
channel.chorusSendLevel = chorusSendLevel / 127;
|
|
1232
|
+
chorusEffect.output.gain.cancelScheduledValues(now);
|
|
1233
|
+
chorusEffect.output.gain.setValueAtTime(channel.chorusSendLevel, now);
|
|
1234
|
+
}
|
|
1235
|
+
else {
|
|
1236
|
+
channel.merger.disconnect(chorusEffect.input);
|
|
1237
|
+
}
|
|
1232
1238
|
}
|
|
1233
|
-
else
|
|
1234
|
-
|
|
1239
|
+
else {
|
|
1240
|
+
if (0 < chorusSendLevel) {
|
|
1241
|
+
channel.merger.connect(chorusEffect.input);
|
|
1242
|
+
const now = this.audioContext.currentTime;
|
|
1243
|
+
channel.chorusSendLevel = chorusSendLevel / 127;
|
|
1244
|
+
chorusEffect.output.gain.cancelScheduledValues(now);
|
|
1245
|
+
chorusEffect.output.gain.setValueAtTime(channel.chorusSendLevel, now);
|
|
1246
|
+
}
|
|
1235
1247
|
}
|
|
1236
1248
|
}
|
|
1237
1249
|
setSostenutoPedal(channelNumber, value) {
|
|
@@ -1309,13 +1321,17 @@ class MidyGM2 {
|
|
|
1309
1321
|
}
|
|
1310
1322
|
updateDetune(channel, detuneChange) {
|
|
1311
1323
|
const now = this.audioContext.currentTime;
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
.
|
|
1324
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1325
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1326
|
+
const note = noteList[i];
|
|
1327
|
+
if (!note)
|
|
1328
|
+
continue;
|
|
1329
|
+
const { bufferSource } = note;
|
|
1330
|
+
const detune = bufferSource.detune.value + detuneChange;
|
|
1331
|
+
bufferSource.detune
|
|
1332
|
+
.cancelScheduledValues(now)
|
|
1333
|
+
.setValueAtTime(detune, now);
|
|
1334
|
+
}
|
|
1319
1335
|
});
|
|
1320
1336
|
}
|
|
1321
1337
|
handlePitchBendRangeRPN(channelNumber) {
|
package/script/midy-GMLite.d.ts
CHANGED
|
@@ -37,6 +37,20 @@ export class MidyGMLite {
|
|
|
37
37
|
notePromises: any[];
|
|
38
38
|
audioContext: any;
|
|
39
39
|
masterGain: any;
|
|
40
|
+
controlChangeHandlers: {
|
|
41
|
+
1: (channelNumber: any, modulation: any) => void;
|
|
42
|
+
6: (channelNumber: any, value: any) => void;
|
|
43
|
+
7: (channelNumber: any, volume: any) => void;
|
|
44
|
+
10: (channelNumber: any, pan: any) => void;
|
|
45
|
+
11: (channelNumber: any, expression: any) => void;
|
|
46
|
+
38: (channelNumber: any, value: any) => void;
|
|
47
|
+
64: (channelNumber: any, value: any) => void;
|
|
48
|
+
100: (channelNumber: any, value: any) => void;
|
|
49
|
+
101: (channelNumber: any, value: any) => void;
|
|
50
|
+
120: (channelNumber: any) => Promise<void>;
|
|
51
|
+
121: (channelNumber: any) => void;
|
|
52
|
+
123: (channelNumber: any) => Promise<void>;
|
|
53
|
+
};
|
|
40
54
|
channels: any[];
|
|
41
55
|
initSoundFontTable(): any[];
|
|
42
56
|
addSoundFont(soundFont: any): void;
|
|
@@ -77,19 +91,34 @@ export class MidyGMLite {
|
|
|
77
91
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
78
92
|
setVolumeEnvelope(note: any): void;
|
|
79
93
|
setPitch(note: any, semitoneOffset: any): void;
|
|
80
|
-
|
|
94
|
+
clampCutoffFrequency(frequency: any): number;
|
|
95
|
+
setFilterEnvelope(note: any): void;
|
|
81
96
|
startModulation(channel: any, note: any, startTime: any): void;
|
|
82
97
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
83
98
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
84
99
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
85
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any,
|
|
100
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
|
|
86
101
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
87
102
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
88
103
|
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
89
104
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
90
105
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
91
106
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
92
|
-
|
|
107
|
+
createControlChangeHandlers(): {
|
|
108
|
+
1: (channelNumber: any, modulation: any) => void;
|
|
109
|
+
6: (channelNumber: any, value: any) => void;
|
|
110
|
+
7: (channelNumber: any, volume: any) => void;
|
|
111
|
+
10: (channelNumber: any, pan: any) => void;
|
|
112
|
+
11: (channelNumber: any, expression: any) => void;
|
|
113
|
+
38: (channelNumber: any, value: any) => void;
|
|
114
|
+
64: (channelNumber: any, value: any) => void;
|
|
115
|
+
100: (channelNumber: any, value: any) => void;
|
|
116
|
+
101: (channelNumber: any, value: any) => void;
|
|
117
|
+
120: (channelNumber: any) => Promise<void>;
|
|
118
|
+
121: (channelNumber: any) => void;
|
|
119
|
+
123: (channelNumber: any) => Promise<void>;
|
|
120
|
+
};
|
|
121
|
+
handleControlChange(channelNumber: any, controller: any, value: any): void;
|
|
93
122
|
updateModulation(channel: any): void;
|
|
94
123
|
setModulationDepth(channelNumber: any, modulation: any): void;
|
|
95
124
|
setVolume(channelNumber: any, volume: any): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAsBA;IAmBE;;;;;;;;;MASE;IAEF;;;;;;;MAOE;IAEF,+
|
|
1
|
+
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAsBA;IAmBE;;;;;;;;;MASE;IAEF;;;;;;;MAOE;IAEF,+BAOC;IA7CD,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;IAuBhB,kBAAgC;IAChC,gBAA4C;IAC5C;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EA+CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA8DC;IAED,mFAmBC;IAED,yDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,2BAEC;IAED,4BAEC;IAED,yCAEC;IAED,mFAGC;IAED,mCAeC;IAED,+CAwBC;IAED,6CAIC;IAED,mCAsBC;IAED,+DA0BC;IAED,wHAmCC;IAED,kGA8BC;IAED,0EAGC;IAED,uIA2CC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;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,sCAUC;IAED,sDAMC;IAED,oCAYC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAaC;IAED,kDAKC;IAED,iEAOC;IAED,+CAEC;IAED,8CAEC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAj/BD;IAQE,gFAKC;IAZD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|