@marmooo/midy 0.2.8 → 0.3.0
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 +15 -9
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +112 -58
- package/esm/midy-GM2.d.ts +24 -15
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +311 -102
- package/esm/midy-GMLite.d.ts +17 -8
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +159 -55
- package/esm/midy.d.ts +24 -15
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +352 -113
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +15 -9
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +112 -58
- package/script/midy-GM2.d.ts +24 -15
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +311 -102
- package/script/midy-GMLite.d.ts +17 -8
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +159 -55
- package/script/midy.d.ts +24 -15
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +352 -113
package/package.json
CHANGED
package/script/midy-GM1.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
export class MidyGM1 {
|
|
2
2
|
static channelSettings: {
|
|
3
|
-
currentBufferSource: null;
|
|
4
3
|
detune: number;
|
|
5
|
-
|
|
4
|
+
programNumber: number;
|
|
6
5
|
bank: number;
|
|
7
6
|
dataMSB: number;
|
|
8
7
|
dataLSB: number;
|
|
9
8
|
rpnMSB: number;
|
|
10
9
|
rpnLSB: number;
|
|
10
|
+
modulationDepthRange: number;
|
|
11
11
|
fineTuning: number;
|
|
12
12
|
coarseTuning: number;
|
|
13
|
-
modulationDepthRange: number;
|
|
14
13
|
};
|
|
15
14
|
constructor(audioContext: any);
|
|
15
|
+
mode: string;
|
|
16
|
+
numChannels: number;
|
|
16
17
|
ticksPerBeat: number;
|
|
17
18
|
totalTime: number;
|
|
18
19
|
noteCheckInterval: number;
|
|
@@ -32,9 +33,11 @@ export class MidyGM1 {
|
|
|
32
33
|
timeline: any[];
|
|
33
34
|
instruments: any[];
|
|
34
35
|
notePromises: any[];
|
|
35
|
-
|
|
36
|
+
exclusiveClassNotes: any[];
|
|
36
37
|
audioContext: any;
|
|
37
38
|
masterVolume: any;
|
|
39
|
+
scheduler: any;
|
|
40
|
+
schedulerBuffer: any;
|
|
38
41
|
voiceParamsHandlers: {
|
|
39
42
|
modLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
|
|
40
43
|
vibLfoToPitch: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
|
|
@@ -73,7 +76,7 @@ export class MidyGM1 {
|
|
|
73
76
|
};
|
|
74
77
|
createChannels(audioContext: any): any[];
|
|
75
78
|
createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
|
|
76
|
-
|
|
79
|
+
createBufferSource(audioBuffer: any, voiceParams: any): any;
|
|
77
80
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
78
81
|
getQueueIndex(second: any): number;
|
|
79
82
|
playNotes(): Promise<any>;
|
|
@@ -108,16 +111,18 @@ export class MidyGM1 {
|
|
|
108
111
|
clampCutoffFrequency(frequency: any): number;
|
|
109
112
|
setFilterEnvelope(note: any, scheduleTime: any): void;
|
|
110
113
|
startModulation(channel: any, note: any, scheduleTime: any): void;
|
|
111
|
-
getAudioBuffer(
|
|
114
|
+
getAudioBuffer(programNumber: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
|
|
112
115
|
createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
116
|
+
handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
113
117
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
114
118
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
|
|
119
|
+
disconnectNote(note: any, scheduledNotes: any, index: any): void;
|
|
115
120
|
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
116
121
|
scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): Promise<any> | undefined;
|
|
117
122
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
|
|
118
123
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
|
|
119
124
|
handleMIDIMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
|
|
120
|
-
handleProgramChange(channelNumber: any,
|
|
125
|
+
handleProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
|
|
121
126
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
|
|
122
127
|
setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
|
|
123
128
|
setModLfoToPitch(channel: any, note: any, scheduleTime: any): void;
|
|
@@ -179,10 +184,11 @@ export class MidyGM1 {
|
|
|
179
184
|
handleCoarseTuningRPN(channelNumber: any, scheduleTime: any): void;
|
|
180
185
|
setCoarseTuning(channelNumber: any, value: any, scheduleTime: any): void;
|
|
181
186
|
allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
187
|
+
resetAllStates(channelNumber: any): void;
|
|
182
188
|
resetAllControllers(channelNumber: any): void;
|
|
183
189
|
allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
184
|
-
handleUniversalNonRealTimeExclusiveMessage(data: any,
|
|
185
|
-
GM1SystemOn(): void;
|
|
190
|
+
handleUniversalNonRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
191
|
+
GM1SystemOn(scheduleTime: any): void;
|
|
186
192
|
handleUniversalRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
187
193
|
handleMasterVolumeSysEx(data: any, scheduleTime: any): void;
|
|
188
194
|
setMasterVolume(volume: any, scheduleTime: 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":"AAiJA;
|
|
1
|
+
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAiJA;IAwBE;;;;;;;;;;;MAWE;IAEF,+BAcC;IAlDD,aAAa;IACb,oBAAiB;IACjB,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,2BAAqC;IAgBnC,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAMnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAaC;IAED,6DA2BC;IAED,4DASC;IAED,2EAsDC;IAED,mCAOC;IAED,0BAoDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MA4EC;IAED,mGAgBC;IAED,wEAMC;IAED,uBAKC;IAED,aAMC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,2DASC;IAED,qDAQC;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,+GA0BC;IAED,gHAwCC;IAED,0EAiBC;IAED,kGAqCC;IAED,6FAQC;IAED,iEAUC;IAED,qFAgBC;IAED,yHAuBC;IAED,yGASC;IAED,4GAeC;IAED,mGA2BC;IAED,sFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAQC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MA2BC;IAED,oFAMC;IAED,6EA2CC;IAED;;;;;;;;;;;;;MAeC;IAED,kGAWC;IAED,wDAUC;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,iEAKC;IAED,uEAQC;IAED,mEAKC;IAED,yEAQC;IAED,gFAGC;IAED,yCAUC;IAGD,8CAqBC;IAED,gFAGC;IAED,+EAgBC;IAED,qCAWC;IAED,4EAaC;IAED,4DAGC;IAED,sDASC;IAED,gDAYC;IAGD,6DAgBC;CACF;AA99CD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IASE,0FAMC;IAdD,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/script/midy-GM1.js
CHANGED
|
@@ -173,6 +173,18 @@ const volumeEnvelopeKeys = [
|
|
|
173
173
|
const volumeEnvelopeKeySet = new Set(volumeEnvelopeKeys);
|
|
174
174
|
class MidyGM1 {
|
|
175
175
|
constructor(audioContext) {
|
|
176
|
+
Object.defineProperty(this, "mode", {
|
|
177
|
+
enumerable: true,
|
|
178
|
+
configurable: true,
|
|
179
|
+
writable: true,
|
|
180
|
+
value: "GM1"
|
|
181
|
+
});
|
|
182
|
+
Object.defineProperty(this, "numChannels", {
|
|
183
|
+
enumerable: true,
|
|
184
|
+
configurable: true,
|
|
185
|
+
writable: true,
|
|
186
|
+
value: 16
|
|
187
|
+
});
|
|
176
188
|
Object.defineProperty(this, "ticksPerBeat", {
|
|
177
189
|
enumerable: true,
|
|
178
190
|
configurable: true,
|
|
@@ -287,18 +299,24 @@ class MidyGM1 {
|
|
|
287
299
|
writable: true,
|
|
288
300
|
value: []
|
|
289
301
|
});
|
|
290
|
-
Object.defineProperty(this, "
|
|
302
|
+
Object.defineProperty(this, "exclusiveClassNotes", {
|
|
291
303
|
enumerable: true,
|
|
292
304
|
configurable: true,
|
|
293
305
|
writable: true,
|
|
294
|
-
value: new
|
|
306
|
+
value: new Array(128)
|
|
295
307
|
});
|
|
296
308
|
this.audioContext = audioContext;
|
|
297
309
|
this.masterVolume = new GainNode(audioContext);
|
|
310
|
+
this.scheduler = new GainNode(audioContext, { gain: 0 });
|
|
311
|
+
this.schedulerBuffer = new AudioBuffer({
|
|
312
|
+
length: 1,
|
|
313
|
+
sampleRate: audioContext.sampleRate,
|
|
314
|
+
});
|
|
298
315
|
this.voiceParamsHandlers = this.createVoiceParamsHandlers();
|
|
299
316
|
this.controlChangeHandlers = this.createControlChangeHandlers();
|
|
300
317
|
this.channels = this.createChannels(audioContext);
|
|
301
318
|
this.masterVolume.connect(audioContext.destination);
|
|
319
|
+
this.scheduler.connect(audioContext.destination);
|
|
302
320
|
this.GM1SystemOn();
|
|
303
321
|
}
|
|
304
322
|
initSoundFontTable() {
|
|
@@ -352,8 +370,10 @@ class MidyGM1 {
|
|
|
352
370
|
};
|
|
353
371
|
}
|
|
354
372
|
createChannels(audioContext) {
|
|
355
|
-
const channels = Array.from({ length:
|
|
373
|
+
const channels = Array.from({ length: this.numChannels }, () => {
|
|
356
374
|
return {
|
|
375
|
+
currentBufferSource: null,
|
|
376
|
+
isDrum: false,
|
|
357
377
|
...this.constructor.channelSettings,
|
|
358
378
|
state: new ControllerState(),
|
|
359
379
|
...this.setChannelAudioNodes(audioContext),
|
|
@@ -392,7 +412,7 @@ class MidyGM1 {
|
|
|
392
412
|
return audioBuffer;
|
|
393
413
|
}
|
|
394
414
|
}
|
|
395
|
-
|
|
415
|
+
createBufferSource(audioBuffer, voiceParams) {
|
|
396
416
|
const bufferSource = new AudioBufferSourceNode(this.audioContext);
|
|
397
417
|
bufferSource.buffer = audioBuffer;
|
|
398
418
|
bufferSource.loop = voiceParams.sampleModes % 2 !== 0;
|
|
@@ -458,7 +478,7 @@ class MidyGM1 {
|
|
|
458
478
|
if (queueIndex >= this.timeline.length) {
|
|
459
479
|
await Promise.all(this.notePromises);
|
|
460
480
|
this.notePromises = [];
|
|
461
|
-
this.
|
|
481
|
+
this.exclusiveClassNotes.flll(undefined);
|
|
462
482
|
this.audioBufferCache.clear();
|
|
463
483
|
resolve();
|
|
464
484
|
return;
|
|
@@ -477,7 +497,7 @@ class MidyGM1 {
|
|
|
477
497
|
else if (this.isStopping) {
|
|
478
498
|
await this.stopNotes(0, true, now);
|
|
479
499
|
this.notePromises = [];
|
|
480
|
-
this.
|
|
500
|
+
this.exclusiveClassNotes.fill(undefined);
|
|
481
501
|
this.audioBufferCache.clear();
|
|
482
502
|
resolve();
|
|
483
503
|
this.isStopping = false;
|
|
@@ -486,7 +506,7 @@ class MidyGM1 {
|
|
|
486
506
|
}
|
|
487
507
|
else if (this.isSeeking) {
|
|
488
508
|
this.stopNotes(0, true, now);
|
|
489
|
-
this.
|
|
509
|
+
this.exclusiveClassNotes.fill(undefined);
|
|
490
510
|
this.startTime = this.audioContext.currentTime;
|
|
491
511
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
492
512
|
offset = this.resumeTime - this.startTime;
|
|
@@ -514,7 +534,7 @@ class MidyGM1 {
|
|
|
514
534
|
extractMidiData(midi) {
|
|
515
535
|
const instruments = new Set();
|
|
516
536
|
const timeline = [];
|
|
517
|
-
const tmpChannels = new Array(
|
|
537
|
+
const tmpChannels = new Array(this.channels.length);
|
|
518
538
|
for (let i = 0; i < tmpChannels.length; i++) {
|
|
519
539
|
tmpChannels[i] = {
|
|
520
540
|
programNumber: -1,
|
|
@@ -606,6 +626,9 @@ class MidyGM1 {
|
|
|
606
626
|
if (!this.isPlaying)
|
|
607
627
|
return;
|
|
608
628
|
this.isStopping = true;
|
|
629
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
630
|
+
this.resetAllStates(i);
|
|
631
|
+
}
|
|
609
632
|
}
|
|
610
633
|
pause() {
|
|
611
634
|
if (!this.isPlaying || this.isPaused)
|
|
@@ -783,8 +806,8 @@ class MidyGM1 {
|
|
|
783
806
|
note.modulationLFO.connect(note.volumeDepth);
|
|
784
807
|
note.volumeDepth.connect(note.volumeEnvelopeNode.gain);
|
|
785
808
|
}
|
|
786
|
-
async getAudioBuffer(
|
|
787
|
-
const audioBufferId = this.getAudioBufferId(
|
|
809
|
+
async getAudioBuffer(programNumber, noteNumber, velocity, voiceParams, isSF3) {
|
|
810
|
+
const audioBufferId = this.getAudioBufferId(programNumber, noteNumber, velocity);
|
|
788
811
|
const cache = this.audioBufferCache.get(audioBufferId);
|
|
789
812
|
if (cache) {
|
|
790
813
|
cache.counter += 1;
|
|
@@ -807,8 +830,8 @@ class MidyGM1 {
|
|
|
807
830
|
const controllerState = this.getControllerState(channel, noteNumber, velocity);
|
|
808
831
|
const voiceParams = voice.getAllParams(controllerState);
|
|
809
832
|
const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
|
|
810
|
-
const audioBuffer = await this.getAudioBuffer(channel.
|
|
811
|
-
note.bufferSource = this.
|
|
833
|
+
const audioBuffer = await this.getAudioBuffer(channel.programNumber, noteNumber, velocity, voiceParams, isSF3);
|
|
834
|
+
note.bufferSource = this.createBufferSource(audioBuffer, voiceParams);
|
|
812
835
|
note.volumeEnvelopeNode = new GainNode(this.audioContext);
|
|
813
836
|
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
814
837
|
type: "lowpass",
|
|
@@ -825,14 +848,28 @@ class MidyGM1 {
|
|
|
825
848
|
note.bufferSource.start(startTime);
|
|
826
849
|
return note;
|
|
827
850
|
}
|
|
851
|
+
handleExclusiveClass(note, channelNumber, startTime) {
|
|
852
|
+
const exclusiveClass = note.voiceParams.exclusiveClass;
|
|
853
|
+
if (exclusiveClass === 0)
|
|
854
|
+
return;
|
|
855
|
+
const prev = this.exclusiveClassNotes[exclusiveClass];
|
|
856
|
+
if (prev) {
|
|
857
|
+
const [prevNote, prevChannelNumber] = prev;
|
|
858
|
+
if (prevNote && !prevNote.ending) {
|
|
859
|
+
this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
860
|
+
startTime, true);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
this.exclusiveClassNotes[exclusiveClass] = [note, channelNumber];
|
|
864
|
+
}
|
|
828
865
|
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
|
|
829
866
|
const channel = this.channels[channelNumber];
|
|
830
867
|
const bankNumber = channel.bank;
|
|
831
|
-
const soundFontIndex = this.soundFontTable[channel.
|
|
868
|
+
const soundFontIndex = this.soundFontTable[channel.programNumber].get(bankNumber);
|
|
832
869
|
if (soundFontIndex === undefined)
|
|
833
870
|
return;
|
|
834
871
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
835
|
-
const voice = soundFont.getVoice(bankNumber, channel.
|
|
872
|
+
const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
|
|
836
873
|
if (!voice)
|
|
837
874
|
return;
|
|
838
875
|
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
@@ -842,30 +879,31 @@ class MidyGM1 {
|
|
|
842
879
|
if (0.5 <= channel.state.sustainPedal) {
|
|
843
880
|
channel.sustainNotes.push(note);
|
|
844
881
|
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
const [prevNote, prevChannelNumber] = prevEntry;
|
|
850
|
-
if (!prevNote.ending) {
|
|
851
|
-
this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
852
|
-
startTime, true);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
this.exclusiveClassMap.set(exclusiveClass, [note, channelNumber]);
|
|
856
|
-
}
|
|
857
|
-
const scheduledNotes = channel.scheduledNotes;
|
|
858
|
-
if (scheduledNotes.has(noteNumber)) {
|
|
859
|
-
scheduledNotes.get(noteNumber).push(note);
|
|
882
|
+
this.handleExclusiveClass(note, channelNumber, startTime);
|
|
883
|
+
let notes = scheduledNotes.get(noteNumber);
|
|
884
|
+
if (notes) {
|
|
885
|
+
notes.push(note);
|
|
860
886
|
}
|
|
861
887
|
else {
|
|
862
|
-
|
|
888
|
+
notes = [note];
|
|
889
|
+
scheduledNotes.set(noteNumber, notes);
|
|
863
890
|
}
|
|
864
891
|
}
|
|
865
892
|
noteOn(channelNumber, noteNumber, velocity, scheduleTime) {
|
|
866
893
|
scheduleTime ??= this.audioContext.currentTime;
|
|
867
894
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime);
|
|
868
895
|
}
|
|
896
|
+
disconnectNote(note, scheduledNotes, index) {
|
|
897
|
+
scheduledNotes[index] = null;
|
|
898
|
+
note.bufferSource.disconnect();
|
|
899
|
+
note.filterNode.disconnect();
|
|
900
|
+
note.volumeEnvelopeNode.disconnect();
|
|
901
|
+
if (note.modulationDepth) {
|
|
902
|
+
note.volumeDepth.disconnect();
|
|
903
|
+
note.modulationDepth.disconnect();
|
|
904
|
+
note.modulationLFO.stop();
|
|
905
|
+
}
|
|
906
|
+
}
|
|
869
907
|
stopNote(endTime, stopTime, scheduledNotes, index) {
|
|
870
908
|
const note = scheduledNotes[index];
|
|
871
909
|
note.volumeEnvelopeNode.gain
|
|
@@ -877,15 +915,7 @@ class MidyGM1 {
|
|
|
877
915
|
}, stopTime);
|
|
878
916
|
return new Promise((resolve) => {
|
|
879
917
|
note.bufferSource.onended = () => {
|
|
880
|
-
scheduledNotes
|
|
881
|
-
note.bufferSource.disconnect();
|
|
882
|
-
note.filterNode.disconnect();
|
|
883
|
-
note.volumeEnvelopeNode.disconnect();
|
|
884
|
-
if (note.modulationDepth) {
|
|
885
|
-
note.volumeDepth.disconnect();
|
|
886
|
-
note.modulationDepth.disconnect();
|
|
887
|
-
note.modulationLFO.stop();
|
|
888
|
-
}
|
|
918
|
+
this.disconnectNote(note, scheduledNotes, index);
|
|
889
919
|
resolve();
|
|
890
920
|
};
|
|
891
921
|
note.bufferSource.stop(stopTime);
|
|
@@ -946,17 +976,17 @@ class MidyGM1 {
|
|
|
946
976
|
console.warn(`Unsupported MIDI message: ${messageType.toString(16)}`);
|
|
947
977
|
}
|
|
948
978
|
}
|
|
949
|
-
handleProgramChange(channelNumber,
|
|
979
|
+
handleProgramChange(channelNumber, programNumber, _scheduleTime) {
|
|
950
980
|
const channel = this.channels[channelNumber];
|
|
951
|
-
channel.
|
|
981
|
+
channel.programNumber = programNumber;
|
|
952
982
|
}
|
|
953
983
|
handlePitchBendMessage(channelNumber, lsb, msb, scheduleTime) {
|
|
954
984
|
const pitchBend = msb * 128 + lsb;
|
|
955
985
|
this.setPitchBend(channelNumber, pitchBend, scheduleTime);
|
|
956
986
|
}
|
|
957
987
|
setPitchBend(channelNumber, value, scheduleTime) {
|
|
958
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
959
988
|
const channel = this.channels[channelNumber];
|
|
989
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
960
990
|
const state = channel.state;
|
|
961
991
|
const prev = state.pitchWheel * 2 - 1;
|
|
962
992
|
const next = (value - 8192) / 8192;
|
|
@@ -1117,8 +1147,8 @@ class MidyGM1 {
|
|
|
1117
1147
|
});
|
|
1118
1148
|
}
|
|
1119
1149
|
setModulationDepth(channelNumber, modulation, scheduleTime) {
|
|
1120
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1121
1150
|
const channel = this.channels[channelNumber];
|
|
1151
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1122
1152
|
channel.state.modulationDepth = modulation / 127;
|
|
1123
1153
|
this.updateModulation(channel, scheduleTime);
|
|
1124
1154
|
}
|
|
@@ -1163,8 +1193,8 @@ class MidyGM1 {
|
|
|
1163
1193
|
.setValueAtTime(volume * gainRight, scheduleTime);
|
|
1164
1194
|
}
|
|
1165
1195
|
setSustainPedal(channelNumber, value, scheduleTime) {
|
|
1166
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1167
1196
|
const channel = this.channels[channelNumber];
|
|
1197
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1168
1198
|
channel.state.sustainPedal = value / 127;
|
|
1169
1199
|
if (64 <= value) {
|
|
1170
1200
|
this.processScheduledNotes(channel, (note) => {
|
|
@@ -1235,8 +1265,8 @@ class MidyGM1 {
|
|
|
1235
1265
|
this.setPitchBendRange(channelNumber, pitchBendRange, scheduleTime);
|
|
1236
1266
|
}
|
|
1237
1267
|
setPitchBendRange(channelNumber, value, scheduleTime) {
|
|
1238
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1239
1268
|
const channel = this.channels[channelNumber];
|
|
1269
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1240
1270
|
const state = channel.state;
|
|
1241
1271
|
const prev = state.pitchWheelSensitivity;
|
|
1242
1272
|
const next = value / 128;
|
|
@@ -1252,8 +1282,8 @@ class MidyGM1 {
|
|
|
1252
1282
|
this.setFineTuning(channelNumber, fineTuning, scheduleTime);
|
|
1253
1283
|
}
|
|
1254
1284
|
setFineTuning(channelNumber, value, scheduleTime) {
|
|
1255
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1256
1285
|
const channel = this.channels[channelNumber];
|
|
1286
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1257
1287
|
const prev = channel.fineTuning;
|
|
1258
1288
|
const next = (value - 8192) / 8.192; // cent
|
|
1259
1289
|
channel.fineTuning = next;
|
|
@@ -1267,8 +1297,8 @@ class MidyGM1 {
|
|
|
1267
1297
|
this.setCoarseTuning(channelNumber, coarseTuning, scheduleTime);
|
|
1268
1298
|
}
|
|
1269
1299
|
setCoarseTuning(channelNumber, value, scheduleTime) {
|
|
1270
|
-
scheduleTime ??= this.audioContext.currentTime;
|
|
1271
1300
|
const channel = this.channels[channelNumber];
|
|
1301
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1272
1302
|
const prev = channel.coarseTuning;
|
|
1273
1303
|
const next = (value - 64) * 100; // cent
|
|
1274
1304
|
channel.coarseTuning = next;
|
|
@@ -1279,12 +1309,24 @@ class MidyGM1 {
|
|
|
1279
1309
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1280
1310
|
return this.stopChannelNotes(channelNumber, 0, true, scheduleTime);
|
|
1281
1311
|
}
|
|
1312
|
+
resetAllStates(channelNumber) {
|
|
1313
|
+
const channel = this.channels[channelNumber];
|
|
1314
|
+
const state = channel.state;
|
|
1315
|
+
for (const type of Object.keys(defaultControllerState)) {
|
|
1316
|
+
state[type] = defaultControllerState[type].defaultValue;
|
|
1317
|
+
}
|
|
1318
|
+
for (const type of Object.keys(this.constructor.channelSettings)) {
|
|
1319
|
+
channel[type] = this.constructor.channelSettings[type];
|
|
1320
|
+
}
|
|
1321
|
+
this.mode = "GM1";
|
|
1322
|
+
}
|
|
1323
|
+
// https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
|
|
1282
1324
|
resetAllControllers(channelNumber) {
|
|
1283
1325
|
const stateTypes = [
|
|
1326
|
+
"pitchWheel",
|
|
1284
1327
|
"expression",
|
|
1285
1328
|
"modulationDepth",
|
|
1286
1329
|
"sustainPedal",
|
|
1287
|
-
"pitchWheelSensitivity",
|
|
1288
1330
|
];
|
|
1289
1331
|
const channel = this.channels[channelNumber];
|
|
1290
1332
|
const state = channel.state;
|
|
@@ -1305,12 +1347,12 @@ class MidyGM1 {
|
|
|
1305
1347
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1306
1348
|
return this.stopChannelNotes(channelNumber, 0, false, scheduleTime);
|
|
1307
1349
|
}
|
|
1308
|
-
handleUniversalNonRealTimeExclusiveMessage(data,
|
|
1350
|
+
handleUniversalNonRealTimeExclusiveMessage(data, scheduleTime) {
|
|
1309
1351
|
switch (data[2]) {
|
|
1310
1352
|
case 9:
|
|
1311
1353
|
switch (data[3]) {
|
|
1312
1354
|
case 1:
|
|
1313
|
-
this.GM1SystemOn();
|
|
1355
|
+
this.GM1SystemOn(scheduleTime);
|
|
1314
1356
|
break;
|
|
1315
1357
|
case 2: // GM System Off
|
|
1316
1358
|
break;
|
|
@@ -1322,12 +1364,17 @@ class MidyGM1 {
|
|
|
1322
1364
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1323
1365
|
}
|
|
1324
1366
|
}
|
|
1325
|
-
GM1SystemOn() {
|
|
1367
|
+
GM1SystemOn(scheduleTime) {
|
|
1368
|
+
scheduleTime ??= this.audioContext.currentTime;
|
|
1369
|
+
this.mode = "GM1";
|
|
1326
1370
|
for (let i = 0; i < this.channels.length; i++) {
|
|
1371
|
+
this.allSoundOff(i, 0, scheduleTime);
|
|
1327
1372
|
const channel = this.channels[i];
|
|
1328
1373
|
channel.bank = 0;
|
|
1374
|
+
channel.isDrum = false;
|
|
1329
1375
|
}
|
|
1330
1376
|
this.channels[9].bank = 128;
|
|
1377
|
+
this.channels[9].isDrum = true;
|
|
1331
1378
|
}
|
|
1332
1379
|
handleUniversalRealTimeExclusiveMessage(data, scheduleTime) {
|
|
1333
1380
|
switch (data[2]) {
|
|
@@ -1368,15 +1415,23 @@ class MidyGM1 {
|
|
|
1368
1415
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1369
1416
|
}
|
|
1370
1417
|
}
|
|
1418
|
+
// https://github.com/marmooo/js-timer-benchmark
|
|
1371
1419
|
scheduleTask(callback, scheduleTime) {
|
|
1372
1420
|
return new Promise((resolve) => {
|
|
1373
|
-
const bufferSource = new AudioBufferSourceNode(this.audioContext
|
|
1421
|
+
const bufferSource = new AudioBufferSourceNode(this.audioContext, {
|
|
1422
|
+
buffer: this.schedulerBuffer,
|
|
1423
|
+
});
|
|
1424
|
+
bufferSource.connect(this.scheduler);
|
|
1374
1425
|
bufferSource.onended = () => {
|
|
1375
|
-
|
|
1376
|
-
|
|
1426
|
+
try {
|
|
1427
|
+
callback();
|
|
1428
|
+
}
|
|
1429
|
+
finally {
|
|
1430
|
+
bufferSource.disconnect();
|
|
1431
|
+
resolve();
|
|
1432
|
+
}
|
|
1377
1433
|
};
|
|
1378
1434
|
bufferSource.start(scheduleTime);
|
|
1379
|
-
bufferSource.stop(scheduleTime);
|
|
1380
1435
|
});
|
|
1381
1436
|
}
|
|
1382
1437
|
}
|
|
@@ -1386,16 +1441,15 @@ Object.defineProperty(MidyGM1, "channelSettings", {
|
|
|
1386
1441
|
configurable: true,
|
|
1387
1442
|
writable: true,
|
|
1388
1443
|
value: {
|
|
1389
|
-
currentBufferSource: null,
|
|
1390
1444
|
detune: 0,
|
|
1391
|
-
|
|
1445
|
+
programNumber: 0,
|
|
1392
1446
|
bank: 0,
|
|
1393
1447
|
dataMSB: 0,
|
|
1394
1448
|
dataLSB: 0,
|
|
1395
1449
|
rpnMSB: 127,
|
|
1396
1450
|
rpnLSB: 127,
|
|
1451
|
+
modulationDepthRange: 50, // cent
|
|
1397
1452
|
fineTuning: 0, // cb
|
|
1398
1453
|
coarseTuning: 0, // cb
|
|
1399
|
-
modulationDepthRange: 50, // cent
|
|
1400
1454
|
}
|
|
1401
1455
|
});
|
package/script/midy-GM2.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export class MidyGM2 {
|
|
2
2
|
static channelSettings: {
|
|
3
|
-
currentBufferSource: null;
|
|
4
3
|
detune: number;
|
|
5
|
-
|
|
4
|
+
programNumber: number;
|
|
6
5
|
bank: number;
|
|
7
6
|
bankMSB: number;
|
|
8
7
|
bankLSB: number;
|
|
@@ -11,9 +10,9 @@ export class MidyGM2 {
|
|
|
11
10
|
rpnMSB: number;
|
|
12
11
|
rpnLSB: number;
|
|
13
12
|
mono: boolean;
|
|
13
|
+
modulationDepthRange: number;
|
|
14
14
|
fineTuning: number;
|
|
15
15
|
coarseTuning: number;
|
|
16
|
-
modulationDepthRange: number;
|
|
17
16
|
};
|
|
18
17
|
constructor(audioContext: any, options?: {
|
|
19
18
|
reverbAlgorithm: (audioContext: any) => {
|
|
@@ -21,8 +20,7 @@ export class MidyGM2 {
|
|
|
21
20
|
output: any;
|
|
22
21
|
};
|
|
23
22
|
});
|
|
24
|
-
|
|
25
|
-
totalTime: number;
|
|
23
|
+
mode: string;
|
|
26
24
|
masterFineTuning: number;
|
|
27
25
|
masterCoarseTuning: number;
|
|
28
26
|
reverb: {
|
|
@@ -36,6 +34,9 @@ export class MidyGM2 {
|
|
|
36
34
|
sendToReverb: number;
|
|
37
35
|
delayTimes: any[];
|
|
38
36
|
};
|
|
37
|
+
numChannels: number;
|
|
38
|
+
ticksPerBeat: number;
|
|
39
|
+
totalTime: number;
|
|
39
40
|
noteCheckInterval: number;
|
|
40
41
|
lookAhead: number;
|
|
41
42
|
startDelay: number;
|
|
@@ -53,7 +54,8 @@ export class MidyGM2 {
|
|
|
53
54
|
timeline: any[];
|
|
54
55
|
instruments: any[];
|
|
55
56
|
notePromises: any[];
|
|
56
|
-
|
|
57
|
+
exclusiveClassNotes: any[];
|
|
58
|
+
drumExclusiveClassNotes: any[];
|
|
57
59
|
defaultOptions: {
|
|
58
60
|
reverbAlgorithm: (audioContext: any) => {
|
|
59
61
|
input: any;
|
|
@@ -68,6 +70,8 @@ export class MidyGM2 {
|
|
|
68
70
|
};
|
|
69
71
|
};
|
|
70
72
|
masterVolume: any;
|
|
73
|
+
scheduler: any;
|
|
74
|
+
schedulerBuffer: any;
|
|
71
75
|
voiceParamsHandlers: {
|
|
72
76
|
modLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
|
|
73
77
|
vibLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
|
|
@@ -93,7 +97,7 @@ export class MidyGM2 {
|
|
|
93
97
|
64: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
94
98
|
65: (channelNumber: any, value: any) => void;
|
|
95
99
|
66: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
96
|
-
67: (channelNumber: any, softPedal: any,
|
|
100
|
+
67: (channelNumber: any, softPedal: any, scheduleTime: any) => void;
|
|
97
101
|
91: (channelNumber: any, reverbSendLevel: any, scheduleTime: any) => void;
|
|
98
102
|
93: (channelNumber: any, chorusSendLevel: any, scheduleTime: any) => void;
|
|
99
103
|
100: (channelNumber: any, value: any) => void;
|
|
@@ -131,7 +135,7 @@ export class MidyGM2 {
|
|
|
131
135
|
};
|
|
132
136
|
createChannels(audioContext: any): any[];
|
|
133
137
|
createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
|
|
134
|
-
|
|
138
|
+
createBufferSource(voiceParams: any, audioBuffer: any): any;
|
|
135
139
|
findPortamentoTarget(queueIndex: any): any;
|
|
136
140
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
137
141
|
getQueueIndex(second: any): number;
|
|
@@ -194,18 +198,22 @@ export class MidyGM2 {
|
|
|
194
198
|
setFilterEnvelope(channel: any, note: any, scheduleTime: any): void;
|
|
195
199
|
startModulation(channel: any, note: any, scheduleTime: any): void;
|
|
196
200
|
startVibrato(channel: any, note: any, scheduleTime: any): void;
|
|
197
|
-
getAudioBuffer(
|
|
201
|
+
getAudioBuffer(programNumber: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
|
|
198
202
|
createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
|
|
199
|
-
calcBank(channel: any
|
|
203
|
+
calcBank(channel: any): any;
|
|
204
|
+
handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
205
|
+
handleDrumExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
206
|
+
isDrumNoteOffException(channel: any, noteNumber: any): boolean;
|
|
200
207
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
|
|
201
208
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
|
|
209
|
+
disconnectNote(note: any, scheduledNotes: any, index: any): void;
|
|
202
210
|
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
203
211
|
scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any, portamentoNoteNumber: any): Promise<any> | undefined;
|
|
204
212
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
|
|
205
213
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
|
|
206
214
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): any[];
|
|
207
215
|
handleMIDIMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
|
|
208
|
-
handleProgramChange(channelNumber: any,
|
|
216
|
+
handleProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
|
|
209
217
|
handleChannelPressure(channelNumber: any, value: any, scheduleTime: any): void;
|
|
210
218
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
|
|
211
219
|
setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
|
|
@@ -245,7 +253,7 @@ export class MidyGM2 {
|
|
|
245
253
|
64: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
246
254
|
65: (channelNumber: any, value: any) => void;
|
|
247
255
|
66: (channelNumber: any, value: any, scheduleTime: any) => void;
|
|
248
|
-
67: (channelNumber: any, softPedal: any,
|
|
256
|
+
67: (channelNumber: any, softPedal: any, scheduleTime: any) => void;
|
|
249
257
|
91: (channelNumber: any, reverbSendLevel: any, scheduleTime: any) => void;
|
|
250
258
|
93: (channelNumber: any, chorusSendLevel: any, scheduleTime: any) => void;
|
|
251
259
|
100: (channelNumber: any, value: any) => void;
|
|
@@ -278,7 +286,7 @@ export class MidyGM2 {
|
|
|
278
286
|
setSustainPedal(channelNumber: any, value: any, scheduleTime: any): void;
|
|
279
287
|
setPortamento(channelNumber: any, value: any): void;
|
|
280
288
|
setSostenutoPedal(channelNumber: any, value: any, scheduleTime: any): void;
|
|
281
|
-
setSoftPedal(channelNumber: any, softPedal: any,
|
|
289
|
+
setSoftPedal(channelNumber: any, softPedal: any, scheduleTime: any): void;
|
|
282
290
|
setReverbSendLevel(channelNumber: any, reverbSendLevel: any, scheduleTime: any): void;
|
|
283
291
|
setChorusSendLevel(channelNumber: any, chorusSendLevel: any, scheduleTime: any): void;
|
|
284
292
|
limitData(channel: any, minMSB: any, maxMSB: any, minLSB: any, maxLSB: any): void;
|
|
@@ -296,6 +304,7 @@ export class MidyGM2 {
|
|
|
296
304
|
handleModulationDepthRangeRPN(channelNumber: any, scheduleTime: any): void;
|
|
297
305
|
setModulationDepthRange(channelNumber: any, modulationDepthRange: any, scheduleTime: any): void;
|
|
298
306
|
allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
307
|
+
resetAllStates(channelNumber: any): void;
|
|
299
308
|
resetAllControllers(channelNumber: any): void;
|
|
300
309
|
allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
301
310
|
omniOff(channelNumber: any, value: any, scheduleTime: any): void;
|
|
@@ -303,8 +312,8 @@ export class MidyGM2 {
|
|
|
303
312
|
monoOn(channelNumber: any, value: any, scheduleTime: any): void;
|
|
304
313
|
polyOn(channelNumber: any, value: any, scheduleTime: any): void;
|
|
305
314
|
handleUniversalNonRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
306
|
-
GM1SystemOn(): void;
|
|
307
|
-
GM2SystemOn(): void;
|
|
315
|
+
GM1SystemOn(scheduleTime: any): void;
|
|
316
|
+
GM2SystemOn(scheduleTime: any): void;
|
|
308
317
|
handleUniversalRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
|
309
318
|
handleMasterVolumeSysEx(data: any, scheduleTime: any): void;
|
|
310
319
|
setMasterVolume(volume: any, scheduleTime: any): void;
|
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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"}
|