@marmooo/midy 0.2.3 → 0.2.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/midy-GM1.d.ts +22 -4
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +120 -23
- package/esm/midy-GM2.d.ts +34 -24
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +194 -133
- package/esm/midy-GMLite.d.ts +23 -5
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +122 -23
- package/esm/midy.d.ts +37 -23
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +303 -132
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +22 -4
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +120 -23
- package/script/midy-GM2.d.ts +34 -24
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +194 -133
- package/script/midy-GMLite.d.ts +23 -5
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +122 -23
- package/script/midy.d.ts +37 -23
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +303 -132
package/package.json
CHANGED
package/script/midy-GM1.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export class MidyGM1 {
|
|
|
22
22
|
resumeTime: number;
|
|
23
23
|
soundFonts: any[];
|
|
24
24
|
soundFontTable: any[];
|
|
25
|
+
audioBufferCounter: Map<any, any>;
|
|
26
|
+
audioBufferCache: Map<any, any>;
|
|
25
27
|
isPlaying: boolean;
|
|
26
28
|
isPausing: boolean;
|
|
27
29
|
isPaused: boolean;
|
|
@@ -30,7 +32,7 @@ export class MidyGM1 {
|
|
|
30
32
|
timeline: any[];
|
|
31
33
|
instruments: any[];
|
|
32
34
|
notePromises: any[];
|
|
33
|
-
exclusiveClassMap:
|
|
35
|
+
exclusiveClassMap: SparseMap;
|
|
34
36
|
audioContext: any;
|
|
35
37
|
masterVolume: any;
|
|
36
38
|
voiceParamsHandlers: {
|
|
@@ -71,12 +73,13 @@ export class MidyGM1 {
|
|
|
71
73
|
};
|
|
72
74
|
createChannels(audioContext: any): any[];
|
|
73
75
|
createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
|
|
74
|
-
createNoteBufferNode(
|
|
76
|
+
createNoteBufferNode(audioBuffer: any, voiceParams: any): any;
|
|
75
77
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
76
78
|
getQueueIndex(second: any): number;
|
|
77
79
|
playNotes(): Promise<any>;
|
|
78
80
|
ticksToSecond(ticks: any, secondsPerBeat: any): number;
|
|
79
81
|
secondToTicks(second: any, secondsPerBeat: any): number;
|
|
82
|
+
getAudioBufferId(programNumber: any, noteNumber: any, velocity: any): string;
|
|
80
83
|
extractMidiData(midi: any): {
|
|
81
84
|
instruments: Set<any>;
|
|
82
85
|
timeline: any[];
|
|
@@ -90,19 +93,21 @@ export class MidyGM1 {
|
|
|
90
93
|
seekTo(second: any): void;
|
|
91
94
|
calcTotalTime(): number;
|
|
92
95
|
currentTime(): number;
|
|
93
|
-
getActiveNotes(channel: any, time: any):
|
|
96
|
+
getActiveNotes(channel: any, time: any): SparseMap;
|
|
94
97
|
getActiveNote(noteList: any, time: any): any;
|
|
95
98
|
cbToRatio(cb: any): number;
|
|
96
99
|
rateToCent(rate: any): number;
|
|
97
100
|
centToRate(cent: any): number;
|
|
98
101
|
centToHz(cent: any): number;
|
|
99
102
|
calcChannelDetune(channel: any): any;
|
|
100
|
-
|
|
103
|
+
updateChannelDetune(channel: any): void;
|
|
104
|
+
updateDetune(channel: any, note: any): void;
|
|
101
105
|
setVolumeEnvelope(note: any): void;
|
|
102
106
|
setPitchEnvelope(note: any): void;
|
|
103
107
|
clampCutoffFrequency(frequency: any): number;
|
|
104
108
|
setFilterEnvelope(note: any): void;
|
|
105
109
|
startModulation(channel: any, note: any, startTime: any): void;
|
|
110
|
+
getAudioBuffer(program: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
|
|
106
111
|
createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
107
112
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
108
113
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
@@ -185,6 +190,19 @@ export class MidyGM1 {
|
|
|
185
190
|
handleSysEx(data: any): void;
|
|
186
191
|
scheduleTask(callback: any, startTime: any): Promise<any>;
|
|
187
192
|
}
|
|
193
|
+
declare class SparseMap {
|
|
194
|
+
constructor(size: any);
|
|
195
|
+
data: any[];
|
|
196
|
+
activeIndices: any[];
|
|
197
|
+
set(key: any, value: any): void;
|
|
198
|
+
get(key: any): any;
|
|
199
|
+
delete(key: any): boolean;
|
|
200
|
+
has(key: any): boolean;
|
|
201
|
+
get size(): number;
|
|
202
|
+
clear(): void;
|
|
203
|
+
forEach(callback: any): void;
|
|
204
|
+
[Symbol.iterator](): Generator<any[], void, unknown>;
|
|
205
|
+
}
|
|
188
206
|
declare class Note {
|
|
189
207
|
constructor(noteNumber: any, velocity: any, startTime: any, voice: any, voiceParams: any);
|
|
190
208
|
bufferSource: any;
|
package/script/midy-GM1.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAkJA;IAsBE;;;;;;;;;;;;MAYE;IAEF,+BAQC;IA3CD,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,kCAA+B;IAC/B,gCAA6B;IAC7B,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAClB,6BAAuC;IAiBrC,kBAAgC;IAChC,kBAA8C;IAC9C;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,6DA2BC;IAED,8DASC;IAED,2EA+CC;IAED,mCAOC;IAED,0BAoDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MA4EC;IAED,+EAmBC;IAED,qDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,mDASC;IAED,6CAQC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,wCAQC;IAED,4CAKC;IAED,mCAgBC;IAED,kCAqBC;IAED,6CAIC;IAED,mCAuBC;IAED,+DAoBC;IAED,yGAgBC;IAED,gHAuCC;IAED,kGAgDC;IAED,0EAGC;IAED,qFA4BC;IAED,6HAuBC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,mDASC;IAED,gDASC;IAED,gDASC;IAED,qCAMC;IAED,mCAQC;IAED,gCAOC;IAED,+BAMC;IAED;;;;;;;;;;;MA4CC;IAED,oFAMC;IAED,0DA6CC;IAED;;;;;;;;;;;;;MAeC;IAED,+EAWC;IAED,qCAeC;IAED,8DAIC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,wCAWC;IAED,sDAKC;IAED,kFAeC;IAED,2DAMC;IAED,oCAkBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,kDAKC;IAED,wDASC;IAED,8CAKC;IAED,oDAOC;IAED,gDAKC;IAED,sDAOC;IAED,+CAEC;IAED,8CAqBC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAMC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAl6CD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IAUE,0FAMC;IAfD,kBAAa;IACb,gBAAW;IACX,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
|
package/script/midy-GM1.js
CHANGED
|
@@ -3,6 +3,58 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MidyGM1 = void 0;
|
|
4
4
|
const midi_file_1 = require("midi-file");
|
|
5
5
|
const soundfont_parser_1 = require("@marmooo/soundfont-parser");
|
|
6
|
+
// 2-3 times faster than Map
|
|
7
|
+
class SparseMap {
|
|
8
|
+
constructor(size) {
|
|
9
|
+
this.data = new Array(size);
|
|
10
|
+
this.activeIndices = [];
|
|
11
|
+
}
|
|
12
|
+
set(key, value) {
|
|
13
|
+
if (this.data[key] === undefined) {
|
|
14
|
+
this.activeIndices.push(key);
|
|
15
|
+
}
|
|
16
|
+
this.data[key] = value;
|
|
17
|
+
}
|
|
18
|
+
get(key) {
|
|
19
|
+
return this.data[key];
|
|
20
|
+
}
|
|
21
|
+
delete(key) {
|
|
22
|
+
if (this.data[key] !== undefined) {
|
|
23
|
+
this.data[key] = undefined;
|
|
24
|
+
const index = this.activeIndices.indexOf(key);
|
|
25
|
+
if (index !== -1) {
|
|
26
|
+
this.activeIndices.splice(index, 1);
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
has(key) {
|
|
33
|
+
return this.data[key] !== undefined;
|
|
34
|
+
}
|
|
35
|
+
get size() {
|
|
36
|
+
return this.activeIndices.length;
|
|
37
|
+
}
|
|
38
|
+
clear() {
|
|
39
|
+
for (let i = 0; i < this.activeIndices.length; i++) {
|
|
40
|
+
const key = this.activeIndices[i];
|
|
41
|
+
this.data[key] = undefined;
|
|
42
|
+
}
|
|
43
|
+
this.activeIndices = [];
|
|
44
|
+
}
|
|
45
|
+
*[Symbol.iterator]() {
|
|
46
|
+
for (let i = 0; i < this.activeIndices.length; i++) {
|
|
47
|
+
const key = this.activeIndices[i];
|
|
48
|
+
yield [key, this.data[key]];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
forEach(callback) {
|
|
52
|
+
for (let i = 0; i < this.activeIndices.length; i++) {
|
|
53
|
+
const key = this.activeIndices[i];
|
|
54
|
+
callback(this.data[key], key, this);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
6
58
|
class Note {
|
|
7
59
|
constructor(noteNumber, velocity, startTime, voice, voiceParams) {
|
|
8
60
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -181,6 +233,18 @@ class MidyGM1 {
|
|
|
181
233
|
writable: true,
|
|
182
234
|
value: this.initSoundFontTable()
|
|
183
235
|
});
|
|
236
|
+
Object.defineProperty(this, "audioBufferCounter", {
|
|
237
|
+
enumerable: true,
|
|
238
|
+
configurable: true,
|
|
239
|
+
writable: true,
|
|
240
|
+
value: new Map()
|
|
241
|
+
});
|
|
242
|
+
Object.defineProperty(this, "audioBufferCache", {
|
|
243
|
+
enumerable: true,
|
|
244
|
+
configurable: true,
|
|
245
|
+
writable: true,
|
|
246
|
+
value: new Map()
|
|
247
|
+
});
|
|
184
248
|
Object.defineProperty(this, "isPlaying", {
|
|
185
249
|
enumerable: true,
|
|
186
250
|
configurable: true,
|
|
@@ -233,7 +297,7 @@ class MidyGM1 {
|
|
|
233
297
|
enumerable: true,
|
|
234
298
|
configurable: true,
|
|
235
299
|
writable: true,
|
|
236
|
-
value: new
|
|
300
|
+
value: new SparseMap(128)
|
|
237
301
|
});
|
|
238
302
|
this.audioContext = audioContext;
|
|
239
303
|
this.masterVolume = new GainNode(audioContext);
|
|
@@ -246,7 +310,7 @@ class MidyGM1 {
|
|
|
246
310
|
initSoundFontTable() {
|
|
247
311
|
const table = new Array(128);
|
|
248
312
|
for (let i = 0; i < 128; i++) {
|
|
249
|
-
table[i] = new
|
|
313
|
+
table[i] = new SparseMap(128);
|
|
250
314
|
}
|
|
251
315
|
return table;
|
|
252
316
|
}
|
|
@@ -299,7 +363,7 @@ class MidyGM1 {
|
|
|
299
363
|
...this.constructor.channelSettings,
|
|
300
364
|
state: new ControllerState(),
|
|
301
365
|
...this.setChannelAudioNodes(audioContext),
|
|
302
|
-
scheduledNotes: new
|
|
366
|
+
scheduledNotes: new SparseMap(128),
|
|
303
367
|
};
|
|
304
368
|
});
|
|
305
369
|
return channels;
|
|
@@ -333,9 +397,8 @@ class MidyGM1 {
|
|
|
333
397
|
return audioBuffer;
|
|
334
398
|
}
|
|
335
399
|
}
|
|
336
|
-
|
|
400
|
+
createNoteBufferNode(audioBuffer, voiceParams) {
|
|
337
401
|
const bufferSource = new AudioBufferSourceNode(this.audioContext);
|
|
338
|
-
const audioBuffer = await this.createNoteBuffer(voiceParams, isSF3);
|
|
339
402
|
bufferSource.buffer = audioBuffer;
|
|
340
403
|
bufferSource.loop = voiceParams.sampleModes % 2 !== 0;
|
|
341
404
|
if (bufferSource.loop) {
|
|
@@ -400,6 +463,7 @@ class MidyGM1 {
|
|
|
400
463
|
await Promise.all(this.notePromises);
|
|
401
464
|
this.notePromises = [];
|
|
402
465
|
this.exclusiveClassMap.clear();
|
|
466
|
+
this.audioBufferCache.clear();
|
|
403
467
|
resolve();
|
|
404
468
|
return;
|
|
405
469
|
}
|
|
@@ -415,8 +479,9 @@ class MidyGM1 {
|
|
|
415
479
|
}
|
|
416
480
|
else if (this.isStopping) {
|
|
417
481
|
await this.stopNotes(0, true);
|
|
418
|
-
this.exclusiveClassMap.clear();
|
|
419
482
|
this.notePromises = [];
|
|
483
|
+
this.exclusiveClassMap.clear();
|
|
484
|
+
this.audioBufferCache.clear();
|
|
420
485
|
resolve();
|
|
421
486
|
this.isStopping = false;
|
|
422
487
|
this.isPaused = false;
|
|
@@ -447,6 +512,9 @@ class MidyGM1 {
|
|
|
447
512
|
secondToTicks(second, secondsPerBeat) {
|
|
448
513
|
return second * this.ticksPerBeat / secondsPerBeat;
|
|
449
514
|
}
|
|
515
|
+
getAudioBufferId(programNumber, noteNumber, velocity) {
|
|
516
|
+
return `${programNumber}:${noteNumber}:${velocity}`;
|
|
517
|
+
}
|
|
450
518
|
extractMidiData(midi) {
|
|
451
519
|
const instruments = new Set();
|
|
452
520
|
const timeline = [];
|
|
@@ -467,6 +535,8 @@ class MidyGM1 {
|
|
|
467
535
|
switch (event.type) {
|
|
468
536
|
case "noteOn": {
|
|
469
537
|
const channel = tmpChannels[event.channel];
|
|
538
|
+
const audioBufferId = this.getAudioBufferId(channel.programNumber, event.noteNumber, event.velocity);
|
|
539
|
+
this.audioBufferCounter.set(audioBufferId, (this.audioBufferCounter.get(audioBufferId) ?? 0) + 1);
|
|
470
540
|
if (channel.programNumber < 0) {
|
|
471
541
|
instruments.add(`${channel.bank}:0`);
|
|
472
542
|
channel.programNumber = 0;
|
|
@@ -483,6 +553,10 @@ class MidyGM1 {
|
|
|
483
553
|
timeline.push(event);
|
|
484
554
|
}
|
|
485
555
|
}
|
|
556
|
+
for (const [audioBufferId, count] of this.audioBufferCounter) {
|
|
557
|
+
if (count === 1)
|
|
558
|
+
this.audioBufferCounter.delete(audioBufferId);
|
|
559
|
+
}
|
|
486
560
|
const priority = {
|
|
487
561
|
controller: 0,
|
|
488
562
|
sysEx: 1,
|
|
@@ -573,7 +647,7 @@ class MidyGM1 {
|
|
|
573
647
|
return this.resumeTime + now - this.startTime - this.startDelay;
|
|
574
648
|
}
|
|
575
649
|
getActiveNotes(channel, time) {
|
|
576
|
-
const activeNotes = new
|
|
650
|
+
const activeNotes = new SparseMap(128);
|
|
577
651
|
channel.scheduledNotes.forEach((noteList) => {
|
|
578
652
|
const activeNote = this.getActiveNote(noteList, time);
|
|
579
653
|
if (activeNote) {
|
|
@@ -612,19 +686,22 @@ class MidyGM1 {
|
|
|
612
686
|
const pitch = pitchWheel * pitchWheelSensitivity;
|
|
613
687
|
return tuning + pitch;
|
|
614
688
|
}
|
|
615
|
-
|
|
616
|
-
const now = this.audioContext.currentTime;
|
|
689
|
+
updateChannelDetune(channel) {
|
|
617
690
|
channel.scheduledNotes.forEach((noteList) => {
|
|
618
691
|
for (let i = 0; i < noteList.length; i++) {
|
|
619
692
|
const note = noteList[i];
|
|
620
693
|
if (!note)
|
|
621
694
|
continue;
|
|
622
|
-
note
|
|
623
|
-
.cancelScheduledValues(now)
|
|
624
|
-
.setValueAtTime(channel.detune, now);
|
|
695
|
+
this.updateDetune(channel, note);
|
|
625
696
|
}
|
|
626
697
|
});
|
|
627
698
|
}
|
|
699
|
+
updateDetune(channel, note) {
|
|
700
|
+
const now = this.audioContext.currentTime;
|
|
701
|
+
note.bufferSource.detune
|
|
702
|
+
.cancelScheduledValues(now)
|
|
703
|
+
.setValueAtTime(channel.detune, now);
|
|
704
|
+
}
|
|
628
705
|
setVolumeEnvelope(note) {
|
|
629
706
|
const now = this.audioContext.currentTime;
|
|
630
707
|
const { voiceParams, startTime } = note;
|
|
@@ -712,11 +789,31 @@ class MidyGM1 {
|
|
|
712
789
|
note.modulationLFO.connect(note.volumeDepth);
|
|
713
790
|
note.volumeDepth.connect(note.volumeEnvelopeNode.gain);
|
|
714
791
|
}
|
|
792
|
+
async getAudioBuffer(program, noteNumber, velocity, voiceParams, isSF3) {
|
|
793
|
+
const audioBufferId = this.getAudioBufferId(program, noteNumber, velocity);
|
|
794
|
+
const cache = this.audioBufferCache.get(audioBufferId);
|
|
795
|
+
if (cache) {
|
|
796
|
+
cache.counter += 1;
|
|
797
|
+
if (cache.maxCount <= cache.counter) {
|
|
798
|
+
this.audioBufferCache.delete(audioBufferId);
|
|
799
|
+
}
|
|
800
|
+
return cache.audioBuffer;
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
const maxCount = this.audioBufferCounter.get(audioBufferId) ?? 0;
|
|
804
|
+
const audioBuffer = await this.createNoteBuffer(voiceParams, isSF3);
|
|
805
|
+
const cache = { audioBuffer, maxCount, counter: 1 };
|
|
806
|
+
this.audioBufferCache.set(audioBufferId, cache);
|
|
807
|
+
return audioBuffer;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
715
810
|
async createNote(channel, voice, noteNumber, velocity, startTime, isSF3) {
|
|
716
811
|
const state = channel.state;
|
|
717
|
-
const
|
|
812
|
+
const controllerState = this.getControllerState(channel, noteNumber, velocity);
|
|
813
|
+
const voiceParams = voice.getAllParams(controllerState);
|
|
718
814
|
const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
|
|
719
|
-
|
|
815
|
+
const audioBuffer = await this.getAudioBuffer(channel.program, noteNumber, velocity, voiceParams, isSF3);
|
|
816
|
+
note.bufferSource = this.createNoteBufferNode(audioBuffer, voiceParams);
|
|
720
817
|
note.volumeEnvelopeNode = new GainNode(this.audioContext);
|
|
721
818
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
722
819
|
type: "lowpass",
|
|
@@ -740,10 +837,10 @@ class MidyGM1 {
|
|
|
740
837
|
if (soundFontIndex === undefined)
|
|
741
838
|
return;
|
|
742
839
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
743
|
-
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
744
840
|
const voice = soundFont.getVoice(bankNumber, channel.program, noteNumber, velocity);
|
|
745
841
|
if (!voice)
|
|
746
842
|
return;
|
|
843
|
+
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
747
844
|
const note = await this.createNote(channel, voice, noteNumber, velocity, startTime, isSF3);
|
|
748
845
|
note.volumeEnvelopeNode.connect(channel.gainL);
|
|
749
846
|
note.volumeEnvelopeNode.connect(channel.gainR);
|
|
@@ -877,7 +974,7 @@ class MidyGM1 {
|
|
|
877
974
|
const next = (value - 8192) / 8192;
|
|
878
975
|
state.pitchWheel = value / 16383;
|
|
879
976
|
channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
|
|
880
|
-
this.
|
|
977
|
+
this.updateChannelDetune(channel);
|
|
881
978
|
this.applyVoiceParams(channel, 14);
|
|
882
979
|
}
|
|
883
980
|
setModLfoToPitch(channel, note) {
|
|
@@ -975,7 +1072,7 @@ class MidyGM1 {
|
|
|
975
1072
|
const freqVibLFO = note.voiceParams.freqVibLFO;
|
|
976
1073
|
note.vibratoLFO.frequency
|
|
977
1074
|
.cancelScheduledValues(now)
|
|
978
|
-
.setValueAtTime(freqVibLFO * channel.state.vibratoRate, now);
|
|
1075
|
+
.setValueAtTime(freqVibLFO * channel.state.vibratoRate * 2, now);
|
|
979
1076
|
}
|
|
980
1077
|
},
|
|
981
1078
|
};
|
|
@@ -1015,7 +1112,7 @@ class MidyGM1 {
|
|
|
1015
1112
|
if (key in voiceParams)
|
|
1016
1113
|
noteVoiceParams[key] = voiceParams[key];
|
|
1017
1114
|
}
|
|
1018
|
-
this.setFilterEnvelope(
|
|
1115
|
+
this.setFilterEnvelope(note);
|
|
1019
1116
|
this.setPitchEnvelope(note);
|
|
1020
1117
|
}
|
|
1021
1118
|
else if (volumeEnvelopeKeySet.has(key)) {
|
|
@@ -1055,7 +1152,7 @@ class MidyGM1 {
|
|
|
1055
1152
|
if (handler) {
|
|
1056
1153
|
handler.call(this, channelNumber, value);
|
|
1057
1154
|
const channel = this.channels[channelNumber];
|
|
1058
|
-
this.applyVoiceParams(channel,
|
|
1155
|
+
this.applyVoiceParams(channel, controllerType + 128);
|
|
1059
1156
|
}
|
|
1060
1157
|
else {
|
|
1061
1158
|
console.warn(`Unsupported Control change: controllerType=${controllerType} value=${value}`);
|
|
@@ -1194,7 +1291,7 @@ class MidyGM1 {
|
|
|
1194
1291
|
const next = value / 128;
|
|
1195
1292
|
state.pitchWheelSensitivity = next;
|
|
1196
1293
|
channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
|
|
1197
|
-
this.
|
|
1294
|
+
this.updateChannelDetune(channel);
|
|
1198
1295
|
this.applyVoiceParams(channel, 16);
|
|
1199
1296
|
}
|
|
1200
1297
|
handleFineTuningRPN(channelNumber) {
|
|
@@ -1209,7 +1306,7 @@ class MidyGM1 {
|
|
|
1209
1306
|
const next = (value - 8192) / 8.192; // cent
|
|
1210
1307
|
channel.fineTuning = next;
|
|
1211
1308
|
channel.detune += next - prev;
|
|
1212
|
-
this.
|
|
1309
|
+
this.updateChannelDetune(channel);
|
|
1213
1310
|
}
|
|
1214
1311
|
handleCoarseTuningRPN(channelNumber) {
|
|
1215
1312
|
const channel = this.channels[channelNumber];
|
|
@@ -1223,7 +1320,7 @@ class MidyGM1 {
|
|
|
1223
1320
|
const next = (value - 64) * 100; // cent
|
|
1224
1321
|
channel.coarseTuning = next;
|
|
1225
1322
|
channel.detune += next - prev;
|
|
1226
|
-
this.
|
|
1323
|
+
this.updateChannelDetune(channel);
|
|
1227
1324
|
}
|
|
1228
1325
|
allSoundOff(channelNumber) {
|
|
1229
1326
|
return this.stopChannelNotes(channelNumber, 0, true);
|
|
@@ -1239,7 +1336,7 @@ class MidyGM1 {
|
|
|
1239
1336
|
const state = channel.state;
|
|
1240
1337
|
for (let i = 0; i < stateTypes.length; i++) {
|
|
1241
1338
|
const type = stateTypes[i];
|
|
1242
|
-
state[type] = defaultControllerState[type];
|
|
1339
|
+
state[type] = defaultControllerState[type].defaultValue;
|
|
1243
1340
|
}
|
|
1244
1341
|
const settingTypes = [
|
|
1245
1342
|
"rpnMSB",
|
package/script/midy-GM2.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export class MidyGM2 {
|
|
|
2
2
|
static channelSettings: {
|
|
3
3
|
currentBufferSource: null;
|
|
4
4
|
detune: number;
|
|
5
|
-
scaleOctaveTuningTable:
|
|
6
|
-
|
|
5
|
+
scaleOctaveTuningTable: Int8Array<ArrayBuffer>;
|
|
6
|
+
channelPressureTable: Uint8Array<ArrayBuffer>;
|
|
7
7
|
keyBasedInstrumentControlTable: Int8Array<ArrayBuffer>;
|
|
8
8
|
program: number;
|
|
9
9
|
bank: number;
|
|
@@ -17,14 +17,6 @@ export class MidyGM2 {
|
|
|
17
17
|
coarseTuning: number;
|
|
18
18
|
modulationDepthRange: number;
|
|
19
19
|
};
|
|
20
|
-
static controllerDestinationSettings: {
|
|
21
|
-
pitchControl: number;
|
|
22
|
-
filterCutoffControl: number;
|
|
23
|
-
amplitudeControl: number;
|
|
24
|
-
lfoPitchDepth: number;
|
|
25
|
-
lfoFilterDepth: number;
|
|
26
|
-
lfoAmplitudeDepth: number;
|
|
27
|
-
};
|
|
28
20
|
constructor(audioContext: any, options?: {
|
|
29
21
|
reverbAlgorithm: (audioContext: any) => {
|
|
30
22
|
input: any;
|
|
@@ -55,6 +47,8 @@ export class MidyGM2 {
|
|
|
55
47
|
resumeTime: number;
|
|
56
48
|
soundFonts: any[];
|
|
57
49
|
soundFontTable: any[];
|
|
50
|
+
audioBufferCounter: Map<any, any>;
|
|
51
|
+
audioBufferCache: Map<any, any>;
|
|
58
52
|
isPlaying: boolean;
|
|
59
53
|
isPausing: boolean;
|
|
60
54
|
isPaused: boolean;
|
|
@@ -63,7 +57,7 @@ export class MidyGM2 {
|
|
|
63
57
|
timeline: any[];
|
|
64
58
|
instruments: any[];
|
|
65
59
|
notePromises: any[];
|
|
66
|
-
exclusiveClassMap:
|
|
60
|
+
exclusiveClassMap: SparseMap;
|
|
67
61
|
defaultOptions: {
|
|
68
62
|
reverbAlgorithm: (audioContext: any) => {
|
|
69
63
|
input: any;
|
|
@@ -141,13 +135,14 @@ export class MidyGM2 {
|
|
|
141
135
|
};
|
|
142
136
|
createChannels(audioContext: any): any[];
|
|
143
137
|
createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
|
|
144
|
-
createNoteBufferNode(
|
|
138
|
+
createNoteBufferNode(audioBuffer: any, voiceParams: any): any;
|
|
145
139
|
findPortamentoTarget(queueIndex: any): any;
|
|
146
140
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
147
141
|
getQueueIndex(second: any): number;
|
|
148
142
|
playNotes(): Promise<any>;
|
|
149
143
|
ticksToSecond(ticks: any, secondsPerBeat: any): number;
|
|
150
144
|
secondToTicks(second: any, secondsPerBeat: any): number;
|
|
145
|
+
getAudioBufferId(programNumber: any, noteNumber: any, velocity: any): string;
|
|
151
146
|
extractMidiData(midi: any): {
|
|
152
147
|
instruments: Set<any>;
|
|
153
148
|
timeline: any[];
|
|
@@ -161,7 +156,7 @@ export class MidyGM2 {
|
|
|
161
156
|
seekTo(second: any): void;
|
|
162
157
|
calcTotalTime(): number;
|
|
163
158
|
currentTime(): number;
|
|
164
|
-
getActiveNotes(channel: any, time: any):
|
|
159
|
+
getActiveNotes(channel: any, time: any): SparseMap;
|
|
165
160
|
getActiveNote(noteList: any, time: any): any;
|
|
166
161
|
createConvolutionReverbImpulse(audioContext: any, decay: any, preDecay: any): any;
|
|
167
162
|
createConvolutionReverb(audioContext: any, impulse: any): {
|
|
@@ -191,16 +186,18 @@ export class MidyGM2 {
|
|
|
191
186
|
centToHz(cent: any): number;
|
|
192
187
|
calcChannelDetune(channel: any): any;
|
|
193
188
|
calcNoteDetune(channel: any, note: any): any;
|
|
194
|
-
|
|
189
|
+
updateChannelDetune(channel: any): void;
|
|
190
|
+
updateDetune(channel: any, note: any, pressure: any): void;
|
|
195
191
|
getPortamentoTime(channel: any): number;
|
|
196
192
|
setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
|
|
197
|
-
setVolumeEnvelope(
|
|
193
|
+
setVolumeEnvelope(note: any, pressure: any): void;
|
|
198
194
|
setPitchEnvelope(note: any): void;
|
|
199
195
|
clampCutoffFrequency(frequency: any): number;
|
|
200
196
|
setPortamentoStartFilterEnvelope(channel: any, note: any): void;
|
|
201
|
-
setFilterEnvelope(channel: any, note: any): void;
|
|
197
|
+
setFilterEnvelope(channel: any, note: any, pressure: any): void;
|
|
202
198
|
startModulation(channel: any, note: any, startTime: any): void;
|
|
203
199
|
startVibrato(channel: any, note: any, startTime: any): void;
|
|
200
|
+
getAudioBuffer(program: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
|
|
204
201
|
createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
|
|
205
202
|
calcBank(channel: any, channelNumber: any): any;
|
|
206
203
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
|
|
@@ -213,17 +210,17 @@ export class MidyGM2 {
|
|
|
213
210
|
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
214
211
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
215
212
|
handleChannelPressure(channelNumber: any, value: any): void;
|
|
216
|
-
setChannelPressure(channel: any, note: any): void;
|
|
217
213
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
218
214
|
setPitchBend(channelNumber: any, value: any): void;
|
|
219
|
-
setModLfoToPitch(channel: any, note: any): void;
|
|
215
|
+
setModLfoToPitch(channel: any, note: any, pressure: any): void;
|
|
220
216
|
setVibLfoToPitch(channel: any, note: any): void;
|
|
221
|
-
setModLfoToFilterFc(
|
|
222
|
-
setModLfoToVolume(
|
|
217
|
+
setModLfoToFilterFc(note: any, pressure: any): void;
|
|
218
|
+
setModLfoToVolume(note: any, pressure: any): void;
|
|
223
219
|
setReverbEffectsSend(channel: any, note: any, prevValue: any): void;
|
|
224
220
|
setChorusEffectsSend(channel: any, note: any, prevValue: any): void;
|
|
225
221
|
setDelayModLFO(note: any): void;
|
|
226
222
|
setFreqModLFO(note: any): void;
|
|
223
|
+
setFreqVibLFO(channel: any, note: any): void;
|
|
227
224
|
createVoiceParamsHandlers(): {
|
|
228
225
|
modLfoToPitch: (channel: any, note: any, _prevValue: any) => void;
|
|
229
226
|
vibLfoToPitch: (channel: any, note: any, _prevValue: any) => void;
|
|
@@ -311,7 +308,7 @@ export class MidyGM2 {
|
|
|
311
308
|
handleUniversalNonRealTimeExclusiveMessage(data: any): void;
|
|
312
309
|
GM1SystemOn(): void;
|
|
313
310
|
GM2SystemOn(): void;
|
|
314
|
-
handleUniversalRealTimeExclusiveMessage(data: any):
|
|
311
|
+
handleUniversalRealTimeExclusiveMessage(data: any): any;
|
|
315
312
|
handleMasterVolumeSysEx(data: any): void;
|
|
316
313
|
setMasterVolume(volume: any): void;
|
|
317
314
|
handleMasterFineTuningSysEx(data: any): void;
|
|
@@ -337,18 +334,31 @@ export class MidyGM2 {
|
|
|
337
334
|
setChorusSendToReverb(value: any): void;
|
|
338
335
|
getChorusSendToReverb(value: any): number;
|
|
339
336
|
getChannelBitmap(data: any): any[];
|
|
340
|
-
handleScaleOctaveTuning1ByteFormatSysEx(data: any): void;
|
|
337
|
+
handleScaleOctaveTuning1ByteFormatSysEx(data: any, realtime: any): void;
|
|
341
338
|
applyDestinationSettings(channel: any, note: any, table: any): void;
|
|
342
|
-
handleChannelPressureSysEx(data: any): void;
|
|
339
|
+
handleChannelPressureSysEx(data: any, tableName: any): void;
|
|
343
340
|
initControlTable(): Uint8Array<ArrayBuffer>;
|
|
344
341
|
applyControlTable(channel: any, controllerType: any): void;
|
|
345
342
|
handleControlChangeSysEx(data: any): void;
|
|
346
343
|
getKeyBasedInstrumentControlValue(channel: any, keyNumber: any, controllerType: any): number;
|
|
347
344
|
handleKeyBasedInstrumentControlSysEx(data: any): void;
|
|
348
345
|
handleExclusiveMessage(data: any): void;
|
|
349
|
-
handleSysEx(data: any):
|
|
346
|
+
handleSysEx(data: any): any;
|
|
350
347
|
scheduleTask(callback: any, startTime: any): Promise<any>;
|
|
351
348
|
}
|
|
349
|
+
declare class SparseMap {
|
|
350
|
+
constructor(size: any);
|
|
351
|
+
data: any[];
|
|
352
|
+
activeIndices: any[];
|
|
353
|
+
set(key: any, value: any): void;
|
|
354
|
+
get(key: any): any;
|
|
355
|
+
delete(key: any): boolean;
|
|
356
|
+
has(key: any): boolean;
|
|
357
|
+
get size(): number;
|
|
358
|
+
clear(): void;
|
|
359
|
+
forEach(callback: any): void;
|
|
360
|
+
[Symbol.iterator](): Generator<any[], void, unknown>;
|
|
361
|
+
}
|
|
352
362
|
declare class Note {
|
|
353
363
|
constructor(noteNumber: any, velocity: any, startTime: any, voice: any, voiceParams: any);
|
|
354
364
|
bufferSource: any;
|
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":"
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}
|