@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/esm/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/esm/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/esm/midy-GM1.js
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
import { parseMidi } from "midi-file";
|
|
2
2
|
import { parse, SoundFont } from "@marmooo/soundfont-parser";
|
|
3
|
+
// 2-3 times faster than Map
|
|
4
|
+
class SparseMap {
|
|
5
|
+
constructor(size) {
|
|
6
|
+
this.data = new Array(size);
|
|
7
|
+
this.activeIndices = [];
|
|
8
|
+
}
|
|
9
|
+
set(key, value) {
|
|
10
|
+
if (this.data[key] === undefined) {
|
|
11
|
+
this.activeIndices.push(key);
|
|
12
|
+
}
|
|
13
|
+
this.data[key] = value;
|
|
14
|
+
}
|
|
15
|
+
get(key) {
|
|
16
|
+
return this.data[key];
|
|
17
|
+
}
|
|
18
|
+
delete(key) {
|
|
19
|
+
if (this.data[key] !== undefined) {
|
|
20
|
+
this.data[key] = undefined;
|
|
21
|
+
const index = this.activeIndices.indexOf(key);
|
|
22
|
+
if (index !== -1) {
|
|
23
|
+
this.activeIndices.splice(index, 1);
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
has(key) {
|
|
30
|
+
return this.data[key] !== undefined;
|
|
31
|
+
}
|
|
32
|
+
get size() {
|
|
33
|
+
return this.activeIndices.length;
|
|
34
|
+
}
|
|
35
|
+
clear() {
|
|
36
|
+
for (let i = 0; i < this.activeIndices.length; i++) {
|
|
37
|
+
const key = this.activeIndices[i];
|
|
38
|
+
this.data[key] = undefined;
|
|
39
|
+
}
|
|
40
|
+
this.activeIndices = [];
|
|
41
|
+
}
|
|
42
|
+
*[Symbol.iterator]() {
|
|
43
|
+
for (let i = 0; i < this.activeIndices.length; i++) {
|
|
44
|
+
const key = this.activeIndices[i];
|
|
45
|
+
yield [key, this.data[key]];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
forEach(callback) {
|
|
49
|
+
for (let i = 0; i < this.activeIndices.length; i++) {
|
|
50
|
+
const key = this.activeIndices[i];
|
|
51
|
+
callback(this.data[key], key, this);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
3
55
|
class Note {
|
|
4
56
|
constructor(noteNumber, velocity, startTime, voice, voiceParams) {
|
|
5
57
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -178,6 +230,18 @@ export class MidyGM1 {
|
|
|
178
230
|
writable: true,
|
|
179
231
|
value: this.initSoundFontTable()
|
|
180
232
|
});
|
|
233
|
+
Object.defineProperty(this, "audioBufferCounter", {
|
|
234
|
+
enumerable: true,
|
|
235
|
+
configurable: true,
|
|
236
|
+
writable: true,
|
|
237
|
+
value: new Map()
|
|
238
|
+
});
|
|
239
|
+
Object.defineProperty(this, "audioBufferCache", {
|
|
240
|
+
enumerable: true,
|
|
241
|
+
configurable: true,
|
|
242
|
+
writable: true,
|
|
243
|
+
value: new Map()
|
|
244
|
+
});
|
|
181
245
|
Object.defineProperty(this, "isPlaying", {
|
|
182
246
|
enumerable: true,
|
|
183
247
|
configurable: true,
|
|
@@ -230,7 +294,7 @@ export class MidyGM1 {
|
|
|
230
294
|
enumerable: true,
|
|
231
295
|
configurable: true,
|
|
232
296
|
writable: true,
|
|
233
|
-
value: new
|
|
297
|
+
value: new SparseMap(128)
|
|
234
298
|
});
|
|
235
299
|
this.audioContext = audioContext;
|
|
236
300
|
this.masterVolume = new GainNode(audioContext);
|
|
@@ -243,7 +307,7 @@ export class MidyGM1 {
|
|
|
243
307
|
initSoundFontTable() {
|
|
244
308
|
const table = new Array(128);
|
|
245
309
|
for (let i = 0; i < 128; i++) {
|
|
246
|
-
table[i] = new
|
|
310
|
+
table[i] = new SparseMap(128);
|
|
247
311
|
}
|
|
248
312
|
return table;
|
|
249
313
|
}
|
|
@@ -296,7 +360,7 @@ export class MidyGM1 {
|
|
|
296
360
|
...this.constructor.channelSettings,
|
|
297
361
|
state: new ControllerState(),
|
|
298
362
|
...this.setChannelAudioNodes(audioContext),
|
|
299
|
-
scheduledNotes: new
|
|
363
|
+
scheduledNotes: new SparseMap(128),
|
|
300
364
|
};
|
|
301
365
|
});
|
|
302
366
|
return channels;
|
|
@@ -330,9 +394,8 @@ export class MidyGM1 {
|
|
|
330
394
|
return audioBuffer;
|
|
331
395
|
}
|
|
332
396
|
}
|
|
333
|
-
|
|
397
|
+
createNoteBufferNode(audioBuffer, voiceParams) {
|
|
334
398
|
const bufferSource = new AudioBufferSourceNode(this.audioContext);
|
|
335
|
-
const audioBuffer = await this.createNoteBuffer(voiceParams, isSF3);
|
|
336
399
|
bufferSource.buffer = audioBuffer;
|
|
337
400
|
bufferSource.loop = voiceParams.sampleModes % 2 !== 0;
|
|
338
401
|
if (bufferSource.loop) {
|
|
@@ -397,6 +460,7 @@ export class MidyGM1 {
|
|
|
397
460
|
await Promise.all(this.notePromises);
|
|
398
461
|
this.notePromises = [];
|
|
399
462
|
this.exclusiveClassMap.clear();
|
|
463
|
+
this.audioBufferCache.clear();
|
|
400
464
|
resolve();
|
|
401
465
|
return;
|
|
402
466
|
}
|
|
@@ -412,8 +476,9 @@ export class MidyGM1 {
|
|
|
412
476
|
}
|
|
413
477
|
else if (this.isStopping) {
|
|
414
478
|
await this.stopNotes(0, true);
|
|
415
|
-
this.exclusiveClassMap.clear();
|
|
416
479
|
this.notePromises = [];
|
|
480
|
+
this.exclusiveClassMap.clear();
|
|
481
|
+
this.audioBufferCache.clear();
|
|
417
482
|
resolve();
|
|
418
483
|
this.isStopping = false;
|
|
419
484
|
this.isPaused = false;
|
|
@@ -444,6 +509,9 @@ export class MidyGM1 {
|
|
|
444
509
|
secondToTicks(second, secondsPerBeat) {
|
|
445
510
|
return second * this.ticksPerBeat / secondsPerBeat;
|
|
446
511
|
}
|
|
512
|
+
getAudioBufferId(programNumber, noteNumber, velocity) {
|
|
513
|
+
return `${programNumber}:${noteNumber}:${velocity}`;
|
|
514
|
+
}
|
|
447
515
|
extractMidiData(midi) {
|
|
448
516
|
const instruments = new Set();
|
|
449
517
|
const timeline = [];
|
|
@@ -464,6 +532,8 @@ export class MidyGM1 {
|
|
|
464
532
|
switch (event.type) {
|
|
465
533
|
case "noteOn": {
|
|
466
534
|
const channel = tmpChannels[event.channel];
|
|
535
|
+
const audioBufferId = this.getAudioBufferId(channel.programNumber, event.noteNumber, event.velocity);
|
|
536
|
+
this.audioBufferCounter.set(audioBufferId, (this.audioBufferCounter.get(audioBufferId) ?? 0) + 1);
|
|
467
537
|
if (channel.programNumber < 0) {
|
|
468
538
|
instruments.add(`${channel.bank}:0`);
|
|
469
539
|
channel.programNumber = 0;
|
|
@@ -480,6 +550,10 @@ export class MidyGM1 {
|
|
|
480
550
|
timeline.push(event);
|
|
481
551
|
}
|
|
482
552
|
}
|
|
553
|
+
for (const [audioBufferId, count] of this.audioBufferCounter) {
|
|
554
|
+
if (count === 1)
|
|
555
|
+
this.audioBufferCounter.delete(audioBufferId);
|
|
556
|
+
}
|
|
483
557
|
const priority = {
|
|
484
558
|
controller: 0,
|
|
485
559
|
sysEx: 1,
|
|
@@ -570,7 +644,7 @@ export class MidyGM1 {
|
|
|
570
644
|
return this.resumeTime + now - this.startTime - this.startDelay;
|
|
571
645
|
}
|
|
572
646
|
getActiveNotes(channel, time) {
|
|
573
|
-
const activeNotes = new
|
|
647
|
+
const activeNotes = new SparseMap(128);
|
|
574
648
|
channel.scheduledNotes.forEach((noteList) => {
|
|
575
649
|
const activeNote = this.getActiveNote(noteList, time);
|
|
576
650
|
if (activeNote) {
|
|
@@ -609,19 +683,22 @@ export class MidyGM1 {
|
|
|
609
683
|
const pitch = pitchWheel * pitchWheelSensitivity;
|
|
610
684
|
return tuning + pitch;
|
|
611
685
|
}
|
|
612
|
-
|
|
613
|
-
const now = this.audioContext.currentTime;
|
|
686
|
+
updateChannelDetune(channel) {
|
|
614
687
|
channel.scheduledNotes.forEach((noteList) => {
|
|
615
688
|
for (let i = 0; i < noteList.length; i++) {
|
|
616
689
|
const note = noteList[i];
|
|
617
690
|
if (!note)
|
|
618
691
|
continue;
|
|
619
|
-
note
|
|
620
|
-
.cancelScheduledValues(now)
|
|
621
|
-
.setValueAtTime(channel.detune, now);
|
|
692
|
+
this.updateDetune(channel, note);
|
|
622
693
|
}
|
|
623
694
|
});
|
|
624
695
|
}
|
|
696
|
+
updateDetune(channel, note) {
|
|
697
|
+
const now = this.audioContext.currentTime;
|
|
698
|
+
note.bufferSource.detune
|
|
699
|
+
.cancelScheduledValues(now)
|
|
700
|
+
.setValueAtTime(channel.detune, now);
|
|
701
|
+
}
|
|
625
702
|
setVolumeEnvelope(note) {
|
|
626
703
|
const now = this.audioContext.currentTime;
|
|
627
704
|
const { voiceParams, startTime } = note;
|
|
@@ -709,11 +786,31 @@ export class MidyGM1 {
|
|
|
709
786
|
note.modulationLFO.connect(note.volumeDepth);
|
|
710
787
|
note.volumeDepth.connect(note.volumeEnvelopeNode.gain);
|
|
711
788
|
}
|
|
789
|
+
async getAudioBuffer(program, noteNumber, velocity, voiceParams, isSF3) {
|
|
790
|
+
const audioBufferId = this.getAudioBufferId(program, noteNumber, velocity);
|
|
791
|
+
const cache = this.audioBufferCache.get(audioBufferId);
|
|
792
|
+
if (cache) {
|
|
793
|
+
cache.counter += 1;
|
|
794
|
+
if (cache.maxCount <= cache.counter) {
|
|
795
|
+
this.audioBufferCache.delete(audioBufferId);
|
|
796
|
+
}
|
|
797
|
+
return cache.audioBuffer;
|
|
798
|
+
}
|
|
799
|
+
else {
|
|
800
|
+
const maxCount = this.audioBufferCounter.get(audioBufferId) ?? 0;
|
|
801
|
+
const audioBuffer = await this.createNoteBuffer(voiceParams, isSF3);
|
|
802
|
+
const cache = { audioBuffer, maxCount, counter: 1 };
|
|
803
|
+
this.audioBufferCache.set(audioBufferId, cache);
|
|
804
|
+
return audioBuffer;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
712
807
|
async createNote(channel, voice, noteNumber, velocity, startTime, isSF3) {
|
|
713
808
|
const state = channel.state;
|
|
714
|
-
const
|
|
809
|
+
const controllerState = this.getControllerState(channel, noteNumber, velocity);
|
|
810
|
+
const voiceParams = voice.getAllParams(controllerState);
|
|
715
811
|
const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
|
|
716
|
-
|
|
812
|
+
const audioBuffer = await this.getAudioBuffer(channel.program, noteNumber, velocity, voiceParams, isSF3);
|
|
813
|
+
note.bufferSource = this.createNoteBufferNode(audioBuffer, voiceParams);
|
|
717
814
|
note.volumeEnvelopeNode = new GainNode(this.audioContext);
|
|
718
815
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
719
816
|
type: "lowpass",
|
|
@@ -737,10 +834,10 @@ export class MidyGM1 {
|
|
|
737
834
|
if (soundFontIndex === undefined)
|
|
738
835
|
return;
|
|
739
836
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
740
|
-
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
741
837
|
const voice = soundFont.getVoice(bankNumber, channel.program, noteNumber, velocity);
|
|
742
838
|
if (!voice)
|
|
743
839
|
return;
|
|
840
|
+
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
744
841
|
const note = await this.createNote(channel, voice, noteNumber, velocity, startTime, isSF3);
|
|
745
842
|
note.volumeEnvelopeNode.connect(channel.gainL);
|
|
746
843
|
note.volumeEnvelopeNode.connect(channel.gainR);
|
|
@@ -874,7 +971,7 @@ export class MidyGM1 {
|
|
|
874
971
|
const next = (value - 8192) / 8192;
|
|
875
972
|
state.pitchWheel = value / 16383;
|
|
876
973
|
channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
|
|
877
|
-
this.
|
|
974
|
+
this.updateChannelDetune(channel);
|
|
878
975
|
this.applyVoiceParams(channel, 14);
|
|
879
976
|
}
|
|
880
977
|
setModLfoToPitch(channel, note) {
|
|
@@ -972,7 +1069,7 @@ export class MidyGM1 {
|
|
|
972
1069
|
const freqVibLFO = note.voiceParams.freqVibLFO;
|
|
973
1070
|
note.vibratoLFO.frequency
|
|
974
1071
|
.cancelScheduledValues(now)
|
|
975
|
-
.setValueAtTime(freqVibLFO * channel.state.vibratoRate, now);
|
|
1072
|
+
.setValueAtTime(freqVibLFO * channel.state.vibratoRate * 2, now);
|
|
976
1073
|
}
|
|
977
1074
|
},
|
|
978
1075
|
};
|
|
@@ -1012,7 +1109,7 @@ export class MidyGM1 {
|
|
|
1012
1109
|
if (key in voiceParams)
|
|
1013
1110
|
noteVoiceParams[key] = voiceParams[key];
|
|
1014
1111
|
}
|
|
1015
|
-
this.setFilterEnvelope(
|
|
1112
|
+
this.setFilterEnvelope(note);
|
|
1016
1113
|
this.setPitchEnvelope(note);
|
|
1017
1114
|
}
|
|
1018
1115
|
else if (volumeEnvelopeKeySet.has(key)) {
|
|
@@ -1052,7 +1149,7 @@ export class MidyGM1 {
|
|
|
1052
1149
|
if (handler) {
|
|
1053
1150
|
handler.call(this, channelNumber, value);
|
|
1054
1151
|
const channel = this.channels[channelNumber];
|
|
1055
|
-
this.applyVoiceParams(channel,
|
|
1152
|
+
this.applyVoiceParams(channel, controllerType + 128);
|
|
1056
1153
|
}
|
|
1057
1154
|
else {
|
|
1058
1155
|
console.warn(`Unsupported Control change: controllerType=${controllerType} value=${value}`);
|
|
@@ -1191,7 +1288,7 @@ export class MidyGM1 {
|
|
|
1191
1288
|
const next = value / 128;
|
|
1192
1289
|
state.pitchWheelSensitivity = next;
|
|
1193
1290
|
channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
|
|
1194
|
-
this.
|
|
1291
|
+
this.updateChannelDetune(channel);
|
|
1195
1292
|
this.applyVoiceParams(channel, 16);
|
|
1196
1293
|
}
|
|
1197
1294
|
handleFineTuningRPN(channelNumber) {
|
|
@@ -1206,7 +1303,7 @@ export class MidyGM1 {
|
|
|
1206
1303
|
const next = (value - 8192) / 8.192; // cent
|
|
1207
1304
|
channel.fineTuning = next;
|
|
1208
1305
|
channel.detune += next - prev;
|
|
1209
|
-
this.
|
|
1306
|
+
this.updateChannelDetune(channel);
|
|
1210
1307
|
}
|
|
1211
1308
|
handleCoarseTuningRPN(channelNumber) {
|
|
1212
1309
|
const channel = this.channels[channelNumber];
|
|
@@ -1220,7 +1317,7 @@ export class MidyGM1 {
|
|
|
1220
1317
|
const next = (value - 64) * 100; // cent
|
|
1221
1318
|
channel.coarseTuning = next;
|
|
1222
1319
|
channel.detune += next - prev;
|
|
1223
|
-
this.
|
|
1320
|
+
this.updateChannelDetune(channel);
|
|
1224
1321
|
}
|
|
1225
1322
|
allSoundOff(channelNumber) {
|
|
1226
1323
|
return this.stopChannelNotes(channelNumber, 0, true);
|
|
@@ -1236,7 +1333,7 @@ export class MidyGM1 {
|
|
|
1236
1333
|
const state = channel.state;
|
|
1237
1334
|
for (let i = 0; i < stateTypes.length; i++) {
|
|
1238
1335
|
const type = stateTypes[i];
|
|
1239
|
-
state[type] = defaultControllerState[type];
|
|
1336
|
+
state[type] = defaultControllerState[type].defaultValue;
|
|
1240
1337
|
}
|
|
1241
1338
|
const settingTypes = [
|
|
1242
1339
|
"rpnMSB",
|
package/esm/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/esm/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":"AA6KA;IAqCE;;;;;;;;;;;;;;;;;MAiBE;IAgCF;;;;;OAaC;IAlGD,qBAAmB;IACnB,kBAAc;IACd,yBAAqB;IACrB,2BAAuB;IACvB;;;MAGE;IACF;;;;;;MAME;IACF,cAAa;IACb,cAAa;IACb,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;IAqBvC;;;;;MA4BE;IAGA,kBAAgC;IAChC;;;;;MAAqD;IACrD,kBAA8C;IAC9C;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IACjD;;;MAA8D;IAC9D;;;;;;;;MAAyD;IAO3D,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAYC;IAED,6DA2BC;IAED,8DASC;IAED,2CAcC;IAED,2EAuDC;IAED,mCAOC;IAED,0BAoDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MAgHC;IAED,+EAoBC;IAED,qDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,mDASC;IAED,6CAQC;IAED,kFAuBC;IAED;;;;MAWC;IAED,gFAUC;IAED,mFAYC;IAED,sGAcC;IAID;;;MA8BC;IAED;;;;;;;;MA0CC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAUC;IAED,6CAEC;IAED,wCAQC;IAED,2DAOC;IAED,wCAIC;IAED,gEAWC;IAED,kDAiBC;IAED,kCAqBC;IAED,6CAIC;IAED,gEAsBC;IAED,gEA0BC;IAED,+DAoBC;IAED,4DAaC;IAED,yGAgBC;IAED,iIAoEC;IAED,gDAQC;IAED,mHA0DC;IAED,2FASC;IAED,qFAqCC;IAED,wJAuCC;IAED,qHAUC;IAED,kEAeC;IAED,oEAYC;IAED,gFAmBC;IAED,4DAIC;IAED,4DAeC;IAED,qEAGC;IAED,mDASC;IAED,+DAQC;IAED,gDASC;IAED,oDAMC;IAED,kDAQC;IAED,oEA2BC;IAED,oEA2BC;IAED,gCAOC;IAED,+BAMC;IAED,6CAMC;IAED;;;;;;;;;;;MAgDC;IAED,oFAMC;IAED,0DAiDC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;MA2BC;IAED,+EAYC;IAED,+CAEC;IAED,qCAeC;IAED,8DAIC;IAED,iEAIC;IAED,sCAiBC;IAED,iDAKC;IAED;;;MAMC;IAED,mCAqBC;IAED,2CAKC;IAED,yDAIC;IAED,+CAEC;IAED,mDAGC;IAED,wCAWC;IAED,sDAKC;IAED,oDAEC;IAED,wDASC;IAED,uDAGC;IAED,mEAmCC;IAED,mEAmCC;IAED,kFAeC;IAED,2DAMC;IAED,oCAqBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,kDAKC;IAED,wDASC;IAED,8CAKC;IAED,oDAOC;IAED,gDAKC;IAED,sDAOC;IAED,wDAKC;IAED,6EAIC;IAED,+CAEC;IAED,8CAyBC;IAED,+CAEC;IAED,gBAEC;IAED,eAEC;IAED,eAEC;IAED,eAEC;IAED,4DA4BC;IAED,oBASC;IAED,oBASC;IAED,wDAqCC;IAED,yCAGC;IAED,mCAQC;IAED,6CAGC;IAED,sCAMC;IAED,+CAGC;IAED,wCAMC;IAED,mDAeC;IAED,4CAOC;IAED,+BAKC;IAED,qDAiBC;IAED,gCAIC;IAED,kCAEC;IA6BD,4CAEC;IAED,4CAaC;IAED,+BAiBC;IAED,wFAKC;IAED,mCAKC;IAED,qCAEC;IAED,oCAOC;IAED,sCAEC;IAED,oCAUC;IAED,sCAEC;IAED,wCAuBC;IAED,0CAEC;IAED,mCAeC;IAED,wEAeC;IAED,oEAoCC;IAED,4DAQC;IAED,4CAUC;IAED,2DAWC;IAED,0CASC;IAED,6FAIC;IAED,sDAcC;IAED,wCAEC;IAED,4BASC;IAED,0DAUC;CACF;AAxkFD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IAgBE,0FAMC;IArBD,kBAAa;IACb,gBAAW;IACX,wBAAmB;IACnB,gBAAW;IACX,WAAM;IACN,WAAM;IACN,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IACb,uBAAkB;IAClB,uBAAkB;IAClB,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
|