@marmooo/midy 0.1.6 → 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 +5 -4
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +45 -16
- package/esm/midy-GM2.d.ts +5 -2
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +176 -66
- package/esm/midy-GMLite.d.ts +5 -4
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +45 -16
- package/esm/midy.d.ts +5 -2
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +177 -67
- package/package.json +5 -1
- package/script/midy-GM1.d.ts +5 -4
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +48 -19
- package/script/midy-GM2.d.ts +5 -2
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +179 -69
- package/script/midy-GMLite.d.ts +5 -4
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +48 -19
- package/script/midy.d.ts +5 -2
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +180 -70
- 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/esm/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: {
|
|
@@ -96,11 +97,11 @@ export class MidyGMLite {
|
|
|
96
97
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
97
98
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
98
99
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
99
|
-
stopNote(
|
|
100
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any,
|
|
101
|
-
releaseNote(channelNumber: any, noteNumber: any, velocity: any):
|
|
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;
|
|
102
|
+
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
102
103
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
103
|
-
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<
|
|
104
|
+
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
104
105
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
105
106
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
106
107
|
setPitchBend(channelNumber: any, pitchBend: 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":"
|
|
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/esm/midy-GMLite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseMidi } from "
|
|
2
|
-
import { parse, SoundFont
|
|
1
|
+
import { parseMidi } from "midi-file";
|
|
2
|
+
import { parse, SoundFont } from "@marmooo/soundfont-parser";
|
|
3
3
|
class Note {
|
|
4
4
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
5
5
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -148,6 +148,12 @@ export class MidyGMLite {
|
|
|
148
148
|
writable: true,
|
|
149
149
|
value: []
|
|
150
150
|
});
|
|
151
|
+
Object.defineProperty(this, "exclusiveClassMap", {
|
|
152
|
+
enumerable: true,
|
|
153
|
+
configurable: true,
|
|
154
|
+
writable: true,
|
|
155
|
+
value: new Map()
|
|
156
|
+
});
|
|
151
157
|
this.audioContext = audioContext;
|
|
152
158
|
this.masterGain = new GainNode(audioContext);
|
|
153
159
|
this.controlChangeHandlers = this.createControlChangeHandlers();
|
|
@@ -220,19 +226,25 @@ export class MidyGMLite {
|
|
|
220
226
|
const sampleStart = instrumentKey.start;
|
|
221
227
|
const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
|
|
222
228
|
if (isSF3) {
|
|
223
|
-
const sample = instrumentKey.sample
|
|
224
|
-
const
|
|
229
|
+
const sample = instrumentKey.sample;
|
|
230
|
+
const start = sample.byteOffset + sampleStart;
|
|
231
|
+
const end = sample.byteOffset + sampleEnd;
|
|
232
|
+
const buffer = sample.buffer.slice(start, end);
|
|
233
|
+
const audioBuffer = await this.audioContext.decodeAudioData(buffer);
|
|
225
234
|
return audioBuffer;
|
|
226
235
|
}
|
|
227
236
|
else {
|
|
228
|
-
const sample = instrumentKey.sample
|
|
237
|
+
const sample = instrumentKey.sample;
|
|
238
|
+
const start = sample.byteOffset + sampleStart;
|
|
239
|
+
const end = sample.byteOffset + sampleEnd;
|
|
240
|
+
const buffer = sample.buffer.slice(start, end);
|
|
229
241
|
const audioBuffer = new AudioBuffer({
|
|
230
242
|
numberOfChannels: 1,
|
|
231
243
|
length: sample.length,
|
|
232
244
|
sampleRate: instrumentKey.sampleRate,
|
|
233
245
|
});
|
|
234
246
|
const channelData = audioBuffer.getChannelData(0);
|
|
235
|
-
const int16Array = new Int16Array(
|
|
247
|
+
const int16Array = new Int16Array(buffer);
|
|
236
248
|
for (let i = 0; i < int16Array.length; i++) {
|
|
237
249
|
channelData[i] = int16Array[i] / 32768;
|
|
238
250
|
}
|
|
@@ -306,6 +318,7 @@ export class MidyGMLite {
|
|
|
306
318
|
if (queueIndex >= this.timeline.length) {
|
|
307
319
|
await Promise.all(this.notePromises);
|
|
308
320
|
this.notePromises = [];
|
|
321
|
+
this.exclusiveClassMap.clear();
|
|
309
322
|
resolve();
|
|
310
323
|
return;
|
|
311
324
|
}
|
|
@@ -321,6 +334,7 @@ export class MidyGMLite {
|
|
|
321
334
|
}
|
|
322
335
|
else if (this.isStopping) {
|
|
323
336
|
await this.stopNotes(0, true);
|
|
337
|
+
this.exclusiveClassMap.clear();
|
|
324
338
|
this.notePromises = [];
|
|
325
339
|
resolve();
|
|
326
340
|
this.isStopping = false;
|
|
@@ -329,6 +343,7 @@ export class MidyGMLite {
|
|
|
329
343
|
}
|
|
330
344
|
else if (this.isSeeking) {
|
|
331
345
|
this.stopNotes(0, true);
|
|
346
|
+
this.exclusiveClassMap.clear();
|
|
332
347
|
this.startTime = this.audioContext.currentTime;
|
|
333
348
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
334
349
|
offset = this.resumeTime - this.startTime;
|
|
@@ -634,6 +649,19 @@ export class MidyGMLite {
|
|
|
634
649
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
635
650
|
note.volumeNode.connect(channel.gainL);
|
|
636
651
|
note.volumeNode.connect(channel.gainR);
|
|
652
|
+
const exclusiveClass = instrumentKey.exclusiveClass;
|
|
653
|
+
if (exclusiveClass !== 0) {
|
|
654
|
+
if (this.exclusiveClassMap.has(exclusiveClass)) {
|
|
655
|
+
const prevEntry = this.exclusiveClassMap.get(exclusiveClass);
|
|
656
|
+
const [prevNote, prevChannelNumber] = prevEntry;
|
|
657
|
+
if (!prevNote.ending) {
|
|
658
|
+
this.scheduleNoteRelease(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
659
|
+
startTime, undefined, // portamentoNoteNumber
|
|
660
|
+
true);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
this.exclusiveClassMap.set(exclusiveClass, [note, channelNumber]);
|
|
664
|
+
}
|
|
637
665
|
const scheduledNotes = channel.scheduledNotes;
|
|
638
666
|
if (scheduledNotes.has(noteNumber)) {
|
|
639
667
|
scheduledNotes.get(noteNumber).push(note);
|
|
@@ -646,15 +674,15 @@ export class MidyGMLite {
|
|
|
646
674
|
const now = this.audioContext.currentTime;
|
|
647
675
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
648
676
|
}
|
|
649
|
-
stopNote(
|
|
677
|
+
stopNote(endTime, stopTime, scheduledNotes, index) {
|
|
650
678
|
const note = scheduledNotes[index];
|
|
651
679
|
note.volumeNode.gain
|
|
652
|
-
.cancelScheduledValues(
|
|
653
|
-
.linearRampToValueAtTime(0,
|
|
680
|
+
.cancelScheduledValues(endTime)
|
|
681
|
+
.linearRampToValueAtTime(0, stopTime);
|
|
654
682
|
note.ending = true;
|
|
655
683
|
this.scheduleTask(() => {
|
|
656
684
|
note.bufferSource.loop = false;
|
|
657
|
-
},
|
|
685
|
+
}, stopTime);
|
|
658
686
|
return new Promise((resolve) => {
|
|
659
687
|
note.bufferSource.onended = () => {
|
|
660
688
|
scheduledNotes[index] = null;
|
|
@@ -672,10 +700,10 @@ export class MidyGMLite {
|
|
|
672
700
|
}
|
|
673
701
|
resolve();
|
|
674
702
|
};
|
|
675
|
-
note.bufferSource.stop(
|
|
703
|
+
note.bufferSource.stop(stopTime);
|
|
676
704
|
});
|
|
677
705
|
}
|
|
678
|
-
scheduleNoteRelease(channelNumber, noteNumber, _velocity,
|
|
706
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, endTime, force) {
|
|
679
707
|
const channel = this.channels[channelNumber];
|
|
680
708
|
if (!force && channel.sustainPedal)
|
|
681
709
|
return;
|
|
@@ -688,12 +716,13 @@ export class MidyGMLite {
|
|
|
688
716
|
continue;
|
|
689
717
|
if (note.ending)
|
|
690
718
|
continue;
|
|
691
|
-
const
|
|
692
|
-
const modRelease =
|
|
719
|
+
const volRelease = endTime + note.instrumentKey.volRelease;
|
|
720
|
+
const modRelease = endTime + note.instrumentKey.modRelease;
|
|
693
721
|
note.filterNode.frequency
|
|
694
|
-
.cancelScheduledValues(
|
|
722
|
+
.cancelScheduledValues(endTime)
|
|
695
723
|
.linearRampToValueAtTime(0, modRelease);
|
|
696
|
-
|
|
724
|
+
const stopTime = Math.min(volRelease, modRelease);
|
|
725
|
+
return this.stopNote(endTime, stopTime, scheduledNotes, i);
|
|
697
726
|
}
|
|
698
727
|
}
|
|
699
728
|
releaseNote(channelNumber, noteNumber, velocity) {
|
package/esm/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;
|
|
@@ -218,8 +219,8 @@ export class Midy {
|
|
|
218
219
|
calcBank(channel: any, channelNumber: any): any;
|
|
219
220
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
|
|
220
221
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, portamento: any): Promise<void>;
|
|
221
|
-
stopNote(
|
|
222
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any,
|
|
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;
|
|
223
224
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any, portamentoNoteNumber: any): Promise<any> | undefined;
|
|
224
225
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
225
226
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
|
|
@@ -360,6 +361,8 @@ declare class Note {
|
|
|
360
361
|
modulationDepth: any;
|
|
361
362
|
vibratoLFO: any;
|
|
362
363
|
vibratoDepth: any;
|
|
364
|
+
reverbEffectsSend: any;
|
|
365
|
+
chorusEffectsSend: any;
|
|
363
366
|
noteNumber: any;
|
|
364
367
|
velocity: any;
|
|
365
368
|
startTime: any;
|
package/esm/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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"}
|
package/esm/midy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseMidi } from "
|
|
2
|
-
import { parse, SoundFont
|
|
1
|
+
import { parseMidi } from "midi-file";
|
|
2
|
+
import { parse, SoundFont } from "@marmooo/soundfont-parser";
|
|
3
3
|
class Note {
|
|
4
4
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
5
5
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -50,6 +50,18 @@ class Note {
|
|
|
50
50
|
writable: true,
|
|
51
51
|
value: void 0
|
|
52
52
|
});
|
|
53
|
+
Object.defineProperty(this, "reverbEffectsSend", {
|
|
54
|
+
enumerable: true,
|
|
55
|
+
configurable: true,
|
|
56
|
+
writable: true,
|
|
57
|
+
value: void 0
|
|
58
|
+
});
|
|
59
|
+
Object.defineProperty(this, "chorusEffectsSend", {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
configurable: true,
|
|
62
|
+
writable: true,
|
|
63
|
+
value: void 0
|
|
64
|
+
});
|
|
53
65
|
this.noteNumber = noteNumber;
|
|
54
66
|
this.velocity = velocity;
|
|
55
67
|
this.startTime = startTime;
|
|
@@ -205,6 +217,12 @@ export class Midy {
|
|
|
205
217
|
writable: true,
|
|
206
218
|
value: []
|
|
207
219
|
});
|
|
220
|
+
Object.defineProperty(this, "exclusiveClassMap", {
|
|
221
|
+
enumerable: true,
|
|
222
|
+
configurable: true,
|
|
223
|
+
writable: true,
|
|
224
|
+
value: new Map()
|
|
225
|
+
});
|
|
208
226
|
Object.defineProperty(this, "defaultOptions", {
|
|
209
227
|
enumerable: true,
|
|
210
228
|
configurable: true,
|
|
@@ -311,19 +329,25 @@ export class Midy {
|
|
|
311
329
|
const sampleStart = instrumentKey.start;
|
|
312
330
|
const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
|
|
313
331
|
if (isSF3) {
|
|
314
|
-
const sample = instrumentKey.sample
|
|
315
|
-
const
|
|
332
|
+
const sample = instrumentKey.sample;
|
|
333
|
+
const start = sample.byteOffset + sampleStart;
|
|
334
|
+
const end = sample.byteOffset + sampleEnd;
|
|
335
|
+
const buffer = sample.buffer.slice(start, end);
|
|
336
|
+
const audioBuffer = await this.audioContext.decodeAudioData(buffer);
|
|
316
337
|
return audioBuffer;
|
|
317
338
|
}
|
|
318
339
|
else {
|
|
319
|
-
const sample = instrumentKey.sample
|
|
340
|
+
const sample = instrumentKey.sample;
|
|
341
|
+
const start = sample.byteOffset + sampleStart;
|
|
342
|
+
const end = sample.byteOffset + sampleEnd;
|
|
343
|
+
const buffer = sample.buffer.slice(start, end);
|
|
320
344
|
const audioBuffer = new AudioBuffer({
|
|
321
345
|
numberOfChannels: 1,
|
|
322
346
|
length: sample.length,
|
|
323
347
|
sampleRate: instrumentKey.sampleRate,
|
|
324
348
|
});
|
|
325
349
|
const channelData = audioBuffer.getChannelData(0);
|
|
326
|
-
const int16Array = new Int16Array(
|
|
350
|
+
const int16Array = new Int16Array(buffer);
|
|
327
351
|
for (let i = 0; i < int16Array.length; i++) {
|
|
328
352
|
channelData[i] = int16Array[i] / 32768;
|
|
329
353
|
}
|
|
@@ -424,6 +448,7 @@ export class Midy {
|
|
|
424
448
|
if (queueIndex >= this.timeline.length) {
|
|
425
449
|
await Promise.all(this.notePromises);
|
|
426
450
|
this.notePromises = [];
|
|
451
|
+
this.exclusiveClassMap.clear();
|
|
427
452
|
resolve();
|
|
428
453
|
return;
|
|
429
454
|
}
|
|
@@ -439,6 +464,7 @@ export class Midy {
|
|
|
439
464
|
}
|
|
440
465
|
else if (this.isStopping) {
|
|
441
466
|
await this.stopNotes(0, true);
|
|
467
|
+
this.exclusiveClassMap.clear();
|
|
442
468
|
this.notePromises = [];
|
|
443
469
|
resolve();
|
|
444
470
|
this.isStopping = false;
|
|
@@ -447,6 +473,7 @@ export class Midy {
|
|
|
447
473
|
}
|
|
448
474
|
else if (this.isSeeking) {
|
|
449
475
|
this.stopNotes(0, true);
|
|
476
|
+
this.exclusiveClassMap.clear();
|
|
450
477
|
this.startTime = this.audioContext.currentTime;
|
|
451
478
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
452
479
|
offset = this.resumeTime - this.startTime;
|
|
@@ -675,14 +702,14 @@ export class Midy {
|
|
|
675
702
|
return impulse;
|
|
676
703
|
}
|
|
677
704
|
createConvolutionReverb(audioContext, impulse) {
|
|
678
|
-
const
|
|
705
|
+
const input = new GainNode(audioContext);
|
|
679
706
|
const convolverNode = new ConvolverNode(audioContext, {
|
|
680
707
|
buffer: impulse,
|
|
681
708
|
});
|
|
682
|
-
|
|
709
|
+
input.connect(convolverNode);
|
|
683
710
|
return {
|
|
684
|
-
input
|
|
685
|
-
output,
|
|
711
|
+
input,
|
|
712
|
+
output: convolverNode,
|
|
686
713
|
convolverNode,
|
|
687
714
|
};
|
|
688
715
|
}
|
|
@@ -724,7 +751,6 @@ export class Midy {
|
|
|
724
751
|
// M.R.Schroeder, "Natural Sounding Artificial Reverberation", J.Audio Eng. Soc., vol.10, p.219, 1962
|
|
725
752
|
createSchroederReverb(audioContext, combFeedbacks, combDelays, allpassFeedbacks, allpassDelays) {
|
|
726
753
|
const input = new GainNode(audioContext);
|
|
727
|
-
const output = new GainNode(audioContext);
|
|
728
754
|
const mergerGain = new GainNode(audioContext);
|
|
729
755
|
for (let i = 0; i < combDelays.length; i++) {
|
|
730
756
|
const comb = this.createCombFilter(audioContext, input, combDelays[i], combFeedbacks[i]);
|
|
@@ -735,7 +761,7 @@ export class Midy {
|
|
|
735
761
|
const allpass = this.createAllpassFilter(audioContext, (i === 0) ? mergerGain : allpasses.at(-1), allpassDelays[i], allpassFeedbacks[i]);
|
|
736
762
|
allpasses.push(allpass);
|
|
737
763
|
}
|
|
738
|
-
allpasses.at(-1)
|
|
764
|
+
const output = allpasses.at(-1);
|
|
739
765
|
return { input, output };
|
|
740
766
|
}
|
|
741
767
|
createChorusEffect(audioContext) {
|
|
@@ -966,6 +992,20 @@ export class Midy {
|
|
|
966
992
|
}
|
|
967
993
|
note.bufferSource.connect(note.filterNode);
|
|
968
994
|
note.filterNode.connect(note.volumeNode);
|
|
995
|
+
if (0 < channel.reverbSendLevel && 0 < instrumentKey.reverbEffectsSend) {
|
|
996
|
+
note.reverbEffectsSend = new GainNode(this.audioContext, {
|
|
997
|
+
gain: instrumentKey.reverbEffectsSend,
|
|
998
|
+
});
|
|
999
|
+
note.volumeNode.connect(note.reverbEffectsSend);
|
|
1000
|
+
note.reverbEffectsSend.connect(this.reverbEffect.input);
|
|
1001
|
+
}
|
|
1002
|
+
if (0 < channel.chorusSendLevel && 0 < instrumentKey.chorusEffectsSend) {
|
|
1003
|
+
note.chorusEffectsSend = new GainNode(this.audioContext, {
|
|
1004
|
+
gain: instrumentKey.chorusEffectsSend,
|
|
1005
|
+
});
|
|
1006
|
+
note.volumeNode.connect(note.chorusEffectsSend);
|
|
1007
|
+
note.chorusEffectsSend.connect(this.chorusEffect.input);
|
|
1008
|
+
}
|
|
969
1009
|
note.bufferSource.start(startTime);
|
|
970
1010
|
return note;
|
|
971
1011
|
}
|
|
@@ -995,6 +1035,19 @@ export class Midy {
|
|
|
995
1035
|
if (channel.sostenutoPedal) {
|
|
996
1036
|
channel.sostenutoNotes.set(noteNumber, note);
|
|
997
1037
|
}
|
|
1038
|
+
const exclusiveClass = instrumentKey.exclusiveClass;
|
|
1039
|
+
if (exclusiveClass !== 0) {
|
|
1040
|
+
if (this.exclusiveClassMap.has(exclusiveClass)) {
|
|
1041
|
+
const prevEntry = this.exclusiveClassMap.get(exclusiveClass);
|
|
1042
|
+
const [prevNote, prevChannelNumber] = prevEntry;
|
|
1043
|
+
if (!prevNote.ending) {
|
|
1044
|
+
this.scheduleNoteRelease(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
1045
|
+
startTime, undefined, // portamentoNoteNumber
|
|
1046
|
+
true);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
this.exclusiveClassMap.set(exclusiveClass, [note, channelNumber]);
|
|
1050
|
+
}
|
|
998
1051
|
const scheduledNotes = channel.scheduledNotes;
|
|
999
1052
|
if (scheduledNotes.has(noteNumber)) {
|
|
1000
1053
|
scheduledNotes.get(noteNumber).push(note);
|
|
@@ -1007,15 +1060,15 @@ export class Midy {
|
|
|
1007
1060
|
const now = this.audioContext.currentTime;
|
|
1008
1061
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now, portamento);
|
|
1009
1062
|
}
|
|
1010
|
-
stopNote(
|
|
1063
|
+
stopNote(endTime, stopTime, scheduledNotes, index) {
|
|
1011
1064
|
const note = scheduledNotes[index];
|
|
1012
1065
|
note.volumeNode.gain
|
|
1013
|
-
.cancelScheduledValues(
|
|
1014
|
-
.linearRampToValueAtTime(0,
|
|
1066
|
+
.cancelScheduledValues(endTime)
|
|
1067
|
+
.linearRampToValueAtTime(0, stopTime);
|
|
1015
1068
|
note.ending = true;
|
|
1016
1069
|
this.scheduleTask(() => {
|
|
1017
1070
|
note.bufferSource.loop = false;
|
|
1018
|
-
},
|
|
1071
|
+
}, stopTime);
|
|
1019
1072
|
return new Promise((resolve) => {
|
|
1020
1073
|
note.bufferSource.onended = () => {
|
|
1021
1074
|
scheduledNotes[index] = null;
|
|
@@ -1031,12 +1084,18 @@ export class Midy {
|
|
|
1031
1084
|
note.vibratoDepth.disconnect();
|
|
1032
1085
|
note.vibratoLFO.stop();
|
|
1033
1086
|
}
|
|
1087
|
+
if (note.reverbEffectsSend) {
|
|
1088
|
+
note.reverbEffectsSend.disconnect();
|
|
1089
|
+
}
|
|
1090
|
+
if (note.chorusEffectsSend) {
|
|
1091
|
+
note.chorusEffectsSend.disconnect();
|
|
1092
|
+
}
|
|
1034
1093
|
resolve();
|
|
1035
1094
|
};
|
|
1036
|
-
note.bufferSource.stop(
|
|
1095
|
+
note.bufferSource.stop(stopTime);
|
|
1037
1096
|
});
|
|
1038
1097
|
}
|
|
1039
|
-
scheduleNoteRelease(channelNumber, noteNumber, _velocity,
|
|
1098
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, endTime, portamentoNoteNumber, force) {
|
|
1040
1099
|
const channel = this.channels[channelNumber];
|
|
1041
1100
|
if (!force) {
|
|
1042
1101
|
if (channel.sustainPedal)
|
|
@@ -1054,22 +1113,23 @@ export class Midy {
|
|
|
1054
1113
|
if (note.ending)
|
|
1055
1114
|
continue;
|
|
1056
1115
|
if (portamentoNoteNumber === undefined) {
|
|
1057
|
-
const
|
|
1116
|
+
const volRelease = endTime +
|
|
1058
1117
|
note.instrumentKey.volRelease * channel.releaseTime;
|
|
1059
|
-
const modRelease =
|
|
1118
|
+
const modRelease = endTime + note.instrumentKey.modRelease;
|
|
1060
1119
|
note.filterNode.frequency
|
|
1061
|
-
.cancelScheduledValues(
|
|
1120
|
+
.cancelScheduledValues(endTime)
|
|
1062
1121
|
.linearRampToValueAtTime(0, modRelease);
|
|
1063
|
-
|
|
1122
|
+
const stopTime = Math.min(volRelease, modRelease);
|
|
1123
|
+
return this.stopNote(endTime, stopTime, scheduledNotes, i);
|
|
1064
1124
|
}
|
|
1065
1125
|
else {
|
|
1066
|
-
const portamentoTime =
|
|
1126
|
+
const portamentoTime = endTime + channel.portamentoTime;
|
|
1067
1127
|
const detuneChange = (portamentoNoteNumber - noteNumber) * 100;
|
|
1068
1128
|
const detune = note.bufferSource.detune.value + detuneChange;
|
|
1069
1129
|
note.bufferSource.detune
|
|
1070
|
-
.cancelScheduledValues(
|
|
1130
|
+
.cancelScheduledValues(endTime)
|
|
1071
1131
|
.linearRampToValueAtTime(detune, portamentoTime);
|
|
1072
|
-
return this.stopNote(
|
|
1132
|
+
return this.stopNote(endTime, portamentoTime, scheduledNotes, i);
|
|
1073
1133
|
}
|
|
1074
1134
|
}
|
|
1075
1135
|
}
|
|
@@ -1116,7 +1176,7 @@ export class Midy {
|
|
|
1116
1176
|
case 0x90:
|
|
1117
1177
|
return this.noteOn(channelNumber, data1, data2);
|
|
1118
1178
|
case 0xA0:
|
|
1119
|
-
return
|
|
1179
|
+
return this.handlePolyphonicKeyPressure(channelNumber, data1, data2);
|
|
1120
1180
|
case 0xB0:
|
|
1121
1181
|
return this.handleControlChange(channelNumber, data1, data2);
|
|
1122
1182
|
case 0xC0:
|
|
@@ -1311,20 +1371,44 @@ export class Midy {
|
|
|
1311
1371
|
if (0 < reverbSendLevel) {
|
|
1312
1372
|
const now = this.audioContext.currentTime;
|
|
1313
1373
|
channel.reverbSendLevel = reverbSendLevel / 127;
|
|
1314
|
-
reverbEffect.
|
|
1315
|
-
reverbEffect.
|
|
1374
|
+
reverbEffect.input.gain.cancelScheduledValues(now);
|
|
1375
|
+
reverbEffect.input.gain.setValueAtTime(channel.reverbSendLevel, now);
|
|
1316
1376
|
}
|
|
1317
1377
|
else {
|
|
1318
|
-
channel.
|
|
1378
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1379
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1380
|
+
const note = noteList[i];
|
|
1381
|
+
if (!note)
|
|
1382
|
+
continue;
|
|
1383
|
+
if (note.instrumentKey.reverbEffectsSend <= 0)
|
|
1384
|
+
continue;
|
|
1385
|
+
note.reverbEffectsSend.disconnect();
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1319
1388
|
}
|
|
1320
1389
|
}
|
|
1321
1390
|
else {
|
|
1322
1391
|
if (0 < reverbSendLevel) {
|
|
1323
|
-
channel.merger.connect(reverbEffect.input);
|
|
1324
1392
|
const now = this.audioContext.currentTime;
|
|
1393
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1394
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1395
|
+
const note = noteList[i];
|
|
1396
|
+
if (!note)
|
|
1397
|
+
continue;
|
|
1398
|
+
if (note.instrumentKey.reverbEffectsSend <= 0)
|
|
1399
|
+
continue;
|
|
1400
|
+
if (!note.reverbEffectsSend) {
|
|
1401
|
+
note.reverbEffectsSend = new GainNode(this.audioContext, {
|
|
1402
|
+
gain: note.instrumentKey.reverbEffectsSend,
|
|
1403
|
+
});
|
|
1404
|
+
note.volumeNode.connect(note.reverbEffectsSend);
|
|
1405
|
+
}
|
|
1406
|
+
note.reverbEffectsSend.connect(reverbEffect.input);
|
|
1407
|
+
}
|
|
1408
|
+
});
|
|
1325
1409
|
channel.reverbSendLevel = reverbSendLevel / 127;
|
|
1326
|
-
reverbEffect.
|
|
1327
|
-
reverbEffect.
|
|
1410
|
+
reverbEffect.input.gain.cancelScheduledValues(now);
|
|
1411
|
+
reverbEffect.input.gain.setValueAtTime(channel.reverbSendLevel, now);
|
|
1328
1412
|
}
|
|
1329
1413
|
}
|
|
1330
1414
|
}
|
|
@@ -1335,20 +1419,44 @@ export class Midy {
|
|
|
1335
1419
|
if (0 < chorusSendLevel) {
|
|
1336
1420
|
const now = this.audioContext.currentTime;
|
|
1337
1421
|
channel.chorusSendLevel = chorusSendLevel / 127;
|
|
1338
|
-
chorusEffect.
|
|
1339
|
-
chorusEffect.
|
|
1422
|
+
chorusEffect.input.gain.cancelScheduledValues(now);
|
|
1423
|
+
chorusEffect.input.gain.setValueAtTime(channel.chorusSendLevel, now);
|
|
1340
1424
|
}
|
|
1341
1425
|
else {
|
|
1342
|
-
channel.
|
|
1426
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1427
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1428
|
+
const note = noteList[i];
|
|
1429
|
+
if (!note)
|
|
1430
|
+
continue;
|
|
1431
|
+
if (note.instrumentKey.chorusEffectsSend <= 0)
|
|
1432
|
+
continue;
|
|
1433
|
+
note.chorusEffectsSend.disconnect();
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1343
1436
|
}
|
|
1344
1437
|
}
|
|
1345
1438
|
else {
|
|
1346
1439
|
if (0 < chorusSendLevel) {
|
|
1347
|
-
channel.merger.connect(chorusEffect.input);
|
|
1348
1440
|
const now = this.audioContext.currentTime;
|
|
1441
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
1442
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
1443
|
+
const note = noteList[i];
|
|
1444
|
+
if (!note)
|
|
1445
|
+
continue;
|
|
1446
|
+
if (note.instrumentKey.chorusEffectsSend <= 0)
|
|
1447
|
+
continue;
|
|
1448
|
+
if (!note.chorusEffectsSend) {
|
|
1449
|
+
note.chorusEffectsSend = new GainNode(this.audioContext, {
|
|
1450
|
+
gain: note.instrumentKey.chorusEffectsSend,
|
|
1451
|
+
});
|
|
1452
|
+
note.volumeNode.connect(note.chorusEffectsSend);
|
|
1453
|
+
}
|
|
1454
|
+
note.chorusEffectsSend.connect(chorusEffect.input);
|
|
1455
|
+
}
|
|
1456
|
+
});
|
|
1349
1457
|
channel.chorusSendLevel = chorusSendLevel / 127;
|
|
1350
|
-
chorusEffect.
|
|
1351
|
-
chorusEffect.
|
|
1458
|
+
chorusEffect.input.gain.cancelScheduledValues(now);
|
|
1459
|
+
chorusEffect.input.gain.setValueAtTime(channel.chorusSendLevel, now);
|
|
1352
1460
|
}
|
|
1353
1461
|
}
|
|
1354
1462
|
}
|
|
@@ -1781,10 +1889,8 @@ export class Midy {
|
|
|
1781
1889
|
}
|
|
1782
1890
|
setReverbTime(value) {
|
|
1783
1891
|
this.reverb.time = this.getReverbTime(value);
|
|
1784
|
-
const { audioContext,
|
|
1785
|
-
|
|
1786
|
-
channels[i].reverbEffect = options.reverbAlgorithm(audioContext);
|
|
1787
|
-
}
|
|
1892
|
+
const { audioContext, options } = this;
|
|
1893
|
+
this.reverbEffect = options.reverbAlgorithm(audioContext);
|
|
1788
1894
|
}
|
|
1789
1895
|
getReverbTime(value) {
|
|
1790
1896
|
return Math.pow(Math.E, (value - 40) * 0.025);
|
|
@@ -1861,10 +1967,7 @@ export class Midy {
|
|
|
1861
1967
|
const now = this.audioContext.currentTime;
|
|
1862
1968
|
const modRate = this.getChorusModRate(value);
|
|
1863
1969
|
this.chorus.modRate = modRate;
|
|
1864
|
-
|
|
1865
|
-
const lfo = this.channels[i].chorusEffect.lfo;
|
|
1866
|
-
lfo.frequency.setValueAtTime(modRate, now);
|
|
1867
|
-
}
|
|
1970
|
+
this.chorusEffect.lfo.frequency.setValueAtTime(modRate, now);
|
|
1868
1971
|
}
|
|
1869
1972
|
getChorusModRate(value) {
|
|
1870
1973
|
return value * 0.122; // Hz
|
|
@@ -1873,12 +1976,9 @@ export class Midy {
|
|
|
1873
1976
|
const now = this.audioContext.currentTime;
|
|
1874
1977
|
const modDepth = this.getChorusModDepth(value);
|
|
1875
1978
|
this.chorus.modDepth = modDepth;
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
.cancelScheduledValues(now)
|
|
1880
|
-
.setValueAtTime(modDepth / 2, now);
|
|
1881
|
-
}
|
|
1979
|
+
this.chorusEffect.lfoGain.gain
|
|
1980
|
+
.cancelScheduledValues(now)
|
|
1981
|
+
.setValueAtTime(modDepth / 2, now);
|
|
1882
1982
|
}
|
|
1883
1983
|
getChorusModDepth(value) {
|
|
1884
1984
|
return (value + 1) / 3200; // second
|
|
@@ -1887,14 +1987,11 @@ export class Midy {
|
|
|
1887
1987
|
const now = this.audioContext.currentTime;
|
|
1888
1988
|
const feedback = this.getChorusFeedback(value);
|
|
1889
1989
|
this.chorus.feedback = feedback;
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
.cancelScheduledValues(now)
|
|
1896
|
-
.setValueAtTime(feedback, now);
|
|
1897
|
-
}
|
|
1990
|
+
const chorusEffect = this.chorusEffect;
|
|
1991
|
+
for (let i = 0; i < chorusEffect.feedbackGains.length; i++) {
|
|
1992
|
+
chorusEffect.feedbackGains[i].gain
|
|
1993
|
+
.cancelScheduledValues(now)
|
|
1994
|
+
.setValueAtTime(feedback, now);
|
|
1898
1995
|
}
|
|
1899
1996
|
}
|
|
1900
1997
|
getChorusFeedback(value) {
|
|
@@ -1902,15 +1999,28 @@ export class Midy {
|
|
|
1902
1999
|
}
|
|
1903
2000
|
setChorusSendToReverb(value) {
|
|
1904
2001
|
const sendToReverb = this.getChorusSendToReverb(value);
|
|
1905
|
-
|
|
1906
|
-
|
|
2002
|
+
const sendGain = this.chorusEffect.sendGain;
|
|
2003
|
+
if (0 < this.chorus.sendToReverb) {
|
|
1907
2004
|
this.chorus.sendToReverb = sendToReverb;
|
|
1908
|
-
|
|
1909
|
-
.
|
|
1910
|
-
.
|
|
2005
|
+
if (0 < sendToReverb) {
|
|
2006
|
+
const now = this.audioContext.currentTime;
|
|
2007
|
+
sendGain.gain
|
|
2008
|
+
.cancelScheduledValues(now)
|
|
2009
|
+
.setValueAtTime(sendToReverb, now);
|
|
2010
|
+
}
|
|
2011
|
+
else {
|
|
2012
|
+
sendGain.disconnect();
|
|
2013
|
+
}
|
|
1911
2014
|
}
|
|
1912
|
-
else
|
|
1913
|
-
this.
|
|
2015
|
+
else {
|
|
2016
|
+
this.chorus.sendToReverb = sendToReverb;
|
|
2017
|
+
if (0 < sendToReverb) {
|
|
2018
|
+
const now = this.audioContext.currentTime;
|
|
2019
|
+
sendGain.connect(this.reverbEffect.input);
|
|
2020
|
+
sendGain.gain
|
|
2021
|
+
.cancelScheduledValues(now)
|
|
2022
|
+
.setValueAtTime(sendToReverb, now);
|
|
2023
|
+
}
|
|
1914
2024
|
}
|
|
1915
2025
|
}
|
|
1916
2026
|
getChorusSendToReverb(value) {
|