@marmooo/midy 0.1.4 → 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/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 +36 -8
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +87 -89
- package/esm/midy-GM2.d.ts +65 -10
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +233 -154
- package/esm/midy-GMLite.d.ts +36 -8
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +87 -89
- package/esm/midy.d.ts +85 -10
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +254 -174
- 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 +36 -8
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +87 -89
- package/script/midy-GM2.d.ts +65 -10
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +233 -154
- package/script/midy-GMLite.d.ts +36 -8
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +87 -89
- package/script/midy.d.ts +85 -10
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +254 -174
- 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/esm/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;
|
|
@@ -50,7 +64,6 @@ export class MidyGMLite {
|
|
|
50
64
|
createChannels(audioContext: any): any[];
|
|
51
65
|
createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
|
|
52
66
|
createNoteBufferNode(instrumentKey: any, isSF3: any): Promise<any>;
|
|
53
|
-
convertToFloat32Array(uint8Array: any): Float32Array;
|
|
54
67
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
55
68
|
getQueueIndex(second: any): number;
|
|
56
69
|
playNotes(): Promise<any>;
|
|
@@ -60,8 +73,8 @@ export class MidyGMLite {
|
|
|
60
73
|
instruments: Set<any>;
|
|
61
74
|
timeline: any[];
|
|
62
75
|
};
|
|
63
|
-
stopChannelNotes(channelNumber: any, velocity: any,
|
|
64
|
-
stopNotes(velocity: any,
|
|
76
|
+
stopChannelNotes(channelNumber: any, velocity: any, force: any): Promise<void>;
|
|
77
|
+
stopNotes(velocity: any, force: any): Promise<any[]>;
|
|
65
78
|
start(): Promise<void>;
|
|
66
79
|
stop(): void;
|
|
67
80
|
pause(): void;
|
|
@@ -83,14 +96,29 @@ export class MidyGMLite {
|
|
|
83
96
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
84
97
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
85
98
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
86
|
-
|
|
87
|
-
|
|
99
|
+
stopNote(stopTime: any, endTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
100
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, force: any): void;
|
|
101
|
+
releaseNote(channelNumber: any, noteNumber: any, velocity: any): void;
|
|
88
102
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
89
|
-
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<
|
|
103
|
+
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<void>;
|
|
90
104
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
91
105
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
92
106
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
93
|
-
|
|
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;
|
|
94
122
|
updateModulation(channel: any): void;
|
|
95
123
|
setModulationDepth(channelNumber: any, modulation: any): void;
|
|
96
124
|
setVolume(channelNumber: any, volume: any): void;
|
|
@@ -101,7 +129,7 @@ export class MidyGMLite {
|
|
|
101
129
|
setPan(channelNumber: any, pan: any): void;
|
|
102
130
|
setExpression(channelNumber: any, expression: any): void;
|
|
103
131
|
dataEntryLSB(channelNumber: any, value: any): void;
|
|
104
|
-
|
|
132
|
+
updateChannelVolume(channel: any): void;
|
|
105
133
|
setSustainPedal(channelNumber: any, value: any): void;
|
|
106
134
|
handleRPN(channelNumber: any): void;
|
|
107
135
|
setRPNMSB(channelNumber: any, value: any): void;
|
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":"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,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,yCAEC;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,oCAYC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAaC;IAED,kDAKC;IAED,iEAOC;IAED,+CAEC;IAED,8CAEC;IAED,+CAEC;IAED,4DAgBC;IAED,oBASC;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"}
|
package/esm/midy-GMLite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseMidi } from "./deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.js";
|
|
2
|
-
import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.
|
|
2
|
+
import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.js";
|
|
3
3
|
class Note {
|
|
4
4
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
5
5
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -150,6 +150,7 @@ export class MidyGMLite {
|
|
|
150
150
|
});
|
|
151
151
|
this.audioContext = audioContext;
|
|
152
152
|
this.masterGain = new GainNode(audioContext);
|
|
153
|
+
this.controlChangeHandlers = this.createControlChangeHandlers();
|
|
153
154
|
this.channels = this.createChannels(audioContext);
|
|
154
155
|
this.masterGain.connect(audioContext.destination);
|
|
155
156
|
this.GM1SystemOn();
|
|
@@ -164,12 +165,14 @@ export class MidyGMLite {
|
|
|
164
165
|
addSoundFont(soundFont) {
|
|
165
166
|
const index = this.soundFonts.length;
|
|
166
167
|
this.soundFonts.push(soundFont);
|
|
167
|
-
soundFont.parsed.presetHeaders
|
|
168
|
+
const presetHeaders = soundFont.parsed.presetHeaders;
|
|
169
|
+
for (let i = 0; i < presetHeaders.length; i++) {
|
|
170
|
+
const presetHeader = presetHeaders[i];
|
|
168
171
|
if (!presetHeader.presetName.startsWith("\u0000")) { // TODO: Only SF3 generated by PolyPone?
|
|
169
172
|
const banks = this.soundFontTable[presetHeader.preset];
|
|
170
173
|
banks.set(presetHeader.bank, index);
|
|
171
174
|
}
|
|
172
|
-
}
|
|
175
|
+
}
|
|
173
176
|
}
|
|
174
177
|
async loadSoundFont(soundFontUrl) {
|
|
175
178
|
const response = await fetch(soundFontUrl);
|
|
@@ -214,27 +217,25 @@ export class MidyGMLite {
|
|
|
214
217
|
return channels;
|
|
215
218
|
}
|
|
216
219
|
async createNoteBuffer(instrumentKey, isSF3) {
|
|
220
|
+
const sampleStart = instrumentKey.start;
|
|
217
221
|
const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
|
|
218
222
|
if (isSF3) {
|
|
219
|
-
const sample =
|
|
220
|
-
sample.set(instrumentKey.sample);
|
|
223
|
+
const sample = instrumentKey.sample.slice(sampleStart, sampleEnd);
|
|
221
224
|
const audioBuffer = await this.audioContext.decodeAudioData(sample.buffer);
|
|
222
|
-
for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {
|
|
223
|
-
const channelData = audioBuffer.getChannelData(channel);
|
|
224
|
-
channelData.set(channelData.subarray(0, sampleEnd));
|
|
225
|
-
}
|
|
226
225
|
return audioBuffer;
|
|
227
226
|
}
|
|
228
227
|
else {
|
|
229
|
-
const sample = instrumentKey.sample.subarray(
|
|
230
|
-
const floatSample = this.convertToFloat32Array(sample);
|
|
228
|
+
const sample = instrumentKey.sample.subarray(sampleStart, sampleEnd);
|
|
231
229
|
const audioBuffer = new AudioBuffer({
|
|
232
230
|
numberOfChannels: 1,
|
|
233
231
|
length: sample.length,
|
|
234
232
|
sampleRate: instrumentKey.sampleRate,
|
|
235
233
|
});
|
|
236
234
|
const channelData = audioBuffer.getChannelData(0);
|
|
237
|
-
|
|
235
|
+
const int16Array = new Int16Array(sample.buffer);
|
|
236
|
+
for (let i = 0; i < int16Array.length; i++) {
|
|
237
|
+
channelData[i] = int16Array[i] / 32768;
|
|
238
|
+
}
|
|
238
239
|
return audioBuffer;
|
|
239
240
|
}
|
|
240
241
|
}
|
|
@@ -250,14 +251,6 @@ export class MidyGMLite {
|
|
|
250
251
|
}
|
|
251
252
|
return bufferSource;
|
|
252
253
|
}
|
|
253
|
-
convertToFloat32Array(uint8Array) {
|
|
254
|
-
const int16Array = new Int16Array(uint8Array.buffer);
|
|
255
|
-
const float32Array = new Float32Array(int16Array.length);
|
|
256
|
-
for (let i = 0; i < int16Array.length; i++) {
|
|
257
|
-
float32Array[i] = int16Array[i] / 32768;
|
|
258
|
-
}
|
|
259
|
-
return float32Array;
|
|
260
|
-
}
|
|
261
254
|
async scheduleTimelineEvents(t, offset, queueIndex) {
|
|
262
255
|
while (queueIndex < this.timeline.length) {
|
|
263
256
|
const event = this.timeline[queueIndex];
|
|
@@ -368,9 +361,11 @@ export class MidyGMLite {
|
|
|
368
361
|
bank: this.channels[i].bank,
|
|
369
362
|
};
|
|
370
363
|
}
|
|
371
|
-
midi.tracks.
|
|
364
|
+
for (let i = 0; i < midi.tracks.length; i++) {
|
|
365
|
+
const track = midi.tracks[i];
|
|
372
366
|
let currentTicks = 0;
|
|
373
|
-
track.
|
|
367
|
+
for (let j = 0; j < track.length; j++) {
|
|
368
|
+
const event = track[j];
|
|
374
369
|
currentTicks += event.deltaTime;
|
|
375
370
|
event.ticks = currentTicks;
|
|
376
371
|
switch (event.type) {
|
|
@@ -390,8 +385,8 @@ export class MidyGMLite {
|
|
|
390
385
|
}
|
|
391
386
|
delete event.deltaTime;
|
|
392
387
|
timeline.push(event);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
395
390
|
const priority = {
|
|
396
391
|
controller: 0,
|
|
397
392
|
sysEx: 1,
|
|
@@ -416,7 +411,7 @@ export class MidyGMLite {
|
|
|
416
411
|
}
|
|
417
412
|
return { instruments, timeline };
|
|
418
413
|
}
|
|
419
|
-
async stopChannelNotes(channelNumber, velocity,
|
|
414
|
+
async stopChannelNotes(channelNumber, velocity, force) {
|
|
420
415
|
const now = this.audioContext.currentTime;
|
|
421
416
|
const channel = this.channels[channelNumber];
|
|
422
417
|
channel.scheduledNotes.forEach((noteList) => {
|
|
@@ -424,16 +419,16 @@ export class MidyGMLite {
|
|
|
424
419
|
const note = noteList[i];
|
|
425
420
|
if (!note)
|
|
426
421
|
continue;
|
|
427
|
-
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now,
|
|
422
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, force);
|
|
428
423
|
this.notePromises.push(promise);
|
|
429
424
|
}
|
|
430
425
|
});
|
|
431
426
|
channel.scheduledNotes.clear();
|
|
432
427
|
await Promise.all(this.notePromises);
|
|
433
428
|
}
|
|
434
|
-
stopNotes(velocity,
|
|
429
|
+
stopNotes(velocity, force) {
|
|
435
430
|
for (let i = 0; i < this.channels.length; i++) {
|
|
436
|
-
this.stopChannelNotes(i, velocity,
|
|
431
|
+
this.stopChannelNotes(i, velocity, force);
|
|
437
432
|
}
|
|
438
433
|
return Promise.all(this.notePromises);
|
|
439
434
|
}
|
|
@@ -609,7 +604,7 @@ export class MidyGMLite {
|
|
|
609
604
|
note.volumeNode = new GainNode(this.audioContext);
|
|
610
605
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
611
606
|
type: "lowpass",
|
|
612
|
-
Q: instrumentKey.initialFilterQ / 10
|
|
607
|
+
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
613
608
|
});
|
|
614
609
|
this.setVolumeEnvelope(note);
|
|
615
610
|
this.setFilterEnvelope(note);
|
|
@@ -622,7 +617,7 @@ export class MidyGMLite {
|
|
|
622
617
|
}
|
|
623
618
|
note.bufferSource.connect(note.filterNode);
|
|
624
619
|
note.filterNode.connect(note.volumeNode);
|
|
625
|
-
note.bufferSource.start(startTime
|
|
620
|
+
note.bufferSource.start(startTime);
|
|
626
621
|
return note;
|
|
627
622
|
}
|
|
628
623
|
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
|
|
@@ -633,7 +628,7 @@ export class MidyGMLite {
|
|
|
633
628
|
return;
|
|
634
629
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
635
630
|
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
636
|
-
const instrumentKey = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber);
|
|
631
|
+
const instrumentKey = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber, velocity);
|
|
637
632
|
if (!instrumentKey)
|
|
638
633
|
return;
|
|
639
634
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
@@ -651,9 +646,38 @@ export class MidyGMLite {
|
|
|
651
646
|
const now = this.audioContext.currentTime;
|
|
652
647
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
653
648
|
}
|
|
654
|
-
|
|
649
|
+
stopNote(stopTime, endTime, scheduledNotes, index) {
|
|
650
|
+
const note = scheduledNotes[index];
|
|
651
|
+
note.volumeNode.gain
|
|
652
|
+
.cancelScheduledValues(stopTime)
|
|
653
|
+
.linearRampToValueAtTime(0, endTime);
|
|
654
|
+
note.ending = true;
|
|
655
|
+
this.scheduleTask(() => {
|
|
656
|
+
note.bufferSource.loop = false;
|
|
657
|
+
}, endTime);
|
|
658
|
+
return new Promise((resolve) => {
|
|
659
|
+
note.bufferSource.onended = () => {
|
|
660
|
+
scheduledNotes[index] = null;
|
|
661
|
+
note.bufferSource.disconnect();
|
|
662
|
+
note.volumeNode.disconnect();
|
|
663
|
+
note.filterNode.disconnect();
|
|
664
|
+
if (note.modulationDepth) {
|
|
665
|
+
note.volumeDepth.disconnect();
|
|
666
|
+
note.modulationDepth.disconnect();
|
|
667
|
+
note.modulationLFO.stop();
|
|
668
|
+
}
|
|
669
|
+
if (note.vibratoDepth) {
|
|
670
|
+
note.vibratoDepth.disconnect();
|
|
671
|
+
note.vibratoLFO.stop();
|
|
672
|
+
}
|
|
673
|
+
resolve();
|
|
674
|
+
};
|
|
675
|
+
note.bufferSource.stop(endTime);
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, force) {
|
|
655
679
|
const channel = this.channels[channelNumber];
|
|
656
|
-
if (
|
|
680
|
+
if (!force && channel.sustainPedal)
|
|
657
681
|
return;
|
|
658
682
|
if (!channel.scheduledNotes.has(noteNumber))
|
|
659
683
|
return;
|
|
@@ -665,33 +689,11 @@ export class MidyGMLite {
|
|
|
665
689
|
if (note.ending)
|
|
666
690
|
continue;
|
|
667
691
|
const volEndTime = stopTime + note.instrumentKey.volRelease;
|
|
668
|
-
note.volumeNode.gain
|
|
669
|
-
.cancelScheduledValues(stopTime)
|
|
670
|
-
.linearRampToValueAtTime(0, volEndTime);
|
|
671
692
|
const modRelease = stopTime + note.instrumentKey.modRelease;
|
|
672
693
|
note.filterNode.frequency
|
|
673
694
|
.cancelScheduledValues(stopTime)
|
|
674
695
|
.linearRampToValueAtTime(0, modRelease);
|
|
675
|
-
|
|
676
|
-
this.scheduleTask(() => {
|
|
677
|
-
note.bufferSource.loop = false;
|
|
678
|
-
}, stopTime);
|
|
679
|
-
return new Promise((resolve) => {
|
|
680
|
-
note.bufferSource.onended = () => {
|
|
681
|
-
scheduledNotes[i] = null;
|
|
682
|
-
note.bufferSource.disconnect();
|
|
683
|
-
note.volumeNode.disconnect();
|
|
684
|
-
note.filterNode.disconnect();
|
|
685
|
-
if (note.volumeDepth)
|
|
686
|
-
note.volumeDepth.disconnect();
|
|
687
|
-
if (note.modulationDepth)
|
|
688
|
-
note.modulationDepth.disconnect();
|
|
689
|
-
if (note.modulationLFO)
|
|
690
|
-
note.modulationLFO.stop();
|
|
691
|
-
resolve();
|
|
692
|
-
};
|
|
693
|
-
note.bufferSource.stop(volEndTime);
|
|
694
|
-
});
|
|
696
|
+
this.stopNote(stopTime, volEndTime, scheduledNotes, i);
|
|
695
697
|
}
|
|
696
698
|
}
|
|
697
699
|
releaseNote(channelNumber, noteNumber, velocity) {
|
|
@@ -749,34 +751,29 @@ export class MidyGMLite {
|
|
|
749
751
|
channel.pitchBendRange * 100;
|
|
750
752
|
this.updateDetune(channel, detuneChange);
|
|
751
753
|
}
|
|
754
|
+
createControlChangeHandlers() {
|
|
755
|
+
return {
|
|
756
|
+
1: this.setModulationDepth,
|
|
757
|
+
6: this.dataEntryMSB,
|
|
758
|
+
7: this.setVolume,
|
|
759
|
+
10: this.setPan,
|
|
760
|
+
11: this.setExpression,
|
|
761
|
+
38: this.dataEntryLSB,
|
|
762
|
+
64: this.setSustainPedal,
|
|
763
|
+
100: this.setRPNLSB,
|
|
764
|
+
101: this.setRPNMSB,
|
|
765
|
+
120: this.allSoundOff,
|
|
766
|
+
121: this.resetAllControllers,
|
|
767
|
+
123: this.allNotesOff,
|
|
768
|
+
};
|
|
769
|
+
}
|
|
752
770
|
handleControlChange(channelNumber, controller, value) {
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
return this.setVolume(channelNumber, value);
|
|
760
|
-
case 10:
|
|
761
|
-
return this.setPan(channelNumber, value);
|
|
762
|
-
case 11:
|
|
763
|
-
return this.setExpression(channelNumber, value);
|
|
764
|
-
case 38:
|
|
765
|
-
return this.dataEntryLSB(channelNumber, value);
|
|
766
|
-
case 64:
|
|
767
|
-
return this.setSustainPedal(channelNumber, value);
|
|
768
|
-
case 100:
|
|
769
|
-
return this.setRPNLSB(channelNumber, value);
|
|
770
|
-
case 101:
|
|
771
|
-
return this.setRPNMSB(channelNumber, value);
|
|
772
|
-
case 120:
|
|
773
|
-
return this.allSoundOff(channelNumber);
|
|
774
|
-
case 121:
|
|
775
|
-
return this.resetAllControllers(channelNumber);
|
|
776
|
-
case 123:
|
|
777
|
-
return this.allNotesOff(channelNumber);
|
|
778
|
-
default:
|
|
779
|
-
console.warn(`Unsupported Control change: controller=${controller} value=${value}`);
|
|
771
|
+
const handler = this.controlChangeHandlers[controller];
|
|
772
|
+
if (handler) {
|
|
773
|
+
handler.call(this, channelNumber, value);
|
|
774
|
+
}
|
|
775
|
+
else {
|
|
776
|
+
console.warn(`Unsupported Control change: controller=${controller} value=${value}`);
|
|
780
777
|
}
|
|
781
778
|
}
|
|
782
779
|
updateModulation(channel) {
|
|
@@ -805,7 +802,7 @@ export class MidyGMLite {
|
|
|
805
802
|
setVolume(channelNumber, volume) {
|
|
806
803
|
const channel = this.channels[channelNumber];
|
|
807
804
|
channel.volume = volume / 127;
|
|
808
|
-
this.
|
|
805
|
+
this.updateChannelVolume(channel);
|
|
809
806
|
}
|
|
810
807
|
panToGain(pan) {
|
|
811
808
|
const theta = Math.PI / 2 * Math.max(0, pan - 1) / 126;
|
|
@@ -817,18 +814,18 @@ export class MidyGMLite {
|
|
|
817
814
|
setPan(channelNumber, pan) {
|
|
818
815
|
const channel = this.channels[channelNumber];
|
|
819
816
|
channel.pan = pan;
|
|
820
|
-
this.
|
|
817
|
+
this.updateChannelVolume(channel);
|
|
821
818
|
}
|
|
822
819
|
setExpression(channelNumber, expression) {
|
|
823
820
|
const channel = this.channels[channelNumber];
|
|
824
821
|
channel.expression = expression / 127;
|
|
825
|
-
this.
|
|
822
|
+
this.updateChannelVolume(channel);
|
|
826
823
|
}
|
|
827
824
|
dataEntryLSB(channelNumber, value) {
|
|
828
825
|
this.channels[channelNumber].dataLSB = value;
|
|
829
826
|
this.handleRPN(channelNumber);
|
|
830
827
|
}
|
|
831
|
-
|
|
828
|
+
updateChannelVolume(channel) {
|
|
832
829
|
const now = this.audioContext.currentTime;
|
|
833
830
|
const volume = channel.volume * channel.expression;
|
|
834
831
|
const { gainLeft, gainRight } = this.panToGain(channel.pan);
|
|
@@ -923,11 +920,12 @@ export class MidyGMLite {
|
|
|
923
920
|
}
|
|
924
921
|
}
|
|
925
922
|
GM1SystemOn() {
|
|
926
|
-
this.channels.
|
|
923
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
924
|
+
const channel = this.channels[i];
|
|
927
925
|
channel.bankMSB = 0;
|
|
928
926
|
channel.bankLSB = 0;
|
|
929
927
|
channel.bank = 0;
|
|
930
|
-
}
|
|
928
|
+
}
|
|
931
929
|
this.channels[9].bankMSB = 1;
|
|
932
930
|
this.channels[9].bank = 128;
|
|
933
931
|
}
|
package/esm/midy.d.ts
CHANGED
|
@@ -97,6 +97,42 @@ export class Midy {
|
|
|
97
97
|
};
|
|
98
98
|
};
|
|
99
99
|
masterGain: any;
|
|
100
|
+
controlChangeHandlers: {
|
|
101
|
+
0: (channelNumber: any, msb: any) => void;
|
|
102
|
+
1: (channelNumber: any, modulation: any) => void;
|
|
103
|
+
5: (channelNumber: any, portamentoTime: any) => void;
|
|
104
|
+
6: (channelNumber: any, value: any) => void;
|
|
105
|
+
7: (channelNumber: any, volume: any) => void;
|
|
106
|
+
10: (channelNumber: any, pan: any) => void;
|
|
107
|
+
11: (channelNumber: any, expression: any) => void;
|
|
108
|
+
32: (channelNumber: any, lsb: any) => void;
|
|
109
|
+
38: (channelNumber: any, value: any) => void;
|
|
110
|
+
64: (channelNumber: any, value: any) => void;
|
|
111
|
+
65: (channelNumber: any, value: any) => void;
|
|
112
|
+
66: (channelNumber: any, value: any) => void;
|
|
113
|
+
67: (channelNumber: any, softPedal: any) => void;
|
|
114
|
+
71: (channelNumber: any, filterResonance: any) => void;
|
|
115
|
+
72: (channelNumber: any, releaseTime: any) => void;
|
|
116
|
+
73: (channelNumber: any, attackTime: any) => void;
|
|
117
|
+
74: (channelNumber: any, brightness: any) => void;
|
|
118
|
+
75: (channelNumber: any, dacayTime: any) => void;
|
|
119
|
+
76: (channelNumber: any, vibratoRate: any) => void;
|
|
120
|
+
77: (channelNumber: any, vibratoDepth: any) => void;
|
|
121
|
+
78: (channelNumber: any, vibratoDelay: any) => void;
|
|
122
|
+
91: (channelNumber: any, reverbSendLevel: any) => void;
|
|
123
|
+
93: (channelNumber: any, chorusSendLevel: any) => void;
|
|
124
|
+
96: (channelNumber: any) => void;
|
|
125
|
+
97: (channelNumber: any) => void;
|
|
126
|
+
100: (channelNumber: any, value: any) => void;
|
|
127
|
+
101: (channelNumber: any, value: any) => void;
|
|
128
|
+
120: (channelNumber: any) => Promise<void>;
|
|
129
|
+
121: (channelNumber: any) => void;
|
|
130
|
+
123: (channelNumber: any) => Promise<void>;
|
|
131
|
+
124: () => void;
|
|
132
|
+
125: () => void;
|
|
133
|
+
126: () => void;
|
|
134
|
+
127: () => void;
|
|
135
|
+
};
|
|
100
136
|
channels: any[];
|
|
101
137
|
reverbEffect: {
|
|
102
138
|
input: any;
|
|
@@ -123,7 +159,7 @@ export class Midy {
|
|
|
123
159
|
createChannels(audioContext: any): any[];
|
|
124
160
|
createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
|
|
125
161
|
createNoteBufferNode(instrumentKey: any, isSF3: any): Promise<any>;
|
|
126
|
-
|
|
162
|
+
findPortamentoTarget(queueIndex: any): any;
|
|
127
163
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
128
164
|
getQueueIndex(second: any): number;
|
|
129
165
|
playNotes(): Promise<any>;
|
|
@@ -133,8 +169,8 @@ export class Midy {
|
|
|
133
169
|
instruments: Set<any>;
|
|
134
170
|
timeline: any[];
|
|
135
171
|
};
|
|
136
|
-
stopChannelNotes(channelNumber: any, velocity: any,
|
|
137
|
-
stopNotes(velocity: any,
|
|
172
|
+
stopChannelNotes(channelNumber: any, velocity: any, force: any): Promise<void>;
|
|
173
|
+
stopNotes(velocity: any, force: any): Promise<any[]>;
|
|
138
174
|
start(): Promise<void>;
|
|
139
175
|
stop(): void;
|
|
140
176
|
pause(): void;
|
|
@@ -170,18 +206,21 @@ export class Midy {
|
|
|
170
206
|
centToHz(cent: any): number;
|
|
171
207
|
calcSemitoneOffset(channel: any): any;
|
|
172
208
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
209
|
+
setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
|
|
173
210
|
setVolumeEnvelope(channel: any, note: any): void;
|
|
174
211
|
setPitch(note: any, semitoneOffset: any): void;
|
|
175
212
|
clampCutoffFrequency(frequency: any): number;
|
|
213
|
+
setPortamentoStartFilterEnvelope(channel: any, note: any): void;
|
|
176
214
|
setFilterEnvelope(channel: any, note: any): void;
|
|
177
215
|
startModulation(channel: any, note: any, startTime: any): void;
|
|
178
216
|
startVibrato(channel: any, note: any, startTime: any): void;
|
|
179
|
-
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
217
|
+
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
|
|
180
218
|
calcBank(channel: any, channelNumber: any): any;
|
|
181
|
-
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
182
|
-
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
183
|
-
|
|
184
|
-
|
|
219
|
+
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
|
|
220
|
+
noteOn(channelNumber: any, noteNumber: any, velocity: any, portamento: any): Promise<void>;
|
|
221
|
+
stopNote(stopTime: any, endTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
222
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, portamentoNoteNumber: any, force: any): Promise<any> | undefined;
|
|
223
|
+
releaseNote(channelNumber: any, noteNumber: any, velocity: any, portamentoNoteNumber: any): Promise<any> | undefined;
|
|
185
224
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
186
225
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
|
|
187
226
|
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
@@ -190,7 +229,43 @@ export class Midy {
|
|
|
190
229
|
handleChannelPressure(channelNumber: any, pressure: any): void;
|
|
191
230
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
192
231
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
193
|
-
|
|
232
|
+
createControlChangeHandlers(): {
|
|
233
|
+
0: (channelNumber: any, msb: any) => void;
|
|
234
|
+
1: (channelNumber: any, modulation: any) => void;
|
|
235
|
+
5: (channelNumber: any, portamentoTime: any) => void;
|
|
236
|
+
6: (channelNumber: any, value: any) => void;
|
|
237
|
+
7: (channelNumber: any, volume: any) => void;
|
|
238
|
+
10: (channelNumber: any, pan: any) => void;
|
|
239
|
+
11: (channelNumber: any, expression: any) => void;
|
|
240
|
+
32: (channelNumber: any, lsb: any) => void;
|
|
241
|
+
38: (channelNumber: any, value: any) => void;
|
|
242
|
+
64: (channelNumber: any, value: any) => void;
|
|
243
|
+
65: (channelNumber: any, value: any) => void;
|
|
244
|
+
66: (channelNumber: any, value: any) => void;
|
|
245
|
+
67: (channelNumber: any, softPedal: any) => void;
|
|
246
|
+
71: (channelNumber: any, filterResonance: any) => void;
|
|
247
|
+
72: (channelNumber: any, releaseTime: any) => void;
|
|
248
|
+
73: (channelNumber: any, attackTime: any) => void;
|
|
249
|
+
74: (channelNumber: any, brightness: any) => void;
|
|
250
|
+
75: (channelNumber: any, dacayTime: any) => void;
|
|
251
|
+
76: (channelNumber: any, vibratoRate: any) => void;
|
|
252
|
+
77: (channelNumber: any, vibratoDepth: any) => void;
|
|
253
|
+
78: (channelNumber: any, vibratoDelay: any) => void;
|
|
254
|
+
91: (channelNumber: any, reverbSendLevel: any) => void;
|
|
255
|
+
93: (channelNumber: any, chorusSendLevel: any) => void;
|
|
256
|
+
96: (channelNumber: any) => void;
|
|
257
|
+
97: (channelNumber: any) => void;
|
|
258
|
+
100: (channelNumber: any, value: any) => void;
|
|
259
|
+
101: (channelNumber: any, value: any) => void;
|
|
260
|
+
120: (channelNumber: any) => Promise<void>;
|
|
261
|
+
121: (channelNumber: any) => void;
|
|
262
|
+
123: (channelNumber: any) => Promise<void>;
|
|
263
|
+
124: () => void;
|
|
264
|
+
125: () => void;
|
|
265
|
+
126: () => void;
|
|
266
|
+
127: () => void;
|
|
267
|
+
};
|
|
268
|
+
handleControlChange(channelNumber: any, controller: any, value: any): void;
|
|
194
269
|
setBankMSB(channelNumber: any, msb: any): void;
|
|
195
270
|
updateModulation(channel: any): void;
|
|
196
271
|
setModulationDepth(channelNumber: any, modulation: any): void;
|
|
@@ -204,7 +279,7 @@ export class Midy {
|
|
|
204
279
|
setExpression(channelNumber: any, expression: any): void;
|
|
205
280
|
setBankLSB(channelNumber: any, lsb: any): void;
|
|
206
281
|
dataEntryLSB(channelNumber: any, value: any): void;
|
|
207
|
-
|
|
282
|
+
updateChannelVolume(channel: any): void;
|
|
208
283
|
setSustainPedal(channelNumber: any, value: any): void;
|
|
209
284
|
setPortamento(channelNumber: any, value: any): void;
|
|
210
285
|
setReverbSendLevel(channelNumber: any, reverbSendLevel: any): void;
|
package/esm/midy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"AAwBA;IAkCE;;;;;;;;;;;;;;;;;;;;;;;;;MAyBE;IAEF;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAgCF;;;;;
|
|
1
|
+
{"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}
|