@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marmooo/midy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "A MIDI player/synthesizer written in JavaScript that supports GM-Lite/GM1 and SF2/SF3.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"scripts": {
|
|
22
22
|
"test": "node test_runner.js"
|
|
23
23
|
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@marmooo/soundfont-parser": "^0.0.7",
|
|
26
|
+
"midi-file": "^1.2.4"
|
|
27
|
+
},
|
|
24
28
|
"devDependencies": {
|
|
25
29
|
"@types/node": "^20.9.0",
|
|
26
30
|
"picocolors": "^1.0.0"
|
package/script/midy-GM1.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export class MidyGM1 {
|
|
|
37
37
|
timeline: any[];
|
|
38
38
|
instruments: any[];
|
|
39
39
|
notePromises: any[];
|
|
40
|
+
exclusiveClassMap: Map<any, any>;
|
|
40
41
|
audioContext: any;
|
|
41
42
|
masterGain: any;
|
|
42
43
|
controlChangeHandlers: {
|
|
@@ -98,11 +99,11 @@ export class MidyGM1 {
|
|
|
98
99
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
99
100
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
100
101
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
101
|
-
stopNote(
|
|
102
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any,
|
|
103
|
-
releaseNote(channelNumber: any, noteNumber: any, velocity: any):
|
|
102
|
+
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
103
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): Promise<any> | undefined;
|
|
104
|
+
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
104
105
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
105
|
-
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<
|
|
106
|
+
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
106
107
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
107
108
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
108
109
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
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":"AAqBA;IAoBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAOC;IAhDD,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;IAyB5B,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,sCAGC;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,kFAeC;IAED,2DAMC;IAED,oCAkBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAaC;IAED,kDAKC;IAED,iEAOC;IAED,8CAKC;IAED,yDAMC;IAED,gDAKC;IAED,6DAMC;IAED,+CAEC;IAED,8CAEC;IAED,+CAEC;IAED,4DAgBC;IAED,oBASC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AA9kCD;IAUE,gFAKC;IAdD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|
package/script/midy-GM1.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MidyGM1 = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const midi_file_1 = require("midi-file");
|
|
5
|
+
const soundfont_parser_1 = require("@marmooo/soundfont-parser");
|
|
6
6
|
class Note {
|
|
7
7
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
8
8
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -163,6 +163,12 @@ class MidyGM1 {
|
|
|
163
163
|
writable: true,
|
|
164
164
|
value: []
|
|
165
165
|
});
|
|
166
|
+
Object.defineProperty(this, "exclusiveClassMap", {
|
|
167
|
+
enumerable: true,
|
|
168
|
+
configurable: true,
|
|
169
|
+
writable: true,
|
|
170
|
+
value: new Map()
|
|
171
|
+
});
|
|
166
172
|
this.audioContext = audioContext;
|
|
167
173
|
this.masterGain = new GainNode(audioContext);
|
|
168
174
|
this.controlChangeHandlers = this.createControlChangeHandlers();
|
|
@@ -192,14 +198,14 @@ class MidyGM1 {
|
|
|
192
198
|
async loadSoundFont(soundFontUrl) {
|
|
193
199
|
const response = await fetch(soundFontUrl);
|
|
194
200
|
const arrayBuffer = await response.arrayBuffer();
|
|
195
|
-
const parsed = (0,
|
|
196
|
-
const soundFont = new
|
|
201
|
+
const parsed = (0, soundfont_parser_1.parse)(new Uint8Array(arrayBuffer));
|
|
202
|
+
const soundFont = new soundfont_parser_1.SoundFont(parsed);
|
|
197
203
|
this.addSoundFont(soundFont);
|
|
198
204
|
}
|
|
199
205
|
async loadMIDI(midiUrl) {
|
|
200
206
|
const response = await fetch(midiUrl);
|
|
201
207
|
const arrayBuffer = await response.arrayBuffer();
|
|
202
|
-
const midi = (0,
|
|
208
|
+
const midi = (0, midi_file_1.parseMidi)(new Uint8Array(arrayBuffer));
|
|
203
209
|
this.ticksPerBeat = midi.header.ticksPerBeat;
|
|
204
210
|
const midiData = this.extractMidiData(midi);
|
|
205
211
|
this.instruments = midiData.instruments;
|
|
@@ -235,19 +241,25 @@ class MidyGM1 {
|
|
|
235
241
|
const sampleStart = instrumentKey.start;
|
|
236
242
|
const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
|
|
237
243
|
if (isSF3) {
|
|
238
|
-
const sample = instrumentKey.sample
|
|
239
|
-
const
|
|
244
|
+
const sample = instrumentKey.sample;
|
|
245
|
+
const start = sample.byteOffset + sampleStart;
|
|
246
|
+
const end = sample.byteOffset + sampleEnd;
|
|
247
|
+
const buffer = sample.buffer.slice(start, end);
|
|
248
|
+
const audioBuffer = await this.audioContext.decodeAudioData(buffer);
|
|
240
249
|
return audioBuffer;
|
|
241
250
|
}
|
|
242
251
|
else {
|
|
243
|
-
const sample = instrumentKey.sample
|
|
252
|
+
const sample = instrumentKey.sample;
|
|
253
|
+
const start = sample.byteOffset + sampleStart;
|
|
254
|
+
const end = sample.byteOffset + sampleEnd;
|
|
255
|
+
const buffer = sample.buffer.slice(start, end);
|
|
244
256
|
const audioBuffer = new AudioBuffer({
|
|
245
257
|
numberOfChannels: 1,
|
|
246
258
|
length: sample.length,
|
|
247
259
|
sampleRate: instrumentKey.sampleRate,
|
|
248
260
|
});
|
|
249
261
|
const channelData = audioBuffer.getChannelData(0);
|
|
250
|
-
const int16Array = new Int16Array(
|
|
262
|
+
const int16Array = new Int16Array(buffer);
|
|
251
263
|
for (let i = 0; i < int16Array.length; i++) {
|
|
252
264
|
channelData[i] = int16Array[i] / 32768;
|
|
253
265
|
}
|
|
@@ -321,6 +333,7 @@ class MidyGM1 {
|
|
|
321
333
|
if (queueIndex >= this.timeline.length) {
|
|
322
334
|
await Promise.all(this.notePromises);
|
|
323
335
|
this.notePromises = [];
|
|
336
|
+
this.exclusiveClassMap.clear();
|
|
324
337
|
resolve();
|
|
325
338
|
return;
|
|
326
339
|
}
|
|
@@ -336,6 +349,7 @@ class MidyGM1 {
|
|
|
336
349
|
}
|
|
337
350
|
else if (this.isStopping) {
|
|
338
351
|
await this.stopNotes(0, true);
|
|
352
|
+
this.exclusiveClassMap.clear();
|
|
339
353
|
this.notePromises = [];
|
|
340
354
|
resolve();
|
|
341
355
|
this.isStopping = false;
|
|
@@ -344,6 +358,7 @@ class MidyGM1 {
|
|
|
344
358
|
}
|
|
345
359
|
else if (this.isSeeking) {
|
|
346
360
|
this.stopNotes(0, true);
|
|
361
|
+
this.exclusiveClassMap.clear();
|
|
347
362
|
this.startTime = this.audioContext.currentTime;
|
|
348
363
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
349
364
|
offset = this.resumeTime - this.startTime;
|
|
@@ -650,6 +665,19 @@ class MidyGM1 {
|
|
|
650
665
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
651
666
|
note.volumeNode.connect(channel.gainL);
|
|
652
667
|
note.volumeNode.connect(channel.gainR);
|
|
668
|
+
const exclusiveClass = instrumentKey.exclusiveClass;
|
|
669
|
+
if (exclusiveClass !== 0) {
|
|
670
|
+
if (this.exclusiveClassMap.has(exclusiveClass)) {
|
|
671
|
+
const prevEntry = this.exclusiveClassMap.get(exclusiveClass);
|
|
672
|
+
const [prevNote, prevChannelNumber] = prevEntry;
|
|
673
|
+
if (!prevNote.ending) {
|
|
674
|
+
this.scheduleNoteRelease(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
675
|
+
startTime, undefined, // portamentoNoteNumber
|
|
676
|
+
true);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
this.exclusiveClassMap.set(exclusiveClass, [note, channelNumber]);
|
|
680
|
+
}
|
|
653
681
|
const scheduledNotes = channel.scheduledNotes;
|
|
654
682
|
if (scheduledNotes.has(noteNumber)) {
|
|
655
683
|
scheduledNotes.get(noteNumber).push(note);
|
|
@@ -662,15 +690,15 @@ class MidyGM1 {
|
|
|
662
690
|
const now = this.audioContext.currentTime;
|
|
663
691
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
664
692
|
}
|
|
665
|
-
stopNote(
|
|
693
|
+
stopNote(endTime, stopTime, scheduledNotes, index) {
|
|
666
694
|
const note = scheduledNotes[index];
|
|
667
695
|
note.volumeNode.gain
|
|
668
|
-
.cancelScheduledValues(
|
|
669
|
-
.linearRampToValueAtTime(0,
|
|
696
|
+
.cancelScheduledValues(endTime)
|
|
697
|
+
.linearRampToValueAtTime(0, stopTime);
|
|
670
698
|
note.ending = true;
|
|
671
699
|
this.scheduleTask(() => {
|
|
672
700
|
note.bufferSource.loop = false;
|
|
673
|
-
},
|
|
701
|
+
}, stopTime);
|
|
674
702
|
return new Promise((resolve) => {
|
|
675
703
|
note.bufferSource.onended = () => {
|
|
676
704
|
scheduledNotes[index] = null;
|
|
@@ -688,10 +716,10 @@ class MidyGM1 {
|
|
|
688
716
|
}
|
|
689
717
|
resolve();
|
|
690
718
|
};
|
|
691
|
-
note.bufferSource.stop(
|
|
719
|
+
note.bufferSource.stop(stopTime);
|
|
692
720
|
});
|
|
693
721
|
}
|
|
694
|
-
scheduleNoteRelease(channelNumber, noteNumber, _velocity,
|
|
722
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, endTime, force) {
|
|
695
723
|
const channel = this.channels[channelNumber];
|
|
696
724
|
if (!force && channel.sustainPedal)
|
|
697
725
|
return;
|
|
@@ -704,12 +732,13 @@ class MidyGM1 {
|
|
|
704
732
|
continue;
|
|
705
733
|
if (note.ending)
|
|
706
734
|
continue;
|
|
707
|
-
const
|
|
708
|
-
const modRelease =
|
|
735
|
+
const volRelease = endTime + note.instrumentKey.volRelease;
|
|
736
|
+
const modRelease = endTime + note.instrumentKey.modRelease;
|
|
709
737
|
note.filterNode.frequency
|
|
710
|
-
.cancelScheduledValues(
|
|
738
|
+
.cancelScheduledValues(endTime)
|
|
711
739
|
.linearRampToValueAtTime(0, modRelease);
|
|
712
|
-
|
|
740
|
+
const stopTime = Math.min(volRelease, modRelease);
|
|
741
|
+
return this.stopNote(endTime, stopTime, scheduledNotes, i);
|
|
713
742
|
}
|
|
714
743
|
}
|
|
715
744
|
releaseNote(channelNumber, noteNumber, velocity) {
|
package/script/midy-GM2.d.ts
CHANGED
|
@@ -78,6 +78,7 @@ export class MidyGM2 {
|
|
|
78
78
|
timeline: any[];
|
|
79
79
|
instruments: any[];
|
|
80
80
|
notePromises: any[];
|
|
81
|
+
exclusiveClassMap: Map<any, any>;
|
|
81
82
|
defaultOptions: {
|
|
82
83
|
reverbAlgorithm: (audioContext: any) => {
|
|
83
84
|
input: any;
|
|
@@ -203,8 +204,8 @@ export class MidyGM2 {
|
|
|
203
204
|
calcBank(channel: any, channelNumber: any): any;
|
|
204
205
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
|
|
205
206
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, portamento: any): Promise<void>;
|
|
206
|
-
stopNote(
|
|
207
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any,
|
|
207
|
+
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
208
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, portamentoNoteNumber: any, force: any): Promise<any> | undefined;
|
|
208
209
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any, portamentoNoteNumber: any): Promise<any> | undefined;
|
|
209
210
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
210
211
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
|
|
@@ -324,6 +325,8 @@ declare class Note {
|
|
|
324
325
|
modulationDepth: any;
|
|
325
326
|
vibratoLFO: any;
|
|
326
327
|
vibratoDepth: any;
|
|
328
|
+
reverbEffectsSend: any;
|
|
329
|
+
chorusEffectsSend: any;
|
|
327
330
|
noteNumber: any;
|
|
328
331
|
velocity: any;
|
|
329
332
|
startTime: 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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"}
|