@marmooo/midy 0.2.9 → 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 +8 -6
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +72 -55
- package/esm/midy-GM2.d.ts +14 -10
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +189 -87
- package/esm/midy-GMLite.d.ts +11 -8
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +124 -61
- package/esm/midy.d.ts +14 -10
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +190 -87
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +8 -6
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +72 -55
- package/script/midy-GM2.d.ts +14 -10
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +189 -87
- package/script/midy-GMLite.d.ts +11 -8
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +124 -61
- package/script/midy.d.ts +14 -10
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +190 -87
package/esm/midy-GM2.js
CHANGED
|
@@ -151,6 +151,39 @@ class Note {
|
|
|
151
151
|
this.voiceParams = voiceParams;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
+
const drumExclusiveClassesByKit = new Array(57);
|
|
155
|
+
const drumExclusiveClassCount = 10;
|
|
156
|
+
const standardSet = new Uint8Array(128);
|
|
157
|
+
standardSet[42] = 1;
|
|
158
|
+
standardSet[44] = 1;
|
|
159
|
+
standardSet[46] = 1; // HH
|
|
160
|
+
standardSet[71] = 2;
|
|
161
|
+
standardSet[72] = 2; // Whistle
|
|
162
|
+
standardSet[73] = 3;
|
|
163
|
+
standardSet[74] = 3; // Guiro
|
|
164
|
+
standardSet[78] = 4;
|
|
165
|
+
standardSet[79] = 4; // Cuica
|
|
166
|
+
standardSet[80] = 5;
|
|
167
|
+
standardSet[81] = 5; // Triangle
|
|
168
|
+
standardSet[29] = 6;
|
|
169
|
+
standardSet[30] = 6; // Scratch
|
|
170
|
+
standardSet[86] = 7;
|
|
171
|
+
standardSet[87] = 7; // Surdo
|
|
172
|
+
drumExclusiveClassesByKit[0] = standardSet;
|
|
173
|
+
const analogSet = new Uint8Array(128);
|
|
174
|
+
analogSet[42] = 8;
|
|
175
|
+
analogSet[44] = 8;
|
|
176
|
+
analogSet[46] = 8; // CHH
|
|
177
|
+
drumExclusiveClassesByKit[25] = analogSet;
|
|
178
|
+
const orchestraSet = new Uint8Array(128);
|
|
179
|
+
orchestraSet[27] = 9;
|
|
180
|
+
orchestraSet[28] = 9;
|
|
181
|
+
orchestraSet[29] = 9; // HH
|
|
182
|
+
drumExclusiveClassesByKit[48] = orchestraSet;
|
|
183
|
+
const sfxSet = new Uint8Array(128);
|
|
184
|
+
sfxSet[41] = 10;
|
|
185
|
+
sfxSet[42] = 10; // Scratch
|
|
186
|
+
drumExclusiveClassesByKit[56] = sfxSet;
|
|
154
187
|
// normalized to 0-1 for use with the SF2 modulator model
|
|
155
188
|
const defaultControllerState = {
|
|
156
189
|
noteOnVelocity: { type: 2, defaultValue: 0 },
|
|
@@ -245,18 +278,6 @@ export class MidyGM2 {
|
|
|
245
278
|
writable: true,
|
|
246
279
|
value: "GM2"
|
|
247
280
|
});
|
|
248
|
-
Object.defineProperty(this, "ticksPerBeat", {
|
|
249
|
-
enumerable: true,
|
|
250
|
-
configurable: true,
|
|
251
|
-
writable: true,
|
|
252
|
-
value: 120
|
|
253
|
-
});
|
|
254
|
-
Object.defineProperty(this, "totalTime", {
|
|
255
|
-
enumerable: true,
|
|
256
|
-
configurable: true,
|
|
257
|
-
writable: true,
|
|
258
|
-
value: 0
|
|
259
|
-
});
|
|
260
281
|
Object.defineProperty(this, "masterFineTuning", {
|
|
261
282
|
enumerable: true,
|
|
262
283
|
configurable: true,
|
|
@@ -290,6 +311,24 @@ export class MidyGM2 {
|
|
|
290
311
|
delayTimes: this.generateDistributedArray(0.02, 2, 0.5),
|
|
291
312
|
}
|
|
292
313
|
});
|
|
314
|
+
Object.defineProperty(this, "numChannels", {
|
|
315
|
+
enumerable: true,
|
|
316
|
+
configurable: true,
|
|
317
|
+
writable: true,
|
|
318
|
+
value: 16
|
|
319
|
+
});
|
|
320
|
+
Object.defineProperty(this, "ticksPerBeat", {
|
|
321
|
+
enumerable: true,
|
|
322
|
+
configurable: true,
|
|
323
|
+
writable: true,
|
|
324
|
+
value: 120
|
|
325
|
+
});
|
|
326
|
+
Object.defineProperty(this, "totalTime", {
|
|
327
|
+
enumerable: true,
|
|
328
|
+
configurable: true,
|
|
329
|
+
writable: true,
|
|
330
|
+
value: 0
|
|
331
|
+
});
|
|
293
332
|
Object.defineProperty(this, "noteCheckInterval", {
|
|
294
333
|
enumerable: true,
|
|
295
334
|
configurable: true,
|
|
@@ -392,11 +431,17 @@ export class MidyGM2 {
|
|
|
392
431
|
writable: true,
|
|
393
432
|
value: []
|
|
394
433
|
});
|
|
395
|
-
Object.defineProperty(this, "
|
|
434
|
+
Object.defineProperty(this, "exclusiveClassNotes", {
|
|
435
|
+
enumerable: true,
|
|
436
|
+
configurable: true,
|
|
437
|
+
writable: true,
|
|
438
|
+
value: new Array(128)
|
|
439
|
+
});
|
|
440
|
+
Object.defineProperty(this, "drumExclusiveClassNotes", {
|
|
396
441
|
enumerable: true,
|
|
397
442
|
configurable: true,
|
|
398
443
|
writable: true,
|
|
399
|
-
value: new
|
|
444
|
+
value: new Array(this.numChannels * drumExclusiveClassCount)
|
|
400
445
|
});
|
|
401
446
|
Object.defineProperty(this, "defaultOptions", {
|
|
402
447
|
enumerable: true,
|
|
@@ -490,8 +535,10 @@ export class MidyGM2 {
|
|
|
490
535
|
};
|
|
491
536
|
}
|
|
492
537
|
createChannels(audioContext) {
|
|
493
|
-
const channels = Array.from({ length:
|
|
538
|
+
const channels = Array.from({ length: this.numChannels }, () => {
|
|
494
539
|
return {
|
|
540
|
+
currentBufferSource: null,
|
|
541
|
+
isDrum: false,
|
|
495
542
|
...this.constructor.channelSettings,
|
|
496
543
|
state: new ControllerState(),
|
|
497
544
|
controlTable: this.initControlTable(),
|
|
@@ -535,24 +582,10 @@ export class MidyGM2 {
|
|
|
535
582
|
return audioBuffer;
|
|
536
583
|
}
|
|
537
584
|
}
|
|
538
|
-
|
|
539
|
-
if (channel.isDrum) {
|
|
540
|
-
const noteNumber = note.noteNumber;
|
|
541
|
-
if (noteNumber === 88 || 47 <= noteNumber && noteNumber <= 84) {
|
|
542
|
-
return true;
|
|
543
|
-
}
|
|
544
|
-
else {
|
|
545
|
-
return false;
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
return voiceParams.sampleModes % 2 !== 0;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
createBufferSource(channel, note, voiceParams, audioBuffer) {
|
|
585
|
+
createBufferSource(voiceParams, audioBuffer) {
|
|
553
586
|
const bufferSource = new AudioBufferSourceNode(this.audioContext);
|
|
554
587
|
bufferSource.buffer = audioBuffer;
|
|
555
|
-
bufferSource.loop =
|
|
588
|
+
bufferSource.loop = voiceParams.sampleModes % 2 !== 0;
|
|
556
589
|
if (bufferSource.loop) {
|
|
557
590
|
bufferSource.loopStart = voiceParams.loopStart / voiceParams.sampleRate;
|
|
558
591
|
bufferSource.loopEnd = voiceParams.loopEnd / voiceParams.sampleRate;
|
|
@@ -640,7 +673,8 @@ export class MidyGM2 {
|
|
|
640
673
|
if (queueIndex >= this.timeline.length) {
|
|
641
674
|
await Promise.all(this.notePromises);
|
|
642
675
|
this.notePromises = [];
|
|
643
|
-
this.
|
|
676
|
+
this.exclusiveClassNotes.fill(undefined);
|
|
677
|
+
this.drumExclusiveClassNotes.fill(undefined);
|
|
644
678
|
this.audioBufferCache.clear();
|
|
645
679
|
resolve();
|
|
646
680
|
return;
|
|
@@ -659,7 +693,8 @@ export class MidyGM2 {
|
|
|
659
693
|
else if (this.isStopping) {
|
|
660
694
|
await this.stopNotes(0, true, now);
|
|
661
695
|
this.notePromises = [];
|
|
662
|
-
this.
|
|
696
|
+
this.exclusiveClassNotes.fill(undefined);
|
|
697
|
+
this.drumExclusiveClassNotes.fill(undefined);
|
|
663
698
|
this.audioBufferCache.clear();
|
|
664
699
|
resolve();
|
|
665
700
|
this.isStopping = false;
|
|
@@ -668,7 +703,8 @@ export class MidyGM2 {
|
|
|
668
703
|
}
|
|
669
704
|
else if (this.isSeeking) {
|
|
670
705
|
this.stopNotes(0, true, now);
|
|
671
|
-
this.
|
|
706
|
+
this.exclusiveClassNotes.fill(undefined);
|
|
707
|
+
this.drumExclusiveClassNotes.fill(undefined);
|
|
672
708
|
this.startTime = this.audioContext.currentTime;
|
|
673
709
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
674
710
|
offset = this.resumeTime - this.startTime;
|
|
@@ -696,7 +732,7 @@ export class MidyGM2 {
|
|
|
696
732
|
extractMidiData(midi) {
|
|
697
733
|
const instruments = new Set();
|
|
698
734
|
const timeline = [];
|
|
699
|
-
const tmpChannels = new Array(
|
|
735
|
+
const tmpChannels = new Array(this.channels.length);
|
|
700
736
|
for (let i = 0; i < tmpChannels.length; i++) {
|
|
701
737
|
tmpChannels[i] = {
|
|
702
738
|
programNumber: -1,
|
|
@@ -824,6 +860,9 @@ export class MidyGM2 {
|
|
|
824
860
|
if (!this.isPlaying)
|
|
825
861
|
return;
|
|
826
862
|
this.isStopping = true;
|
|
863
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
864
|
+
this.resetAllStates(i);
|
|
865
|
+
}
|
|
827
866
|
}
|
|
828
867
|
pause() {
|
|
829
868
|
if (!this.isPlaying || this.isPaused)
|
|
@@ -1194,8 +1233,8 @@ export class MidyGM2 {
|
|
|
1194
1233
|
note.vibratoLFO.connect(note.vibratoDepth);
|
|
1195
1234
|
note.vibratoDepth.connect(note.bufferSource.detune);
|
|
1196
1235
|
}
|
|
1197
|
-
async getAudioBuffer(
|
|
1198
|
-
const audioBufferId = this.getAudioBufferId(
|
|
1236
|
+
async getAudioBuffer(programNumber, noteNumber, velocity, voiceParams, isSF3) {
|
|
1237
|
+
const audioBufferId = this.getAudioBufferId(programNumber, noteNumber, velocity);
|
|
1199
1238
|
const cache = this.audioBufferCache.get(audioBufferId);
|
|
1200
1239
|
if (cache) {
|
|
1201
1240
|
cache.counter += 1;
|
|
@@ -1218,8 +1257,8 @@ export class MidyGM2 {
|
|
|
1218
1257
|
const controllerState = this.getControllerState(channel, noteNumber, velocity);
|
|
1219
1258
|
const voiceParams = voice.getAllParams(controllerState);
|
|
1220
1259
|
const note = new Note(noteNumber, velocity, startTime, voice, voiceParams);
|
|
1221
|
-
const audioBuffer = await this.getAudioBuffer(channel.
|
|
1222
|
-
note.bufferSource = this.createBufferSource(
|
|
1260
|
+
const audioBuffer = await this.getAudioBuffer(channel.programNumber, noteNumber, velocity, voiceParams, isSF3);
|
|
1261
|
+
note.bufferSource = this.createBufferSource(voiceParams, audioBuffer);
|
|
1223
1262
|
note.volumeNode = new GainNode(this.audioContext);
|
|
1224
1263
|
note.gainL = new GainNode(this.audioContext);
|
|
1225
1264
|
note.gainR = new GainNode(this.audioContext);
|
|
@@ -1279,14 +1318,56 @@ export class MidyGM2 {
|
|
|
1279
1318
|
return channel.bank;
|
|
1280
1319
|
}
|
|
1281
1320
|
}
|
|
1321
|
+
handleExclusiveClass(note, channelNumber, startTime) {
|
|
1322
|
+
const exclusiveClass = note.voiceParams.exclusiveClass;
|
|
1323
|
+
if (exclusiveClass === 0)
|
|
1324
|
+
return;
|
|
1325
|
+
const prev = this.exclusiveClassNotes[exclusiveClass];
|
|
1326
|
+
if (prev) {
|
|
1327
|
+
const [prevNote, prevChannelNumber] = prev;
|
|
1328
|
+
if (prevNote && !prevNote.ending) {
|
|
1329
|
+
this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
1330
|
+
startTime, true, // force
|
|
1331
|
+
undefined);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
this.exclusiveClassNotes[exclusiveClass] = [note, channelNumber];
|
|
1335
|
+
}
|
|
1336
|
+
handleDrumExclusiveClass(note, channelNumber, startTime) {
|
|
1337
|
+
const channel = this.channels[channelNumber];
|
|
1338
|
+
if (!channel.isDrum)
|
|
1339
|
+
return;
|
|
1340
|
+
const kitTable = drumExclusiveClassesByKit[channel.programNumber];
|
|
1341
|
+
if (!kitTable)
|
|
1342
|
+
return;
|
|
1343
|
+
const drumExclusiveClass = kitTable[note.noteNumber];
|
|
1344
|
+
if (drumExclusiveClass === 0)
|
|
1345
|
+
return;
|
|
1346
|
+
const index = (drumExclusiveClass - 1) * this.channels.length +
|
|
1347
|
+
channelNumber;
|
|
1348
|
+
const prevNote = this.drumExclusiveClassNotes[index];
|
|
1349
|
+
if (prevNote && !prevNote.ending) {
|
|
1350
|
+
this.scheduleNoteOff(channelNumber, prevNote.noteNumber, 0, // velocity,
|
|
1351
|
+
startTime, true, // force
|
|
1352
|
+
undefined);
|
|
1353
|
+
}
|
|
1354
|
+
this.drumExclusiveClassNotes[index] = note;
|
|
1355
|
+
}
|
|
1356
|
+
isDrumNoteOffException(channel, noteNumber) {
|
|
1357
|
+
if (!channel.isDrum)
|
|
1358
|
+
return false;
|
|
1359
|
+
const programNumber = channel.programNumber;
|
|
1360
|
+
return (programNumber === 48 && noteNumber === 88) ||
|
|
1361
|
+
(programNumber === 56 && 47 <= noteNumber && noteNumber <= 84);
|
|
1362
|
+
}
|
|
1282
1363
|
async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime, portamento) {
|
|
1283
1364
|
const channel = this.channels[channelNumber];
|
|
1284
1365
|
const bankNumber = this.calcBank(channel, channelNumber);
|
|
1285
|
-
const soundFontIndex = this.soundFontTable[channel.
|
|
1366
|
+
const soundFontIndex = this.soundFontTable[channel.programNumber].get(bankNumber);
|
|
1286
1367
|
if (soundFontIndex === undefined)
|
|
1287
1368
|
return;
|
|
1288
1369
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
1289
|
-
const voice = soundFont.getVoice(bankNumber, channel.
|
|
1370
|
+
const voice = soundFont.getVoice(bankNumber, channel.programNumber, noteNumber, velocity);
|
|
1290
1371
|
if (!voice)
|
|
1291
1372
|
return;
|
|
1292
1373
|
const isSF3 = soundFont.parsed.info.version.major === 3;
|
|
@@ -1296,31 +1377,58 @@ export class MidyGM2 {
|
|
|
1296
1377
|
if (0.5 <= channel.state.sustainPedal) {
|
|
1297
1378
|
channel.sustainNotes.push(note);
|
|
1298
1379
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
if (this.exclusiveClassMap.has(exclusiveClass)) {
|
|
1302
|
-
const prevEntry = this.exclusiveClassMap.get(exclusiveClass);
|
|
1303
|
-
const [prevNote, prevChannelNumber] = prevEntry;
|
|
1304
|
-
if (prevNote && !prevNote.ending) {
|
|
1305
|
-
this.scheduleNoteOff(prevChannelNumber, prevNote.noteNumber, 0, // velocity,
|
|
1306
|
-
startTime, true, // force
|
|
1307
|
-
undefined);
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
1310
|
-
this.exclusiveClassMap.set(exclusiveClass, [note, channelNumber]);
|
|
1311
|
-
}
|
|
1380
|
+
this.handleExclusiveClass(note, channelNumber, startTime);
|
|
1381
|
+
this.handleDrumExclusiveClass(note, channelNumber, startTime);
|
|
1312
1382
|
const scheduledNotes = channel.scheduledNotes;
|
|
1313
|
-
|
|
1314
|
-
|
|
1383
|
+
let notes = scheduledNotes.get(noteNumber);
|
|
1384
|
+
if (notes) {
|
|
1385
|
+
notes.push(note);
|
|
1315
1386
|
}
|
|
1316
1387
|
else {
|
|
1317
|
-
|
|
1388
|
+
notes = [note];
|
|
1389
|
+
scheduledNotes.set(noteNumber, notes);
|
|
1390
|
+
}
|
|
1391
|
+
if (this.isDrumNoteOffException(channel, noteNumber)) {
|
|
1392
|
+
const stopTime = startTime + note.bufferSource.buffer.duration;
|
|
1393
|
+
const index = notes.length - 1;
|
|
1394
|
+
const promise = new Promise((resolve) => {
|
|
1395
|
+
note.bufferSource.onended = () => {
|
|
1396
|
+
this.disconnectNote(note, scheduledNotes, index);
|
|
1397
|
+
resolve();
|
|
1398
|
+
};
|
|
1399
|
+
note.bufferSource.stop(stopTime);
|
|
1400
|
+
});
|
|
1401
|
+
this.notePromises.push(promise);
|
|
1318
1402
|
}
|
|
1319
1403
|
}
|
|
1320
1404
|
noteOn(channelNumber, noteNumber, velocity, scheduleTime) {
|
|
1321
1405
|
scheduleTime ??= this.audioContext.currentTime;
|
|
1322
1406
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime, false);
|
|
1323
1407
|
}
|
|
1408
|
+
disconnectNote(note, scheduledNotes, index) {
|
|
1409
|
+
scheduledNotes[index] = null;
|
|
1410
|
+
note.bufferSource.disconnect();
|
|
1411
|
+
note.filterNode.disconnect();
|
|
1412
|
+
note.volumeEnvelopeNode.disconnect();
|
|
1413
|
+
note.volumeNode.disconnect();
|
|
1414
|
+
note.gainL.disconnect();
|
|
1415
|
+
note.gainR.disconnect();
|
|
1416
|
+
if (note.modulationDepth) {
|
|
1417
|
+
note.volumeDepth.disconnect();
|
|
1418
|
+
note.modulationDepth.disconnect();
|
|
1419
|
+
note.modulationLFO.stop();
|
|
1420
|
+
}
|
|
1421
|
+
if (note.vibratoDepth) {
|
|
1422
|
+
note.vibratoDepth.disconnect();
|
|
1423
|
+
note.vibratoLFO.stop();
|
|
1424
|
+
}
|
|
1425
|
+
if (note.reverbEffectsSend) {
|
|
1426
|
+
note.reverbEffectsSend.disconnect();
|
|
1427
|
+
}
|
|
1428
|
+
if (note.chorusEffectsSend) {
|
|
1429
|
+
note.chorusEffectsSend.disconnect();
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1324
1432
|
stopNote(endTime, stopTime, scheduledNotes, index) {
|
|
1325
1433
|
const note = scheduledNotes[index];
|
|
1326
1434
|
note.volumeEnvelopeNode.gain
|
|
@@ -1332,28 +1440,7 @@ export class MidyGM2 {
|
|
|
1332
1440
|
}, stopTime);
|
|
1333
1441
|
return new Promise((resolve) => {
|
|
1334
1442
|
note.bufferSource.onended = () => {
|
|
1335
|
-
scheduledNotes
|
|
1336
|
-
note.bufferSource.disconnect();
|
|
1337
|
-
note.filterNode.disconnect();
|
|
1338
|
-
note.volumeEnvelopeNode.disconnect();
|
|
1339
|
-
note.volumeNode.disconnect();
|
|
1340
|
-
note.gainL.disconnect();
|
|
1341
|
-
note.gainR.disconnect();
|
|
1342
|
-
if (note.modulationDepth) {
|
|
1343
|
-
note.volumeDepth.disconnect();
|
|
1344
|
-
note.modulationDepth.disconnect();
|
|
1345
|
-
note.modulationLFO.stop();
|
|
1346
|
-
}
|
|
1347
|
-
if (note.vibratoDepth) {
|
|
1348
|
-
note.vibratoDepth.disconnect();
|
|
1349
|
-
note.vibratoLFO.stop();
|
|
1350
|
-
}
|
|
1351
|
-
if (note.reverbEffectsSend) {
|
|
1352
|
-
note.reverbEffectsSend.disconnect();
|
|
1353
|
-
}
|
|
1354
|
-
if (note.chorusEffectsSend) {
|
|
1355
|
-
note.chorusEffectsSend.disconnect();
|
|
1356
|
-
}
|
|
1443
|
+
this.disconnectNote(note, scheduledNotes, index);
|
|
1357
1444
|
resolve();
|
|
1358
1445
|
};
|
|
1359
1446
|
note.bufferSource.stop(stopTime);
|
|
@@ -1361,6 +1448,8 @@ export class MidyGM2 {
|
|
|
1361
1448
|
}
|
|
1362
1449
|
scheduleNoteOff(channelNumber, noteNumber, _velocity, endTime, force, portamentoNoteNumber) {
|
|
1363
1450
|
const channel = this.channels[channelNumber];
|
|
1451
|
+
if (this.isDrumNoteOffException(channel, noteNumber))
|
|
1452
|
+
return;
|
|
1364
1453
|
const state = channel.state;
|
|
1365
1454
|
if (!force) {
|
|
1366
1455
|
if (0.5 <= state.sustainPedal)
|
|
@@ -1446,10 +1535,10 @@ export class MidyGM2 {
|
|
|
1446
1535
|
console.warn(`Unsupported MIDI message: ${messageType.toString(16)}`);
|
|
1447
1536
|
}
|
|
1448
1537
|
}
|
|
1449
|
-
handleProgramChange(channelNumber,
|
|
1538
|
+
handleProgramChange(channelNumber, programNumber, _scheduleTime) {
|
|
1450
1539
|
const channel = this.channels[channelNumber];
|
|
1451
1540
|
channel.bank = channel.bankMSB * 128 + channel.bankLSB;
|
|
1452
|
-
channel.
|
|
1541
|
+
channel.programNumber = programNumber;
|
|
1453
1542
|
if (this.mode === "GM2") {
|
|
1454
1543
|
switch (channel.bankMSB) {
|
|
1455
1544
|
case 120:
|
|
@@ -2080,16 +2169,30 @@ export class MidyGM2 {
|
|
|
2080
2169
|
scheduleTime ??= this.audioContext.currentTime;
|
|
2081
2170
|
return this.stopChannelNotes(channelNumber, 0, true, scheduleTime);
|
|
2082
2171
|
}
|
|
2172
|
+
resetAllStates(channelNumber) {
|
|
2173
|
+
const channel = this.channels[channelNumber];
|
|
2174
|
+
const state = channel.state;
|
|
2175
|
+
for (const type of Object.keys(defaultControllerState)) {
|
|
2176
|
+
state[type] = defaultControllerState[type].defaultValue;
|
|
2177
|
+
}
|
|
2178
|
+
for (const type of Object.keys(this.constructor.channelSettings)) {
|
|
2179
|
+
channel[type] = this.constructor.channelSettings[type];
|
|
2180
|
+
}
|
|
2181
|
+
this.mode = "GM2";
|
|
2182
|
+
this.masterFineTuning = 0; // cb
|
|
2183
|
+
this.masterCoarseTuning = 0; // cb
|
|
2184
|
+
}
|
|
2185
|
+
// https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
|
|
2083
2186
|
resetAllControllers(channelNumber) {
|
|
2084
2187
|
const stateTypes = [
|
|
2188
|
+
"channelPressure",
|
|
2189
|
+
"pitchWheel",
|
|
2085
2190
|
"expression",
|
|
2086
2191
|
"modulationDepth",
|
|
2087
2192
|
"sustainPedal",
|
|
2088
2193
|
"portamento",
|
|
2089
2194
|
"sostenutoPedal",
|
|
2090
2195
|
"softPedal",
|
|
2091
|
-
"channelPressure",
|
|
2092
|
-
"pitchWheelSensitivity",
|
|
2093
2196
|
];
|
|
2094
2197
|
const channel = this.channels[channelNumber];
|
|
2095
2198
|
const state = channel.state;
|
|
@@ -2454,7 +2557,7 @@ export class MidyGM2 {
|
|
|
2454
2557
|
return value * 0.00787;
|
|
2455
2558
|
}
|
|
2456
2559
|
getChannelBitmap(data) {
|
|
2457
|
-
const bitmap = new Array(
|
|
2560
|
+
const bitmap = new Array(this.channels.length).fill(false);
|
|
2458
2561
|
const ff = data[4] & 0b11;
|
|
2459
2562
|
const gg = data[5] & 0x7F;
|
|
2460
2563
|
const hh = data[6] & 0x7F;
|
|
@@ -2596,6 +2699,7 @@ export class MidyGM2 {
|
|
|
2596
2699
|
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
2597
2700
|
}
|
|
2598
2701
|
}
|
|
2702
|
+
// https://github.com/marmooo/js-timer-benchmark
|
|
2599
2703
|
scheduleTask(callback, scheduleTime) {
|
|
2600
2704
|
return new Promise((resolve) => {
|
|
2601
2705
|
const bufferSource = new AudioBufferSourceNode(this.audioContext, {
|
|
@@ -2620,10 +2724,8 @@ Object.defineProperty(MidyGM2, "channelSettings", {
|
|
|
2620
2724
|
configurable: true,
|
|
2621
2725
|
writable: true,
|
|
2622
2726
|
value: {
|
|
2623
|
-
currentBufferSource: null,
|
|
2624
|
-
isDrum: false,
|
|
2625
2727
|
detune: 0,
|
|
2626
|
-
|
|
2728
|
+
programNumber: 0,
|
|
2627
2729
|
bank: 121 * 128,
|
|
2628
2730
|
bankMSB: 121,
|
|
2629
2731
|
bankLSB: 0,
|
package/esm/midy-GMLite.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export class MidyGMLite {
|
|
2
2
|
static channelSettings: {
|
|
3
|
-
currentBufferSource: null;
|
|
4
|
-
isDrum: boolean;
|
|
5
3
|
detune: number;
|
|
6
|
-
|
|
4
|
+
programNumber: number;
|
|
7
5
|
bank: number;
|
|
8
6
|
dataMSB: number;
|
|
9
7
|
dataLSB: number;
|
|
@@ -13,6 +11,7 @@ export class MidyGMLite {
|
|
|
13
11
|
};
|
|
14
12
|
constructor(audioContext: any);
|
|
15
13
|
mode: string;
|
|
14
|
+
numChannels: number;
|
|
16
15
|
ticksPerBeat: number;
|
|
17
16
|
totalTime: number;
|
|
18
17
|
noteCheckInterval: number;
|
|
@@ -32,7 +31,8 @@ export class MidyGMLite {
|
|
|
32
31
|
timeline: any[];
|
|
33
32
|
instruments: any[];
|
|
34
33
|
notePromises: any[];
|
|
35
|
-
|
|
34
|
+
exclusiveClassNotes: any[];
|
|
35
|
+
drumExclusiveClassNotes: any[];
|
|
36
36
|
audioContext: any;
|
|
37
37
|
masterVolume: any;
|
|
38
38
|
scheduler: any;
|
|
@@ -75,8 +75,7 @@ export class MidyGMLite {
|
|
|
75
75
|
};
|
|
76
76
|
createChannels(audioContext: any): any[];
|
|
77
77
|
createNoteBuffer(voiceParams: any, isSF3: any): Promise<any>;
|
|
78
|
-
|
|
79
|
-
createBufferSource(channel: any, voiceParams: any, audioBuffer: any): any;
|
|
78
|
+
createBufferSource(voiceParams: any, audioBuffer: any): any;
|
|
80
79
|
scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
|
|
81
80
|
getQueueIndex(second: any): number;
|
|
82
81
|
playNotes(): Promise<any>;
|
|
@@ -111,16 +110,19 @@ export class MidyGMLite {
|
|
|
111
110
|
clampCutoffFrequency(frequency: any): number;
|
|
112
111
|
setFilterEnvelope(note: any, scheduleTime: any): void;
|
|
113
112
|
startModulation(channel: any, note: any, scheduleTime: any): void;
|
|
114
|
-
getAudioBuffer(
|
|
113
|
+
getAudioBuffer(programNumber: any, noteNumber: any, velocity: any, voiceParams: any, isSF3: any): Promise<any>;
|
|
115
114
|
createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
115
|
+
handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
116
|
+
handleDrumExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
116
117
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
117
118
|
noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
|
|
119
|
+
disconnectNote(note: any, scheduledNotes: any, index: any): void;
|
|
118
120
|
stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
|
|
119
121
|
scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any): Promise<any> | undefined;
|
|
120
122
|
noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
|
|
121
123
|
releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
|
|
122
124
|
handleMIDIMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
|
|
123
|
-
handleProgramChange(channelNumber: any,
|
|
125
|
+
handleProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
|
|
124
126
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
|
|
125
127
|
setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;
|
|
126
128
|
setModLfoToPitch(channel: any, note: any, scheduleTime: any): void;
|
|
@@ -177,6 +179,7 @@ export class MidyGMLite {
|
|
|
177
179
|
handlePitchBendRangeRPN(channelNumber: any, scheduleTime: any): void;
|
|
178
180
|
setPitchBendRange(channelNumber: any, value: any, scheduleTime: any): void;
|
|
179
181
|
allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
182
|
+
resetAllStates(channelNumber: any): void;
|
|
180
183
|
resetAllControllers(channelNumber: any): void;
|
|
181
184
|
allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
|
|
182
185
|
handleUniversalNonRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
|
package/esm/midy-GMLite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AA+JA;IA2BE;;;;;;;;;MASE;IAEF,+BAcC;IAnDD,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;IACrC,+BAEE;IAcA,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,wCAIC;IAED,2DAIC;IAED,+DAIC;IAED,sDAeC;IAED,qDAoBC;IAED,6CAIC;IAED,sDAsBC;IAED,kEAoBC;IAED,+GA0BC;IAED,gHAwCC;IAED,0EAiBC;IAED,8EAiBC;IAED,kGAmDC;IAED,6FAQC;IAED,iEAUC;IAED,qFAgBC;IAED,yHAwBC;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,uDAYC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAUC;IAED,gFAGC;IAED,yCAUC;IAGD,8CAqBC;IAED,gFAGC;IAED,+EAgBC;IAED,qCAWC;IAED,4EAaC;IAED,4DAGC;IAED,sDASC;IAED,gDAYC;IAGD,6DAgBC;CACF;AA79CD;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"}
|