@marmooo/midy 0.1.5 → 0.1.7
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 +6 -5
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +97 -65
- package/esm/midy-GM2.d.ts +15 -9
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +316 -129
- package/esm/midy-GMLite.d.ts +6 -5
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +97 -65
- package/esm/midy.d.ts +15 -9
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +317 -134
- package/package.json +5 -1
- package/script/midy-GM1.d.ts +6 -5
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +100 -68
- package/script/midy-GM2.d.ts +15 -9
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +319 -132
- package/script/midy-GMLite.d.ts +6 -5
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +100 -68
- package/script/midy.d.ts +15 -9
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +320 -137
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.d.ts +0 -149
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.d.ts.map +0 -1
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.js +0 -180
- package/esm/deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.d.ts +0 -84
- package/esm/deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.d.ts.map +0 -1
- package/esm/deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.js +0 -216
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.d.ts +0 -149
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.d.ts.map +0 -1
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.6/+esm.js +0 -190
- package/script/deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.d.ts +0 -84
- package/script/deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.d.ts.map +0 -1
- package/script/deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.js +0 -221
package/script/midy-GMLite.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export class MidyGMLite {
|
|
|
35
35
|
timeline: any[];
|
|
36
36
|
instruments: any[];
|
|
37
37
|
notePromises: any[];
|
|
38
|
+
exclusiveClassMap: Map<any, any>;
|
|
38
39
|
audioContext: any;
|
|
39
40
|
masterGain: any;
|
|
40
41
|
controlChangeHandlers: {
|
|
@@ -64,7 +65,6 @@ export class MidyGMLite {
|
|
|
64
65
|
createChannels(audioContext: any): any[];
|
|
65
66
|
createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
|
|
66
67
|
createNoteBufferNode(instrumentKey: any, isSF3: any): Promise<any>;
|
|
67
|
-
convertToFloat32Array(uint8Array: any): Float32Array;
|
|
68
68
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
69
69
|
getQueueIndex(second: any): number;
|
|
70
70
|
playNotes(): Promise<any>;
|
|
@@ -74,8 +74,8 @@ export class MidyGMLite {
|
|
|
74
74
|
instruments: Set<any>;
|
|
75
75
|
timeline: any[];
|
|
76
76
|
};
|
|
77
|
-
stopChannelNotes(channelNumber: any, velocity: any,
|
|
78
|
-
stopNotes(velocity: any,
|
|
77
|
+
stopChannelNotes(channelNumber: any, velocity: any, force: any): Promise<void>;
|
|
78
|
+
stopNotes(velocity: any, force: any): Promise<any[]>;
|
|
79
79
|
start(): Promise<void>;
|
|
80
80
|
stop(): void;
|
|
81
81
|
pause(): void;
|
|
@@ -97,7 +97,8 @@ export class MidyGMLite {
|
|
|
97
97
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
98
98
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
99
99
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
100
|
-
|
|
100
|
+
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
101
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): Promise<any> | undefined;
|
|
101
102
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
102
103
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
103
104
|
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
@@ -129,7 +130,7 @@ export class MidyGMLite {
|
|
|
129
130
|
setPan(channelNumber: any, pan: any): void;
|
|
130
131
|
setExpression(channelNumber: any, expression: any): void;
|
|
131
132
|
dataEntryLSB(channelNumber: any, value: any): void;
|
|
132
|
-
|
|
133
|
+
updateChannelVolume(channel: any): void;
|
|
133
134
|
setSustainPedal(channelNumber: any, value: any): void;
|
|
134
135
|
handleRPN(channelNumber: any): void;
|
|
135
136
|
setRPNMSB(channelNumber: any, value: any): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAmBA;IAoBE;;;;;;;;;MASE;IAEF;;;;;;;MAOE;IAEF,+BAOC;IA9CD,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;IAClB,iCAA8B;IAuB5B,kBAAgC;IAChC,gBAA4C;IAC5C;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,+DA2BC;IAED,mEAWC;IAED,2EA+CC;IAED,mCAOC;IAED,0BAkDC;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,kGAgDC;IAED,0EAGC;IAED,qFA4BC;IAED,6HAuBC;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,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;AA5gCD;IAQE,gFAKC;IAZD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|
package/script/midy-GMLite.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MidyGMLite = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const midi_file_1 = require("midi-file");
|
|
5
|
+
const soundfont_parser_1 = require("@marmooo/soundfont-parser");
|
|
6
6
|
class Note {
|
|
7
7
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
8
8
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -151,6 +151,12 @@ class MidyGMLite {
|
|
|
151
151
|
writable: true,
|
|
152
152
|
value: []
|
|
153
153
|
});
|
|
154
|
+
Object.defineProperty(this, "exclusiveClassMap", {
|
|
155
|
+
enumerable: true,
|
|
156
|
+
configurable: true,
|
|
157
|
+
writable: true,
|
|
158
|
+
value: new Map()
|
|
159
|
+
});
|
|
154
160
|
this.audioContext = audioContext;
|
|
155
161
|
this.masterGain = new GainNode(audioContext);
|
|
156
162
|
this.controlChangeHandlers = this.createControlChangeHandlers();
|
|
@@ -168,24 +174,26 @@ class MidyGMLite {
|
|
|
168
174
|
addSoundFont(soundFont) {
|
|
169
175
|
const index = this.soundFonts.length;
|
|
170
176
|
this.soundFonts.push(soundFont);
|
|
171
|
-
soundFont.parsed.presetHeaders
|
|
177
|
+
const presetHeaders = soundFont.parsed.presetHeaders;
|
|
178
|
+
for (let i = 0; i < presetHeaders.length; i++) {
|
|
179
|
+
const presetHeader = presetHeaders[i];
|
|
172
180
|
if (!presetHeader.presetName.startsWith("\u0000")) { // TODO: Only SF3 generated by PolyPone?
|
|
173
181
|
const banks = this.soundFontTable[presetHeader.preset];
|
|
174
182
|
banks.set(presetHeader.bank, index);
|
|
175
183
|
}
|
|
176
|
-
}
|
|
184
|
+
}
|
|
177
185
|
}
|
|
178
186
|
async loadSoundFont(soundFontUrl) {
|
|
179
187
|
const response = await fetch(soundFontUrl);
|
|
180
188
|
const arrayBuffer = await response.arrayBuffer();
|
|
181
|
-
const parsed = (0,
|
|
182
|
-
const soundFont = new
|
|
189
|
+
const parsed = (0, soundfont_parser_1.parse)(new Uint8Array(arrayBuffer));
|
|
190
|
+
const soundFont = new soundfont_parser_1.SoundFont(parsed);
|
|
183
191
|
this.addSoundFont(soundFont);
|
|
184
192
|
}
|
|
185
193
|
async loadMIDI(midiUrl) {
|
|
186
194
|
const response = await fetch(midiUrl);
|
|
187
195
|
const arrayBuffer = await response.arrayBuffer();
|
|
188
|
-
const midi = (0,
|
|
196
|
+
const midi = (0, midi_file_1.parseMidi)(new Uint8Array(arrayBuffer));
|
|
189
197
|
this.ticksPerBeat = midi.header.ticksPerBeat;
|
|
190
198
|
const midiData = this.extractMidiData(midi);
|
|
191
199
|
this.instruments = midiData.instruments;
|
|
@@ -218,27 +226,31 @@ class MidyGMLite {
|
|
|
218
226
|
return channels;
|
|
219
227
|
}
|
|
220
228
|
async createNoteBuffer(instrumentKey, isSF3) {
|
|
229
|
+
const sampleStart = instrumentKey.start;
|
|
221
230
|
const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
|
|
222
231
|
if (isSF3) {
|
|
223
|
-
const sample =
|
|
224
|
-
sample.
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
channelData.set(channelData.subarray(0, sampleEnd));
|
|
229
|
-
}
|
|
232
|
+
const sample = instrumentKey.sample;
|
|
233
|
+
const start = sample.byteOffset + sampleStart;
|
|
234
|
+
const end = sample.byteOffset + sampleEnd;
|
|
235
|
+
const buffer = sample.buffer.slice(start, end);
|
|
236
|
+
const audioBuffer = await this.audioContext.decodeAudioData(buffer);
|
|
230
237
|
return audioBuffer;
|
|
231
238
|
}
|
|
232
239
|
else {
|
|
233
|
-
const sample = instrumentKey.sample
|
|
234
|
-
const
|
|
240
|
+
const sample = instrumentKey.sample;
|
|
241
|
+
const start = sample.byteOffset + sampleStart;
|
|
242
|
+
const end = sample.byteOffset + sampleEnd;
|
|
243
|
+
const buffer = sample.buffer.slice(start, end);
|
|
235
244
|
const audioBuffer = new AudioBuffer({
|
|
236
245
|
numberOfChannels: 1,
|
|
237
246
|
length: sample.length,
|
|
238
247
|
sampleRate: instrumentKey.sampleRate,
|
|
239
248
|
});
|
|
240
249
|
const channelData = audioBuffer.getChannelData(0);
|
|
241
|
-
|
|
250
|
+
const int16Array = new Int16Array(buffer);
|
|
251
|
+
for (let i = 0; i < int16Array.length; i++) {
|
|
252
|
+
channelData[i] = int16Array[i] / 32768;
|
|
253
|
+
}
|
|
242
254
|
return audioBuffer;
|
|
243
255
|
}
|
|
244
256
|
}
|
|
@@ -254,14 +266,6 @@ class MidyGMLite {
|
|
|
254
266
|
}
|
|
255
267
|
return bufferSource;
|
|
256
268
|
}
|
|
257
|
-
convertToFloat32Array(uint8Array) {
|
|
258
|
-
const int16Array = new Int16Array(uint8Array.buffer);
|
|
259
|
-
const float32Array = new Float32Array(int16Array.length);
|
|
260
|
-
for (let i = 0; i < int16Array.length; i++) {
|
|
261
|
-
float32Array[i] = int16Array[i] / 32768;
|
|
262
|
-
}
|
|
263
|
-
return float32Array;
|
|
264
|
-
}
|
|
265
269
|
async scheduleTimelineEvents(t, offset, queueIndex) {
|
|
266
270
|
while (queueIndex < this.timeline.length) {
|
|
267
271
|
const event = this.timeline[queueIndex];
|
|
@@ -317,6 +321,7 @@ class MidyGMLite {
|
|
|
317
321
|
if (queueIndex >= this.timeline.length) {
|
|
318
322
|
await Promise.all(this.notePromises);
|
|
319
323
|
this.notePromises = [];
|
|
324
|
+
this.exclusiveClassMap.clear();
|
|
320
325
|
resolve();
|
|
321
326
|
return;
|
|
322
327
|
}
|
|
@@ -332,6 +337,7 @@ class MidyGMLite {
|
|
|
332
337
|
}
|
|
333
338
|
else if (this.isStopping) {
|
|
334
339
|
await this.stopNotes(0, true);
|
|
340
|
+
this.exclusiveClassMap.clear();
|
|
335
341
|
this.notePromises = [];
|
|
336
342
|
resolve();
|
|
337
343
|
this.isStopping = false;
|
|
@@ -340,6 +346,7 @@ class MidyGMLite {
|
|
|
340
346
|
}
|
|
341
347
|
else if (this.isSeeking) {
|
|
342
348
|
this.stopNotes(0, true);
|
|
349
|
+
this.exclusiveClassMap.clear();
|
|
343
350
|
this.startTime = this.audioContext.currentTime;
|
|
344
351
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
345
352
|
offset = this.resumeTime - this.startTime;
|
|
@@ -372,9 +379,11 @@ class MidyGMLite {
|
|
|
372
379
|
bank: this.channels[i].bank,
|
|
373
380
|
};
|
|
374
381
|
}
|
|
375
|
-
midi.tracks.
|
|
382
|
+
for (let i = 0; i < midi.tracks.length; i++) {
|
|
383
|
+
const track = midi.tracks[i];
|
|
376
384
|
let currentTicks = 0;
|
|
377
|
-
track.
|
|
385
|
+
for (let j = 0; j < track.length; j++) {
|
|
386
|
+
const event = track[j];
|
|
378
387
|
currentTicks += event.deltaTime;
|
|
379
388
|
event.ticks = currentTicks;
|
|
380
389
|
switch (event.type) {
|
|
@@ -394,8 +403,8 @@ class MidyGMLite {
|
|
|
394
403
|
}
|
|
395
404
|
delete event.deltaTime;
|
|
396
405
|
timeline.push(event);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
399
408
|
const priority = {
|
|
400
409
|
controller: 0,
|
|
401
410
|
sysEx: 1,
|
|
@@ -420,7 +429,7 @@ class MidyGMLite {
|
|
|
420
429
|
}
|
|
421
430
|
return { instruments, timeline };
|
|
422
431
|
}
|
|
423
|
-
async stopChannelNotes(channelNumber, velocity,
|
|
432
|
+
async stopChannelNotes(channelNumber, velocity, force) {
|
|
424
433
|
const now = this.audioContext.currentTime;
|
|
425
434
|
const channel = this.channels[channelNumber];
|
|
426
435
|
channel.scheduledNotes.forEach((noteList) => {
|
|
@@ -428,16 +437,16 @@ class MidyGMLite {
|
|
|
428
437
|
const note = noteList[i];
|
|
429
438
|
if (!note)
|
|
430
439
|
continue;
|
|
431
|
-
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now,
|
|
440
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, force);
|
|
432
441
|
this.notePromises.push(promise);
|
|
433
442
|
}
|
|
434
443
|
});
|
|
435
444
|
channel.scheduledNotes.clear();
|
|
436
445
|
await Promise.all(this.notePromises);
|
|
437
446
|
}
|
|
438
|
-
stopNotes(velocity,
|
|
447
|
+
stopNotes(velocity, force) {
|
|
439
448
|
for (let i = 0; i < this.channels.length; i++) {
|
|
440
|
-
this.stopChannelNotes(i, velocity,
|
|
449
|
+
this.stopChannelNotes(i, velocity, force);
|
|
441
450
|
}
|
|
442
451
|
return Promise.all(this.notePromises);
|
|
443
452
|
}
|
|
@@ -613,7 +622,7 @@ class MidyGMLite {
|
|
|
613
622
|
note.volumeNode = new GainNode(this.audioContext);
|
|
614
623
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
615
624
|
type: "lowpass",
|
|
616
|
-
Q: instrumentKey.initialFilterQ / 10
|
|
625
|
+
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
617
626
|
});
|
|
618
627
|
this.setVolumeEnvelope(note);
|
|
619
628
|
this.setFilterEnvelope(note);
|
|
@@ -626,7 +635,7 @@ class MidyGMLite {
|
|
|
626
635
|
}
|
|
627
636
|
note.bufferSource.connect(note.filterNode);
|
|
628
637
|
note.filterNode.connect(note.volumeNode);
|
|
629
|
-
note.bufferSource.start(startTime
|
|
638
|
+
note.bufferSource.start(startTime);
|
|
630
639
|
return note;
|
|
631
640
|
}
|
|
632
641
|
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
|
|
@@ -643,6 +652,19 @@ class MidyGMLite {
|
|
|
643
652
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
644
653
|
note.volumeNode.connect(channel.gainL);
|
|
645
654
|
note.volumeNode.connect(channel.gainR);
|
|
655
|
+
const exclusiveClass = instrumentKey.exclusiveClass;
|
|
656
|
+
if (exclusiveClass !== 0) {
|
|
657
|
+
if (this.exclusiveClassMap.has(exclusiveClass)) {
|
|
658
|
+
const prevEntry = this.exclusiveClassMap.get(exclusiveClass);
|
|
659
|
+
const [prevNote, prevChannelNumber] = prevEntry;
|
|
660
|
+
if (!prevNote.ending) {
|
|
661
|
+
this.scheduleNoteRelease(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
662
|
+
startTime, undefined, // portamentoNoteNumber
|
|
663
|
+
true);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
this.exclusiveClassMap.set(exclusiveClass, [note, channelNumber]);
|
|
667
|
+
}
|
|
646
668
|
const scheduledNotes = channel.scheduledNotes;
|
|
647
669
|
if (scheduledNotes.has(noteNumber)) {
|
|
648
670
|
scheduledNotes.get(noteNumber).push(note);
|
|
@@ -655,9 +677,38 @@ class MidyGMLite {
|
|
|
655
677
|
const now = this.audioContext.currentTime;
|
|
656
678
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
657
679
|
}
|
|
658
|
-
|
|
680
|
+
stopNote(endTime, stopTime, scheduledNotes, index) {
|
|
681
|
+
const note = scheduledNotes[index];
|
|
682
|
+
note.volumeNode.gain
|
|
683
|
+
.cancelScheduledValues(endTime)
|
|
684
|
+
.linearRampToValueAtTime(0, stopTime);
|
|
685
|
+
note.ending = true;
|
|
686
|
+
this.scheduleTask(() => {
|
|
687
|
+
note.bufferSource.loop = false;
|
|
688
|
+
}, stopTime);
|
|
689
|
+
return new Promise((resolve) => {
|
|
690
|
+
note.bufferSource.onended = () => {
|
|
691
|
+
scheduledNotes[index] = null;
|
|
692
|
+
note.bufferSource.disconnect();
|
|
693
|
+
note.volumeNode.disconnect();
|
|
694
|
+
note.filterNode.disconnect();
|
|
695
|
+
if (note.modulationDepth) {
|
|
696
|
+
note.volumeDepth.disconnect();
|
|
697
|
+
note.modulationDepth.disconnect();
|
|
698
|
+
note.modulationLFO.stop();
|
|
699
|
+
}
|
|
700
|
+
if (note.vibratoDepth) {
|
|
701
|
+
note.vibratoDepth.disconnect();
|
|
702
|
+
note.vibratoLFO.stop();
|
|
703
|
+
}
|
|
704
|
+
resolve();
|
|
705
|
+
};
|
|
706
|
+
note.bufferSource.stop(stopTime);
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, endTime, force) {
|
|
659
710
|
const channel = this.channels[channelNumber];
|
|
660
|
-
if (
|
|
711
|
+
if (!force && channel.sustainPedal)
|
|
661
712
|
return;
|
|
662
713
|
if (!channel.scheduledNotes.has(noteNumber))
|
|
663
714
|
return;
|
|
@@ -668,33 +719,13 @@ class MidyGMLite {
|
|
|
668
719
|
continue;
|
|
669
720
|
if (note.ending)
|
|
670
721
|
continue;
|
|
671
|
-
const
|
|
672
|
-
note.
|
|
673
|
-
.cancelScheduledValues(stopTime)
|
|
674
|
-
.linearRampToValueAtTime(0, volEndTime);
|
|
675
|
-
const modRelease = stopTime + note.instrumentKey.modRelease;
|
|
722
|
+
const volRelease = endTime + note.instrumentKey.volRelease;
|
|
723
|
+
const modRelease = endTime + note.instrumentKey.modRelease;
|
|
676
724
|
note.filterNode.frequency
|
|
677
|
-
.cancelScheduledValues(
|
|
725
|
+
.cancelScheduledValues(endTime)
|
|
678
726
|
.linearRampToValueAtTime(0, modRelease);
|
|
679
|
-
|
|
680
|
-
this.
|
|
681
|
-
note.bufferSource.loop = false;
|
|
682
|
-
}, stopTime);
|
|
683
|
-
return new Promise((resolve) => {
|
|
684
|
-
note.bufferSource.onended = () => {
|
|
685
|
-
scheduledNotes[i] = null;
|
|
686
|
-
note.bufferSource.disconnect();
|
|
687
|
-
note.volumeNode.disconnect();
|
|
688
|
-
note.filterNode.disconnect();
|
|
689
|
-
if (note.modulationDepth) {
|
|
690
|
-
note.volumeDepth.disconnect();
|
|
691
|
-
note.modulationDepth.disconnect();
|
|
692
|
-
note.modulationLFO.stop();
|
|
693
|
-
}
|
|
694
|
-
resolve();
|
|
695
|
-
};
|
|
696
|
-
note.bufferSource.stop(volEndTime);
|
|
697
|
-
});
|
|
727
|
+
const stopTime = Math.min(volRelease, modRelease);
|
|
728
|
+
return this.stopNote(endTime, stopTime, scheduledNotes, i);
|
|
698
729
|
}
|
|
699
730
|
}
|
|
700
731
|
releaseNote(channelNumber, noteNumber, velocity) {
|
|
@@ -803,7 +834,7 @@ class MidyGMLite {
|
|
|
803
834
|
setVolume(channelNumber, volume) {
|
|
804
835
|
const channel = this.channels[channelNumber];
|
|
805
836
|
channel.volume = volume / 127;
|
|
806
|
-
this.
|
|
837
|
+
this.updateChannelVolume(channel);
|
|
807
838
|
}
|
|
808
839
|
panToGain(pan) {
|
|
809
840
|
const theta = Math.PI / 2 * Math.max(0, pan - 1) / 126;
|
|
@@ -815,18 +846,18 @@ class MidyGMLite {
|
|
|
815
846
|
setPan(channelNumber, pan) {
|
|
816
847
|
const channel = this.channels[channelNumber];
|
|
817
848
|
channel.pan = pan;
|
|
818
|
-
this.
|
|
849
|
+
this.updateChannelVolume(channel);
|
|
819
850
|
}
|
|
820
851
|
setExpression(channelNumber, expression) {
|
|
821
852
|
const channel = this.channels[channelNumber];
|
|
822
853
|
channel.expression = expression / 127;
|
|
823
|
-
this.
|
|
854
|
+
this.updateChannelVolume(channel);
|
|
824
855
|
}
|
|
825
856
|
dataEntryLSB(channelNumber, value) {
|
|
826
857
|
this.channels[channelNumber].dataLSB = value;
|
|
827
858
|
this.handleRPN(channelNumber);
|
|
828
859
|
}
|
|
829
|
-
|
|
860
|
+
updateChannelVolume(channel) {
|
|
830
861
|
const now = this.audioContext.currentTime;
|
|
831
862
|
const volume = channel.volume * channel.expression;
|
|
832
863
|
const { gainLeft, gainRight } = this.panToGain(channel.pan);
|
|
@@ -921,11 +952,12 @@ class MidyGMLite {
|
|
|
921
952
|
}
|
|
922
953
|
}
|
|
923
954
|
GM1SystemOn() {
|
|
924
|
-
this.channels.
|
|
955
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
956
|
+
const channel = this.channels[i];
|
|
925
957
|
channel.bankMSB = 0;
|
|
926
958
|
channel.bankLSB = 0;
|
|
927
959
|
channel.bank = 0;
|
|
928
|
-
}
|
|
960
|
+
}
|
|
929
961
|
this.channels[9].bankMSB = 1;
|
|
930
962
|
this.channels[9].bank = 128;
|
|
931
963
|
}
|
package/script/midy.d.ts
CHANGED
|
@@ -83,6 +83,7 @@ export class Midy {
|
|
|
83
83
|
timeline: any[];
|
|
84
84
|
instruments: any[];
|
|
85
85
|
notePromises: any[];
|
|
86
|
+
exclusiveClassMap: Map<any, any>;
|
|
86
87
|
defaultOptions: {
|
|
87
88
|
reverbAlgorithm: (audioContext: any) => {
|
|
88
89
|
input: any;
|
|
@@ -159,7 +160,7 @@ export class Midy {
|
|
|
159
160
|
createChannels(audioContext: any): any[];
|
|
160
161
|
createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
|
|
161
162
|
createNoteBufferNode(instrumentKey: any, isSF3: any): Promise<any>;
|
|
162
|
-
|
|
163
|
+
findPortamentoTarget(queueIndex: any): any;
|
|
163
164
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
164
165
|
getQueueIndex(second: any): number;
|
|
165
166
|
playNotes(): Promise<any>;
|
|
@@ -169,8 +170,8 @@ export class Midy {
|
|
|
169
170
|
instruments: Set<any>;
|
|
170
171
|
timeline: any[];
|
|
171
172
|
};
|
|
172
|
-
stopChannelNotes(channelNumber: any, velocity: any,
|
|
173
|
-
stopNotes(velocity: any,
|
|
173
|
+
stopChannelNotes(channelNumber: any, velocity: any, force: any): Promise<void>;
|
|
174
|
+
stopNotes(velocity: any, force: any): Promise<any[]>;
|
|
174
175
|
start(): Promise<void>;
|
|
175
176
|
stop(): void;
|
|
176
177
|
pause(): void;
|
|
@@ -206,18 +207,21 @@ export class Midy {
|
|
|
206
207
|
centToHz(cent: any): number;
|
|
207
208
|
calcSemitoneOffset(channel: any): any;
|
|
208
209
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
210
|
+
setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
|
|
209
211
|
setVolumeEnvelope(channel: any, note: any): void;
|
|
210
212
|
setPitch(note: any, semitoneOffset: any): void;
|
|
211
213
|
clampCutoffFrequency(frequency: any): number;
|
|
214
|
+
setPortamentoStartFilterEnvelope(channel: any, note: any): void;
|
|
212
215
|
setFilterEnvelope(channel: any, note: any): void;
|
|
213
216
|
startModulation(channel: any, note: any, startTime: any): void;
|
|
214
217
|
startVibrato(channel: any, note: any, startTime: any): void;
|
|
215
|
-
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
218
|
+
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
|
|
216
219
|
calcBank(channel: any, channelNumber: any): any;
|
|
217
|
-
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
218
|
-
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
|
|
221
|
+
noteOn(channelNumber: any, noteNumber: any, velocity: any, portamento: any): Promise<void>;
|
|
222
|
+
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
223
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, portamentoNoteNumber: any, force: any): Promise<any> | undefined;
|
|
224
|
+
releaseNote(channelNumber: any, noteNumber: any, velocity: any, portamentoNoteNumber: any): Promise<any> | undefined;
|
|
221
225
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
222
226
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
|
|
223
227
|
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
@@ -276,7 +280,7 @@ export class Midy {
|
|
|
276
280
|
setExpression(channelNumber: any, expression: any): void;
|
|
277
281
|
setBankLSB(channelNumber: any, lsb: any): void;
|
|
278
282
|
dataEntryLSB(channelNumber: any, value: any): void;
|
|
279
|
-
|
|
283
|
+
updateChannelVolume(channel: any): void;
|
|
280
284
|
setSustainPedal(channelNumber: any, value: any): void;
|
|
281
285
|
setPortamento(channelNumber: any, value: any): void;
|
|
282
286
|
setReverbSendLevel(channelNumber: any, reverbSendLevel: any): void;
|
|
@@ -357,6 +361,8 @@ declare class Note {
|
|
|
357
361
|
modulationDepth: any;
|
|
358
362
|
vibratoLFO: any;
|
|
359
363
|
vibratoDepth: any;
|
|
364
|
+
reverbEffectsSend: any;
|
|
365
|
+
chorusEffectsSend: any;
|
|
360
366
|
noteNumber: any;
|
|
361
367
|
velocity: any;
|
|
362
368
|
startTime: any;
|
package/script/midy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}
|