@marmooo/midy 0.3.7 → 0.3.8
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/README.md +31 -11
- package/esm/midy-GM1.d.ts +9 -6
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +67 -57
- package/esm/midy-GM2.d.ts +13 -7
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +147 -154
- package/esm/midy-GMLite.d.ts +8 -6
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +68 -59
- package/esm/midy.d.ts +13 -7
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +208 -226
- package/package.json +2 -2
- package/script/midy-GM1.d.ts +9 -6
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +67 -57
- package/script/midy-GM2.d.ts +13 -7
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +147 -154
- package/script/midy-GMLite.d.ts +8 -6
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +68 -59
- package/script/midy.d.ts +13 -7
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +208 -226
package/README.md
CHANGED
|
@@ -23,6 +23,26 @@ This library provides several files depending on the implementation level.
|
|
|
23
23
|
- [@marmooo/midi-player](https://marmooo.github.io/midi-player/) - GUI library
|
|
24
24
|
- [Humidy](https://marmooo.github.io/humidy/) - GM2 MIDI mixer app
|
|
25
25
|
|
|
26
|
+
## Support Status
|
|
27
|
+
|
|
28
|
+
All implementations follow the specification.
|
|
29
|
+
|
|
30
|
+
| Message | Support | Notes |
|
|
31
|
+
| :----------------------- | :-----: | :------- |
|
|
32
|
+
| Note Off | ✔️ | |
|
|
33
|
+
| Note On | ✔️ | |
|
|
34
|
+
| Polyphonic Key Pressure | ✔️ | full GM2 |
|
|
35
|
+
| Controller Change | ✔️ | full GM2 |
|
|
36
|
+
| Program Change | ✔️ | full GM2 |
|
|
37
|
+
| Channel Pressure | ✔️ | full GM2 |
|
|
38
|
+
| Pitch Bend | ✔️ | |
|
|
39
|
+
| System Exclusive Message | ✔️ | full GM2 |
|
|
40
|
+
| System Common Message | ❌ | |
|
|
41
|
+
| System Real Time Message | ✔️ | full GM2 |
|
|
42
|
+
| MIDI Time Code | ❌ | |
|
|
43
|
+
| MIDI Show Control | ❌ | |
|
|
44
|
+
| MIDI Machine Control | ❌ | |
|
|
45
|
+
|
|
26
46
|
## Usage
|
|
27
47
|
|
|
28
48
|
### Initialization
|
|
@@ -34,6 +54,7 @@ This library provides several files depending on the implementation level.
|
|
|
34
54
|
import { Midy } from "midy.js";
|
|
35
55
|
|
|
36
56
|
const audioContext = new AudioContext();
|
|
57
|
+
await audioContext.suspend();
|
|
37
58
|
const midy = new Midy(audioContext);
|
|
38
59
|
await midy.loadMIDI("test.mid");
|
|
39
60
|
await midy.loadSoundFont("test.sf3");
|
|
@@ -56,9 +77,9 @@ There are functions that handle MIDI messages as they are, as well as simplified
|
|
|
56
77
|
functions.
|
|
57
78
|
|
|
58
79
|
```js
|
|
59
|
-
midy.
|
|
80
|
+
midy.handleMessage(data, scheduleTime);
|
|
60
81
|
midy.noteOn(channelNumber, noteNumber, velocity);
|
|
61
|
-
midy.setProgramChange(channelNumber,
|
|
82
|
+
midy.setProgramChange(channelNumber, programNumber);
|
|
62
83
|
```
|
|
63
84
|
|
|
64
85
|
### Control Change
|
|
@@ -101,19 +122,18 @@ const soundFontURL = "https://soundfonts.pages.dev/GeneralUser_GS_v1.471";
|
|
|
101
122
|
function getSoundFontPaths() {
|
|
102
123
|
const paths = [];
|
|
103
124
|
for (const instrument of midy.instruments) {
|
|
104
|
-
const [
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
paths.push(path);
|
|
125
|
+
const [bank, program] = instrument.split(":");
|
|
126
|
+
const bankNumber = Number(bank);
|
|
127
|
+
const programNumber = Number(program);
|
|
128
|
+
const index = midy.soundFontTable[programNumber][bankNumber];
|
|
129
|
+
if (index !== undefined) continue;
|
|
130
|
+
const baseName = bankNumber === 128 ? "128" : program;
|
|
131
|
+
paths.push(`${soundFontURL}/${baseName}.sf3`);
|
|
112
132
|
}
|
|
113
133
|
return paths;
|
|
114
134
|
}
|
|
115
135
|
|
|
116
|
-
const paths =
|
|
136
|
+
const paths = getSoundFontPaths();
|
|
117
137
|
await midy.loadSoundFont(paths);
|
|
118
138
|
```
|
|
119
139
|
|
package/esm/midy-GM1.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export class MidyGM1 {
|
|
2
2
|
static channelSettings: {
|
|
3
|
+
scheduleIndex: number;
|
|
3
4
|
detune: number;
|
|
4
5
|
programNumber: number;
|
|
5
|
-
bank: number;
|
|
6
6
|
dataMSB: number;
|
|
7
7
|
dataLSB: number;
|
|
8
8
|
rpnMSB: number;
|
|
@@ -22,7 +22,7 @@ export class MidyGM1 {
|
|
|
22
22
|
startTime: number;
|
|
23
23
|
resumeTime: number;
|
|
24
24
|
soundFonts: any[];
|
|
25
|
-
soundFontTable:
|
|
25
|
+
soundFontTable: never[][];
|
|
26
26
|
voiceCounter: Map<any, any>;
|
|
27
27
|
voiceCache: Map<any, any>;
|
|
28
28
|
isPlaying: boolean;
|
|
@@ -39,6 +39,7 @@ export class MidyGM1 {
|
|
|
39
39
|
masterVolume: any;
|
|
40
40
|
scheduler: any;
|
|
41
41
|
schedulerBuffer: any;
|
|
42
|
+
messageHandlers: any[];
|
|
42
43
|
voiceParamsHandlers: {
|
|
43
44
|
modLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
|
|
44
45
|
vibLfoToPitch: (_channel: any, _note: any, _scheduleTime: any) => void;
|
|
@@ -53,7 +54,6 @@ export class MidyGM1 {
|
|
|
53
54
|
};
|
|
54
55
|
controlChangeHandlers: any[];
|
|
55
56
|
channels: any[];
|
|
56
|
-
initSoundFontTable(): any[];
|
|
57
57
|
addSoundFont(soundFont: any): void;
|
|
58
58
|
toUint8Array(input: any): Promise<Uint8Array<ArrayBuffer>>;
|
|
59
59
|
loadSoundFont(input: any): Promise<void>;
|
|
@@ -68,13 +68,14 @@ export class MidyGM1 {
|
|
|
68
68
|
createChannels(audioContext: any): any[];
|
|
69
69
|
createAudioBuffer(voiceParams: any): Promise<any>;
|
|
70
70
|
createBufferSource(voiceParams: any, audioBuffer: any): any;
|
|
71
|
-
scheduleTimelineEvents(
|
|
71
|
+
scheduleTimelineEvents(scheduleTime: any, queueIndex: any): Promise<any>;
|
|
72
72
|
getQueueIndex(second: any): number;
|
|
73
73
|
resetAllStates(): void;
|
|
74
74
|
updateStates(queueIndex: any, nextQueueIndex: any): void;
|
|
75
75
|
playNotes(): Promise<void>;
|
|
76
76
|
ticksToSecond(ticks: any, secondsPerBeat: any): number;
|
|
77
77
|
secondToTicks(second: any, secondsPerBeat: any): number;
|
|
78
|
+
getSoundFontId(channel: any): string;
|
|
78
79
|
extractMidiData(midi: any): {
|
|
79
80
|
instruments: Set<any>;
|
|
80
81
|
timeline: any[];
|
|
@@ -115,7 +116,9 @@ export class MidyGM1 {
|
|
|
115
116
|
findNoteOffIndex(channel: any, noteNumber: any): any;
|
|
116
117
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): void;
|
|
117
118
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
|
|
118
|
-
|
|
119
|
+
createMessageHandlers(): any[];
|
|
120
|
+
handleMessage(data: any, scheduleTime: any): void;
|
|
121
|
+
handleChannelMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<void>;
|
|
119
122
|
setProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
|
|
120
123
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
|
|
121
124
|
setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
|
|
@@ -172,7 +175,7 @@ export class MidyGM1 {
|
|
|
172
175
|
GM1SystemOn(scheduleTime: any): void;
|
|
173
176
|
handleUniversalRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
174
177
|
handleMasterVolumeSysEx(data: any, scheduleTime: any): void;
|
|
175
|
-
setMasterVolume(
|
|
178
|
+
setMasterVolume(value: any, scheduleTime: any): void;
|
|
176
179
|
handleSysEx(data: any, scheduleTime: any): void;
|
|
177
180
|
scheduleTask(callback: any, scheduleTime: any): Promise<any>;
|
|
178
181
|
}
|
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":"AA4FA;IAyBE;;;;;;;;;;;MAWE;IAEF,+
|
|
1
|
+
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AA4FA;IAyBE;;;;;;;;;;;MAWE;IAEF,+BAeC;IApDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,0BAAuD;IACvD,4BAAyB;IACzB,0BAAuB;IACvB,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IAgBnC,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF,uBAAmD;IACnD;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,gBAAiD;IAMnD,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAWC;IAED;;;;MAeC;IAED,yCAaC;IAED,kDAUC;IAED,4DASC;IAED,yEAqDC;IAED,mCAOC;IAED,uBAQC;IAED,yDA2BC;IAED,2BAwCC;IAED,uDAEC;IAED,wDAEC;IAED,qCAKC;IAED;;;MAwDC;IAED,kGAeC;IAED,mGAeC;IAED,wEAMC;IAED,uBAMC;IAED,sBAKC;IAED,uBAQC;IAED,wBAKC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,yEASC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,2DAIC;IAED,+DAIC;IAED,sDAeC;IAED,qDAoBC;IAED,6CAIC;IAED,sDAsBC;IAED,kEAoBC;IAED,6FAyBC;IAED,oGAuCC;IAED,0EAiBC;IAED,kGAgCC;IAED,6FASC;IAED,gCASC;IAED,iEAoBC;IAED,qGAeC;IAED,6CAUC;IAED,qDAUC;IAED,qFASC;IAED,sFAeC;IAED,+BAmBC;IAED,kDAOC;IAED,uGA2BC;IAED,mFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAWC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MAiCC;IAED,oFAMC;IAED,6EA2BC;IAED,qCAeC;IAED,+FAWC;IAED,wDASC;IAED,iFAKC;IAED,oEAKC;IAED;;;MAMC;IAED,8DAKC;IAED,4EAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAWC;IAED,kFAeC;IAED,2DAMC;IAED,uDAkBC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAUC;IAED,iEAMC;IAED,uEAQC;IAED,mEAKC;IAED,yEAQC;IAED,gFAGC;IAED,6CAqBC;IAGD,8EAgCC;IAED,gFAGC;IAED,+EAgBC;IAED,qCASC;IAED,4EAaC;IAED,4DAGC;IAED,qDAKC;IAED,gDAYC;IAGD,6DAgBC;CACF;AAtiDD;IAWE,0FAMC;IAhBD,cAAW;IACX,gBAAe;IACf,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
|
package/esm/midy-GM1.js
CHANGED
|
@@ -200,7 +200,7 @@ export class MidyGM1 {
|
|
|
200
200
|
enumerable: true,
|
|
201
201
|
configurable: true,
|
|
202
202
|
writable: true,
|
|
203
|
-
value:
|
|
203
|
+
value: Array.from({ length: 128 }, () => [])
|
|
204
204
|
});
|
|
205
205
|
Object.defineProperty(this, "voiceCounter", {
|
|
206
206
|
enumerable: true,
|
|
@@ -281,6 +281,7 @@ export class MidyGM1 {
|
|
|
281
281
|
length: 1,
|
|
282
282
|
sampleRate: audioContext.sampleRate,
|
|
283
283
|
});
|
|
284
|
+
this.messageHandlers = this.createMessageHandlers();
|
|
284
285
|
this.voiceParamsHandlers = this.createVoiceParamsHandlers();
|
|
285
286
|
this.controlChangeHandlers = this.createControlChangeHandlers();
|
|
286
287
|
this.channels = this.createChannels(audioContext);
|
|
@@ -288,21 +289,14 @@ export class MidyGM1 {
|
|
|
288
289
|
this.scheduler.connect(audioContext.destination);
|
|
289
290
|
this.GM1SystemOn();
|
|
290
291
|
}
|
|
291
|
-
initSoundFontTable() {
|
|
292
|
-
const table = new Array(128);
|
|
293
|
-
for (let i = 0; i < 128; i++) {
|
|
294
|
-
table[i] = new Map();
|
|
295
|
-
}
|
|
296
|
-
return table;
|
|
297
|
-
}
|
|
298
292
|
addSoundFont(soundFont) {
|
|
299
293
|
const index = this.soundFonts.length;
|
|
300
294
|
this.soundFonts.push(soundFont);
|
|
301
295
|
const presetHeaders = soundFont.parsed.presetHeaders;
|
|
296
|
+
const soundFontTable = this.soundFontTable;
|
|
302
297
|
for (let i = 0; i < presetHeaders.length; i++) {
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
banks.set(presetHeader.bank, index);
|
|
298
|
+
const { preset, bank } = presetHeaders[i];
|
|
299
|
+
soundFontTable[preset][bank] = index;
|
|
306
300
|
}
|
|
307
301
|
}
|
|
308
302
|
async toUint8Array(input) {
|
|
@@ -380,13 +374,16 @@ export class MidyGM1 {
|
|
|
380
374
|
this.GM1SystemOn();
|
|
381
375
|
}
|
|
382
376
|
getVoiceId(channel, noteNumber, velocity) {
|
|
383
|
-
const
|
|
384
|
-
const
|
|
385
|
-
|
|
377
|
+
const programNumber = channel.programNumber;
|
|
378
|
+
const bankTable = this.soundFontTable[programNumber];
|
|
379
|
+
if (!bankTable)
|
|
380
|
+
return;
|
|
381
|
+
const bank = channel.isDrum ? 128 : 0;
|
|
382
|
+
const soundFontIndex = bankTable[bank];
|
|
386
383
|
if (soundFontIndex === undefined)
|
|
387
384
|
return;
|
|
388
385
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
389
|
-
const voice = soundFont.getVoice(
|
|
386
|
+
const voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
|
|
390
387
|
const { instrument, sampleID } = voice.generators;
|
|
391
388
|
return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
|
|
392
389
|
}
|
|
@@ -435,13 +432,16 @@ export class MidyGM1 {
|
|
|
435
432
|
}
|
|
436
433
|
return bufferSource;
|
|
437
434
|
}
|
|
438
|
-
async scheduleTimelineEvents(
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
435
|
+
async scheduleTimelineEvents(scheduleTime, queueIndex) {
|
|
436
|
+
const timeOffset = this.resumeTime - this.startTime;
|
|
437
|
+
const lookAheadCheckTime = scheduleTime + timeOffset + this.lookAhead;
|
|
438
|
+
const schedulingOffset = this.startDelay - timeOffset;
|
|
439
|
+
const timeline = this.timeline;
|
|
440
|
+
while (queueIndex < timeline.length) {
|
|
441
|
+
const event = timeline[queueIndex];
|
|
442
|
+
if (lookAheadCheckTime < event.startTime)
|
|
442
443
|
break;
|
|
443
|
-
const
|
|
444
|
-
const startTime = event.startTime + delay;
|
|
444
|
+
const startTime = event.startTime + schedulingOffset;
|
|
445
445
|
switch (event.type) {
|
|
446
446
|
case "noteOn":
|
|
447
447
|
await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, startTime);
|
|
@@ -513,13 +513,11 @@ export class MidyGM1 {
|
|
|
513
513
|
this.isPaused = false;
|
|
514
514
|
this.startTime = this.audioContext.currentTime;
|
|
515
515
|
let queueIndex = this.getQueueIndex(this.resumeTime);
|
|
516
|
-
let resumeTime = this.resumeTime - this.startTime;
|
|
517
516
|
let finished = false;
|
|
518
517
|
this.notePromises = [];
|
|
519
518
|
while (queueIndex < this.timeline.length) {
|
|
520
519
|
const now = this.audioContext.currentTime;
|
|
521
|
-
|
|
522
|
-
queueIndex = await this.scheduleTimelineEvents(t, resumeTime, queueIndex);
|
|
520
|
+
queueIndex = await this.scheduleTimelineEvents(now, queueIndex);
|
|
523
521
|
if (this.isPausing) {
|
|
524
522
|
await this.stopNotes(0, true, now);
|
|
525
523
|
await this.audioContext.suspend();
|
|
@@ -538,7 +536,6 @@ export class MidyGM1 {
|
|
|
538
536
|
const nextQueueIndex = this.getQueueIndex(this.resumeTime);
|
|
539
537
|
this.updateStates(queueIndex, nextQueueIndex);
|
|
540
538
|
queueIndex = nextQueueIndex;
|
|
541
|
-
resumeTime = this.resumeTime - this.startTime;
|
|
542
539
|
this.isSeeking = false;
|
|
543
540
|
continue;
|
|
544
541
|
}
|
|
@@ -557,16 +554,16 @@ export class MidyGM1 {
|
|
|
557
554
|
secondToTicks(second, secondsPerBeat) {
|
|
558
555
|
return second * this.ticksPerBeat / secondsPerBeat;
|
|
559
556
|
}
|
|
557
|
+
getSoundFontId(channel) {
|
|
558
|
+
const programNumber = channel.programNumber;
|
|
559
|
+
const bank = channel.isDrum ? "128" : "000";
|
|
560
|
+
const program = programNumber.toString().padStart(3, "0");
|
|
561
|
+
return `${bank}:${program}`;
|
|
562
|
+
}
|
|
560
563
|
extractMidiData(midi) {
|
|
561
564
|
const instruments = new Set();
|
|
562
565
|
const timeline = [];
|
|
563
|
-
const
|
|
564
|
-
for (let i = 0; i < tmpChannels.length; i++) {
|
|
565
|
-
tmpChannels[i] = {
|
|
566
|
-
programNumber: -1,
|
|
567
|
-
bank: this.channels[i].bank,
|
|
568
|
-
};
|
|
569
|
-
}
|
|
566
|
+
const channels = this.channels;
|
|
570
567
|
for (let i = 0; i < midi.tracks.length; i++) {
|
|
571
568
|
const track = midi.tracks[i];
|
|
572
569
|
let currentTicks = 0;
|
|
@@ -576,17 +573,15 @@ export class MidyGM1 {
|
|
|
576
573
|
event.ticks = currentTicks;
|
|
577
574
|
switch (event.type) {
|
|
578
575
|
case "noteOn": {
|
|
579
|
-
const channel =
|
|
580
|
-
|
|
581
|
-
instruments.add(`${channel.bank}:0`);
|
|
582
|
-
channel.programNumber = 0;
|
|
583
|
-
}
|
|
576
|
+
const channel = channels[event.channel];
|
|
577
|
+
instruments.add(this.getSoundFontId(channel));
|
|
584
578
|
break;
|
|
585
579
|
}
|
|
586
580
|
case "programChange": {
|
|
587
|
-
const channel =
|
|
588
|
-
channel
|
|
589
|
-
instruments.add(
|
|
581
|
+
const channel = channels[event.channel];
|
|
582
|
+
this.setProgramChange(event.channel, event.programNumber);
|
|
583
|
+
instruments.add(this.getSoundFontId(channel));
|
|
584
|
+
break;
|
|
590
585
|
}
|
|
591
586
|
}
|
|
592
587
|
delete event.deltaTime;
|
|
@@ -892,13 +887,16 @@ export class MidyGM1 {
|
|
|
892
887
|
}
|
|
893
888
|
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
|
|
894
889
|
const channel = this.channels[channelNumber];
|
|
895
|
-
const
|
|
896
|
-
const
|
|
897
|
-
|
|
890
|
+
const programNumber = channel.programNumber;
|
|
891
|
+
const bankTable = this.soundFontTable[programNumber];
|
|
892
|
+
if (!bankTable)
|
|
893
|
+
return;
|
|
894
|
+
const bank = channel.isDrum ? 128 : 0;
|
|
895
|
+
const soundFontIndex = bankTable[bank];
|
|
898
896
|
if (soundFontIndex === undefined)
|
|
899
897
|
return;
|
|
900
898
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
901
|
-
const voice = soundFont.getVoice(
|
|
899
|
+
const voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
|
|
902
900
|
if (!voice)
|
|
903
901
|
return;
|
|
904
902
|
const note = await this.createNote(channel, voice, noteNumber, velocity, startTime);
|
|
@@ -1000,7 +998,26 @@ export class MidyGM1 {
|
|
|
1000
998
|
channel.sustainNotes = [];
|
|
1001
999
|
return promises;
|
|
1002
1000
|
}
|
|
1003
|
-
|
|
1001
|
+
createMessageHandlers() {
|
|
1002
|
+
const handlers = new Array(256);
|
|
1003
|
+
// Channel Message
|
|
1004
|
+
handlers[0x80] = (data, scheduleTime) => this.noteOff(data[0] & 0x0F, data[1], data[2], scheduleTime);
|
|
1005
|
+
handlers[0x90] = (data, scheduleTime) => this.noteOn(data[0] & 0x0F, data[1], data[2], scheduleTime);
|
|
1006
|
+
handlers[0xB0] = (data, scheduleTime) => this.setControlChange(data[0] & 0x0F, data[1], data[2], scheduleTime);
|
|
1007
|
+
handlers[0xC0] = (data, scheduleTime) => this.setProgramChange(data[0] & 0x0F, data[1], scheduleTime);
|
|
1008
|
+
handlers[0xE0] = (data, scheduleTime) => this.handlePitchBendMessage(data[0] & 0x0F, data[1], data[2], scheduleTime);
|
|
1009
|
+
return handlers;
|
|
1010
|
+
}
|
|
1011
|
+
handleMessage(data, scheduleTime) {
|
|
1012
|
+
const status = data[0];
|
|
1013
|
+
if (status === 0xF0) {
|
|
1014
|
+
return this.handleSysEx(data.subarray(1), scheduleTime);
|
|
1015
|
+
}
|
|
1016
|
+
const handler = this.messageHandlers[status];
|
|
1017
|
+
if (handler)
|
|
1018
|
+
handler(data, scheduleTime);
|
|
1019
|
+
}
|
|
1020
|
+
handleChannelMessage(statusByte, data1, data2, scheduleTime) {
|
|
1004
1021
|
const channelNumber = statusByte & 0x0F;
|
|
1005
1022
|
const messageType = statusByte & 0xF0;
|
|
1006
1023
|
switch (messageType) {
|
|
@@ -1428,10 +1445,8 @@ export class MidyGM1 {
|
|
|
1428
1445
|
for (let i = 0; i < this.channels.length; i++) {
|
|
1429
1446
|
this.allSoundOff(i, 0, scheduleTime);
|
|
1430
1447
|
const channel = this.channels[i];
|
|
1431
|
-
channel.bank = 0;
|
|
1432
1448
|
channel.isDrum = false;
|
|
1433
1449
|
}
|
|
1434
|
-
this.channels[9].bank = 128;
|
|
1435
1450
|
this.channels[9].isDrum = true;
|
|
1436
1451
|
}
|
|
1437
1452
|
handleUniversalRealTimeExclusiveMessage(data, scheduleTime) {
|
|
@@ -1452,16 +1467,11 @@ export class MidyGM1 {
|
|
|
1452
1467
|
const volume = (data[5] * 128 + data[4]) / 16383;
|
|
1453
1468
|
this.setMasterVolume(volume, scheduleTime);
|
|
1454
1469
|
}
|
|
1455
|
-
setMasterVolume(
|
|
1470
|
+
setMasterVolume(value, scheduleTime) {
|
|
1456
1471
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
else {
|
|
1461
|
-
this.masterVolume.gain
|
|
1462
|
-
.cancelScheduledValues(scheduleTime)
|
|
1463
|
-
.setValueAtTime(volume * volume, scheduleTime);
|
|
1464
|
-
}
|
|
1472
|
+
this.masterVolume.gain
|
|
1473
|
+
.cancelScheduledValues(scheduleTime)
|
|
1474
|
+
.setValueAtTime(value * value, scheduleTime);
|
|
1465
1475
|
}
|
|
1466
1476
|
handleSysEx(data, scheduleTime) {
|
|
1467
1477
|
switch (data[0]) {
|
|
@@ -1498,9 +1508,9 @@ Object.defineProperty(MidyGM1, "channelSettings", {
|
|
|
1498
1508
|
configurable: true,
|
|
1499
1509
|
writable: true,
|
|
1500
1510
|
value: {
|
|
1511
|
+
scheduleIndex: 0,
|
|
1501
1512
|
detune: 0,
|
|
1502
1513
|
programNumber: 0,
|
|
1503
|
-
bank: 0,
|
|
1504
1514
|
dataMSB: 0,
|
|
1505
1515
|
dataLSB: 0,
|
|
1506
1516
|
rpnMSB: 127,
|
package/esm/midy-GM2.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ export class MidyGM2 {
|
|
|
3
3
|
scheduleIndex: number;
|
|
4
4
|
detune: number;
|
|
5
5
|
programNumber: number;
|
|
6
|
-
bank: number;
|
|
7
6
|
bankMSB: number;
|
|
8
7
|
bankLSB: number;
|
|
9
8
|
dataMSB: number;
|
|
@@ -34,13 +33,15 @@ export class MidyGM2 {
|
|
|
34
33
|
numChannels: number;
|
|
35
34
|
ticksPerBeat: number;
|
|
36
35
|
totalTime: number;
|
|
36
|
+
lastActiveSensing: number;
|
|
37
|
+
activeSensingThreshold: number;
|
|
37
38
|
noteCheckInterval: number;
|
|
38
39
|
lookAhead: number;
|
|
39
40
|
startDelay: number;
|
|
40
41
|
startTime: number;
|
|
41
42
|
resumeTime: number;
|
|
42
43
|
soundFonts: any[];
|
|
43
|
-
soundFontTable:
|
|
44
|
+
soundFontTable: never[][];
|
|
44
45
|
voiceCounter: Map<any, any>;
|
|
45
46
|
voiceCache: Map<any, any>;
|
|
46
47
|
isPlaying: boolean;
|
|
@@ -58,6 +59,7 @@ export class MidyGM2 {
|
|
|
58
59
|
masterVolume: any;
|
|
59
60
|
scheduler: any;
|
|
60
61
|
schedulerBuffer: any;
|
|
62
|
+
messageHandlers: any[];
|
|
61
63
|
voiceParamsHandlers: {
|
|
62
64
|
modLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
|
|
63
65
|
vibLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
|
|
@@ -71,6 +73,7 @@ export class MidyGM2 {
|
|
|
71
73
|
freqVibLFO: (channel: any, note: any, scheduleTime: any) => void;
|
|
72
74
|
};
|
|
73
75
|
controlChangeHandlers: any[];
|
|
76
|
+
keyBasedControllerHandlers: any[];
|
|
74
77
|
channels: any[];
|
|
75
78
|
reverbEffect: {
|
|
76
79
|
input: any;
|
|
@@ -85,7 +88,6 @@ export class MidyGM2 {
|
|
|
85
88
|
delayNodes: any[];
|
|
86
89
|
feedbackGains: any[];
|
|
87
90
|
};
|
|
88
|
-
initSoundFontTable(): any[];
|
|
89
91
|
addSoundFont(soundFont: any): void;
|
|
90
92
|
toUint8Array(input: any): Promise<Uint8Array<ArrayBuffer>>;
|
|
91
93
|
loadSoundFont(input: any): Promise<void>;
|
|
@@ -102,13 +104,14 @@ export class MidyGM2 {
|
|
|
102
104
|
createAudioBuffer(voiceParams: any): Promise<any>;
|
|
103
105
|
isLoopDrum(channel: any, noteNumber: any): boolean;
|
|
104
106
|
createBufferSource(channel: any, noteNumber: any, voiceParams: any, audioBuffer: any): any;
|
|
105
|
-
scheduleTimelineEvents(
|
|
107
|
+
scheduleTimelineEvents(scheduleTime: any, queueIndex: any): Promise<any>;
|
|
106
108
|
getQueueIndex(second: any): number;
|
|
107
109
|
resetAllStates(): void;
|
|
108
110
|
updateStates(queueIndex: any, nextQueueIndex: any): void;
|
|
109
111
|
playNotes(): Promise<void>;
|
|
110
112
|
ticksToSecond(ticks: any, secondsPerBeat: any): number;
|
|
111
113
|
secondToTicks(second: any, secondsPerBeat: any): number;
|
|
114
|
+
getSoundFontId(channel: any): string;
|
|
112
115
|
extractMidiData(midi: any): {
|
|
113
116
|
instruments: Set<any>;
|
|
114
117
|
timeline: any[];
|
|
@@ -172,7 +175,6 @@ export class MidyGM2 {
|
|
|
172
175
|
startVibrato(channel: any, note: any, scheduleTime: any): void;
|
|
173
176
|
getAudioBuffer(channel: any, noteNumber: any, velocity: any, voiceParams: any): Promise<any>;
|
|
174
177
|
createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any): Promise<Note>;
|
|
175
|
-
calcBank(channel: any): any;
|
|
176
178
|
handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
177
179
|
handleDrumExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
178
180
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
@@ -185,7 +187,9 @@ export class MidyGM2 {
|
|
|
185
187
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): void;
|
|
186
188
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
|
|
187
189
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
|
|
188
|
-
|
|
190
|
+
createMessageHandlers(): any[];
|
|
191
|
+
handleMessage(data: any, scheduleTime: any): void;
|
|
192
|
+
activeSensing(): void;
|
|
189
193
|
setProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
|
|
190
194
|
setChannelPressure(channelNumber: any, value: any, scheduleTime: any): void;
|
|
191
195
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
|
|
@@ -233,6 +237,7 @@ export class MidyGM2 {
|
|
|
233
237
|
updateChannelVolume(channel: any, scheduleTime: any): void;
|
|
234
238
|
updateKeyBasedVolume(channel: any, keyNumber: any, scheduleTime: any): void;
|
|
235
239
|
setSustainPedal(channelNumber: any, value: any, scheduleTime: any): void;
|
|
240
|
+
isPortamento(channel: any, note: any): boolean;
|
|
236
241
|
setPortamento(channelNumber: any, value: any, scheduleTime: any): void;
|
|
237
242
|
setSostenutoPedal(channelNumber: any, value: any, scheduleTime: any): void;
|
|
238
243
|
getSoftPedalFactor(channel: any, note: any): number;
|
|
@@ -266,7 +271,7 @@ export class MidyGM2 {
|
|
|
266
271
|
GM2SystemOn(scheduleTime: any): void;
|
|
267
272
|
handleUniversalRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
268
273
|
handleMasterVolumeSysEx(data: any, scheduleTime: any): void;
|
|
269
|
-
setMasterVolume(
|
|
274
|
+
setMasterVolume(value: any, scheduleTime: any): void;
|
|
270
275
|
handleMasterFineTuningSysEx(data: any, scheduleTime: any): void;
|
|
271
276
|
setMasterFineTuning(value: any, scheduleTime: any): void;
|
|
272
277
|
handleMasterCoarseTuningSysEx(data: any, scheduleTime: any): void;
|
|
@@ -302,6 +307,7 @@ export class MidyGM2 {
|
|
|
302
307
|
setControlChangeEffects(channel: any, controllerType: any, scheduleTime: any): void;
|
|
303
308
|
handleControlChangeSysEx(data: any, scheduleTime: any): void;
|
|
304
309
|
getKeyBasedValue(channel: any, keyNumber: any, controllerType: any): any;
|
|
310
|
+
createKeyBasedControllerHandlers(): any[];
|
|
305
311
|
handleKeyBasedInstrumentControlSysEx(data: any, scheduleTime: any): void;
|
|
306
312
|
handleSysEx(data: any, scheduleTime: any): void;
|
|
307
313
|
scheduleTask(callback: any, scheduleTime: any): Promise<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":"AAkJA;
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}
|