@marmooo/midy 0.4.6 → 0.4.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/esm/midy-GM1.d.ts +3 -0
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +115 -53
- package/esm/midy-GM2.d.ts +16 -4
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +255 -159
- package/esm/midy-GMLite.d.ts +2 -0
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +109 -53
- package/esm/midy.d.ts +34 -11
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +352 -223
- package/package.json +3 -2
- package/script/midy-GM1.d.ts +3 -0
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +115 -53
- package/script/midy-GM2.d.ts +16 -4
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +255 -159
- package/script/midy-GMLite.d.ts +2 -0
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +109 -53
- package/script/midy.d.ts +34 -11
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +352 -223
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marmooo/midy",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
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",
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"test": "node test_runner.js"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@marmooo/soundfont-parser": "^0.1.
|
|
25
|
+
"@marmooo/soundfont-parser": "^0.1.8",
|
|
26
|
+
"@wasm-audio-decoders/ogg-vorbis": "^0.1.20",
|
|
26
27
|
"midi-file": "^1.2.4"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
package/script/midy-GM1.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export class MidyGM1 extends EventTarget {
|
|
|
27
27
|
voiceCounter: Map<any, any>;
|
|
28
28
|
voiceCache: Map<any, any>;
|
|
29
29
|
realtimeVoiceCache: Map<any, any>;
|
|
30
|
+
decodeMethod: string;
|
|
31
|
+
decoderQueue: Promise<void>;
|
|
30
32
|
isPlaying: boolean;
|
|
31
33
|
isPausing: boolean;
|
|
32
34
|
isPaused: boolean;
|
|
@@ -72,6 +74,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
72
74
|
merger: any;
|
|
73
75
|
};
|
|
74
76
|
createChannels(audioContext: any): any[];
|
|
77
|
+
decodeOggVorbis(sample: any): Promise<any>;
|
|
75
78
|
createAudioBuffer(voiceParams: any): Promise<any>;
|
|
76
79
|
createBufferSource(voiceParams: any, audioBuffer: any): any;
|
|
77
80
|
scheduleTimelineEvents(scheduleTime: any, queueIndex: any): any;
|
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":"AAmHA;IAsCE;;;;;;;;;;;MAWE;IAEF,+BAgBC;IA9DD,gCAAgC;IAChC,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,kCAA+B;IAC/B,qBAAqC;IACrC,4BAAiC;IACjC,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,iCAEG;IACH,cAAU;IACV,cAAa;IACb,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IAiBnC,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,sBA6BC;IAED,8DAeC;IAED;;;;MAeC;IAED,yCAaC;IAED,2CAsBC;IAED,kDA6BC;IAED,4DASC;IAED,gEAsDC;IAED,mCASC;IAED,uBAUC;IAED,yDAqCC;IAED,2BA0EC;IAED,uDAEC;IAED,wDAEC;IAED,qCAKC;IAED;;;MAwDC;IAED,kGAeC;IAED,mGAeC;IAED,wEAQC;IAED,uBAMC;IAED,sBAIC;IAED,uBAMC;IAED,wBAIC;IAED,0BAKC;IAED,8BAMC;IAED,wBAYC;IAED,sBAIC;IAED,kEAWC;IAED,kFAYC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAMC;IAED,2DAIC;IAED,6CAEC;IAED,sDAeC;IAED,4DASC;IAED,qDAkBC;IAED,6CAIC;IAED,sDA6BC;IAED,kEAqBC;IAED,4GAkCC;IAED,uEAyCC;IAED,0EAiBC;IAED,oEASC;IAED,0FAwBC;IAED,gCASC;IAED,iEAwBC;IAED,4FAmBC;IAED,6CAUC;IAED,qDAUC;IAED,qFAeC;IAED,+BAmBC;IAED,kDAOC;IAED,sFA2BC;IAED,mFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAYC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;;MAoCC;IAED,oFAMC;IAED,6EA2BC;IAED,qCAeC;IAED,+FAYC;IAED,wDAUC;IAED,4EAKC;IAED,mEAKC;IAED;;;MAMC;IAED,gEAKC;IAED,uEAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAWC;IAED,kFAeC;IAED,2DAMC;IAED,uDAoBC;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,qCAUC;IAED,4EAaC;IAED,4DAGC;IAED,qDAKC;IAED,gDAYC;IAGD,6DAgBC;CACF"}
|
package/script/midy-GM1.js
CHANGED
|
@@ -3,6 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MidyGM1 = void 0;
|
|
4
4
|
const midi_file_1 = require("midi-file");
|
|
5
5
|
const soundfont_parser_1 = require("@marmooo/soundfont-parser");
|
|
6
|
+
const ogg_vorbis_1 = require("@wasm-audio-decoders/ogg-vorbis");
|
|
7
|
+
let decoderPromise = null;
|
|
8
|
+
let decoderQueue = Promise.resolve();
|
|
9
|
+
function initDecoder() {
|
|
10
|
+
if (!decoderPromise) {
|
|
11
|
+
const instance = new ogg_vorbis_1.OggVorbisDecoderWebWorker();
|
|
12
|
+
decoderPromise = instance.ready.then(() => instance);
|
|
13
|
+
}
|
|
14
|
+
return decoderPromise;
|
|
15
|
+
}
|
|
6
16
|
class Note {
|
|
7
17
|
constructor(noteNumber, velocity, startTime) {
|
|
8
18
|
Object.defineProperty(this, "voice", {
|
|
@@ -41,37 +51,37 @@ class Note {
|
|
|
41
51
|
writable: true,
|
|
42
52
|
value: void 0
|
|
43
53
|
});
|
|
44
|
-
Object.defineProperty(this, "
|
|
54
|
+
Object.defineProperty(this, "filterEnvelopeNode", {
|
|
45
55
|
enumerable: true,
|
|
46
56
|
configurable: true,
|
|
47
57
|
writable: true,
|
|
48
58
|
value: void 0
|
|
49
59
|
});
|
|
50
|
-
Object.defineProperty(this, "
|
|
60
|
+
Object.defineProperty(this, "volumeEnvelopeNode", {
|
|
51
61
|
enumerable: true,
|
|
52
62
|
configurable: true,
|
|
53
63
|
writable: true,
|
|
54
64
|
value: void 0
|
|
55
65
|
});
|
|
56
|
-
Object.defineProperty(this, "
|
|
66
|
+
Object.defineProperty(this, "modLfo", {
|
|
57
67
|
enumerable: true,
|
|
58
68
|
configurable: true,
|
|
59
69
|
writable: true,
|
|
60
70
|
value: void 0
|
|
61
|
-
});
|
|
62
|
-
Object.defineProperty(this, "
|
|
71
|
+
}); // CC#1 modulation LFO
|
|
72
|
+
Object.defineProperty(this, "modLfoToPitch", {
|
|
63
73
|
enumerable: true,
|
|
64
74
|
configurable: true,
|
|
65
75
|
writable: true,
|
|
66
76
|
value: void 0
|
|
67
77
|
});
|
|
68
|
-
Object.defineProperty(this, "
|
|
78
|
+
Object.defineProperty(this, "modLfoToFilterFc", {
|
|
69
79
|
enumerable: true,
|
|
70
80
|
configurable: true,
|
|
71
81
|
writable: true,
|
|
72
82
|
value: void 0
|
|
73
83
|
});
|
|
74
|
-
Object.defineProperty(this, "
|
|
84
|
+
Object.defineProperty(this, "modLfoToVolume", {
|
|
75
85
|
enumerable: true,
|
|
76
86
|
configurable: true,
|
|
77
87
|
writable: true,
|
|
@@ -258,6 +268,18 @@ class MidyGM1 extends EventTarget {
|
|
|
258
268
|
writable: true,
|
|
259
269
|
value: new Map()
|
|
260
270
|
});
|
|
271
|
+
Object.defineProperty(this, "decodeMethod", {
|
|
272
|
+
enumerable: true,
|
|
273
|
+
configurable: true,
|
|
274
|
+
writable: true,
|
|
275
|
+
value: "wasm-audio-decoders"
|
|
276
|
+
});
|
|
277
|
+
Object.defineProperty(this, "decoderQueue", {
|
|
278
|
+
enumerable: true,
|
|
279
|
+
configurable: true,
|
|
280
|
+
writable: true,
|
|
281
|
+
value: Promise.resolve()
|
|
282
|
+
});
|
|
261
283
|
Object.defineProperty(this, "isPlaying", {
|
|
262
284
|
enumerable: true,
|
|
263
285
|
configurable: true,
|
|
@@ -419,14 +441,6 @@ class MidyGM1 extends EventTarget {
|
|
|
419
441
|
voiceCounter.set(audioBufferId, (voiceCounter.get(audioBufferId) ?? 0) + 1);
|
|
420
442
|
break;
|
|
421
443
|
}
|
|
422
|
-
case "controller":
|
|
423
|
-
if (event.controllerType === 0) {
|
|
424
|
-
this.setBankMSB(event.channel, event.value);
|
|
425
|
-
}
|
|
426
|
-
else if (event.controllerType === 32) {
|
|
427
|
-
this.setBankLSB(event.channel, event.value);
|
|
428
|
-
}
|
|
429
|
-
break;
|
|
430
444
|
case "programChange":
|
|
431
445
|
this.setProgramChange(event.channel, event.programNumber, event.startTime);
|
|
432
446
|
}
|
|
@@ -484,11 +498,57 @@ class MidyGM1 extends EventTarget {
|
|
|
484
498
|
});
|
|
485
499
|
return channels;
|
|
486
500
|
}
|
|
501
|
+
decodeOggVorbis(sample) {
|
|
502
|
+
const task = decoderQueue.then(async () => {
|
|
503
|
+
const decoder = await initDecoder();
|
|
504
|
+
const slice = sample.data.slice();
|
|
505
|
+
const { channelData, sampleRate, errors } = await decoder.decodeFile(slice);
|
|
506
|
+
if (0 < errors.length) {
|
|
507
|
+
throw new Error(errors.join(", "));
|
|
508
|
+
}
|
|
509
|
+
const audioBuffer = new AudioBuffer({
|
|
510
|
+
numberOfChannels: channelData.length,
|
|
511
|
+
length: channelData[0].length,
|
|
512
|
+
sampleRate,
|
|
513
|
+
});
|
|
514
|
+
for (let ch = 0; ch < channelData.length; ch++) {
|
|
515
|
+
audioBuffer.getChannelData(ch).set(channelData[ch]);
|
|
516
|
+
}
|
|
517
|
+
return audioBuffer;
|
|
518
|
+
});
|
|
519
|
+
decoderQueue = task.catch(() => { });
|
|
520
|
+
return task;
|
|
521
|
+
}
|
|
487
522
|
async createAudioBuffer(voiceParams) {
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
523
|
+
const sample = voiceParams.sample;
|
|
524
|
+
if (sample.type === "compressed") {
|
|
525
|
+
switch (this.decodeMethod) {
|
|
526
|
+
case "decodeAudioData": {
|
|
527
|
+
// https://jakearchibald.com/2016/sounds-fun/
|
|
528
|
+
// https://github.com/WebAudio/web-audio-api/issues/1091
|
|
529
|
+
// decodeAudioData() has priming issues on Safari
|
|
530
|
+
const arrayBuffer = sample.data.slice().buffer;
|
|
531
|
+
return await this.audioContext.decodeAudioData(arrayBuffer);
|
|
532
|
+
}
|
|
533
|
+
case "wasm-audio-decoders":
|
|
534
|
+
return await this.decodeOggVorbis(sample);
|
|
535
|
+
default:
|
|
536
|
+
throw new Error(`Unknown decodeMethod: ${this.decodeMethod}`);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
const data = sample.data;
|
|
541
|
+
const end = data.length + voiceParams.end;
|
|
542
|
+
const subarray = data.subarray(voiceParams.start, end);
|
|
543
|
+
const pcm = sample.decodePCM(subarray);
|
|
544
|
+
const audioBuffer = new AudioBuffer({
|
|
545
|
+
numberOfChannels: 1,
|
|
546
|
+
length: pcm.length,
|
|
547
|
+
sampleRate: sample.sampleHeader.sampleRate,
|
|
548
|
+
});
|
|
549
|
+
audioBuffer.getChannelData(0).set(pcm);
|
|
550
|
+
return audioBuffer;
|
|
551
|
+
}
|
|
492
552
|
}
|
|
493
553
|
createBufferSource(voiceParams, audioBuffer) {
|
|
494
554
|
const bufferSource = new AudioBufferSourceNode(this.audioContext);
|
|
@@ -554,7 +614,7 @@ class MidyGM1 extends EventTarget {
|
|
|
554
614
|
const channels = this.channels;
|
|
555
615
|
for (let ch = 0; ch < channels.length; ch++) {
|
|
556
616
|
channels[ch].scheduledNotes = [];
|
|
557
|
-
this.resetChannelStates(
|
|
617
|
+
this.resetChannelStates(ch);
|
|
558
618
|
}
|
|
559
619
|
}
|
|
560
620
|
updateStates(queueIndex, nextQueueIndex) {
|
|
@@ -937,7 +997,7 @@ class MidyGM1 extends EventTarget {
|
|
|
937
997
|
const modHold = modAttack + voiceParams.modHold;
|
|
938
998
|
const decayDuration = voiceParams.modDecay;
|
|
939
999
|
note.adjustedBaseFreq = adjustedBaseFreq;
|
|
940
|
-
note.
|
|
1000
|
+
note.filterEnvelopeNode.frequency
|
|
941
1001
|
.cancelScheduledValues(scheduleTime)
|
|
942
1002
|
.setValueAtTime(adjustedBaseFreq, startTime)
|
|
943
1003
|
.setValueAtTime(adjustedBaseFreq, modDelay)
|
|
@@ -948,23 +1008,23 @@ class MidyGM1 extends EventTarget {
|
|
|
948
1008
|
startModulation(channel, note, scheduleTime) {
|
|
949
1009
|
const audioContext = this.audioContext;
|
|
950
1010
|
const { voiceParams } = note;
|
|
951
|
-
note.
|
|
1011
|
+
note.modLfo = new OscillatorNode(audioContext, {
|
|
952
1012
|
frequency: this.centToHz(voiceParams.freqModLFO),
|
|
953
1013
|
});
|
|
954
|
-
note.
|
|
1014
|
+
note.modLfoToFilterFc = new GainNode(audioContext, {
|
|
955
1015
|
gain: voiceParams.modLfoToFilterFc,
|
|
956
1016
|
});
|
|
957
|
-
note.
|
|
1017
|
+
note.modLfoToPitch = new GainNode(audioContext);
|
|
958
1018
|
this.setModLfoToPitch(channel, note, scheduleTime);
|
|
959
|
-
note.
|
|
1019
|
+
note.modLfoToVolume = new GainNode(audioContext);
|
|
960
1020
|
this.setModLfoToVolume(note, scheduleTime);
|
|
961
|
-
note.
|
|
962
|
-
note.
|
|
963
|
-
note.
|
|
964
|
-
note.
|
|
965
|
-
note.
|
|
966
|
-
note.
|
|
967
|
-
note.
|
|
1021
|
+
note.modLfo.start(note.startTime + voiceParams.delayModLFO);
|
|
1022
|
+
note.modLfo.connect(note.modLfoToFilterFc);
|
|
1023
|
+
note.modLfoToFilterFc.connect(note.filterEnvelopeNode.frequency);
|
|
1024
|
+
note.modLfo.connect(note.modLfoToPitch);
|
|
1025
|
+
note.modLfoToPitch.connect(note.bufferSource.detune);
|
|
1026
|
+
note.modLfo.connect(note.modLfoToVolume);
|
|
1027
|
+
note.modLfoToVolume.connect(note.volumeEnvelopeNode.gain);
|
|
968
1028
|
}
|
|
969
1029
|
async getAudioBuffer(channel, noteNumber, velocity, voiceParams, realtime) {
|
|
970
1030
|
const audioBufferId = this.getVoiceId(channel, noteNumber, velocity);
|
|
@@ -1005,7 +1065,7 @@ class MidyGM1 extends EventTarget {
|
|
|
1005
1065
|
const audioBuffer = await this.getAudioBuffer(channel, noteNumber, velocity, voiceParams, realtime);
|
|
1006
1066
|
note.bufferSource = this.createBufferSource(voiceParams, audioBuffer);
|
|
1007
1067
|
note.volumeEnvelopeNode = new GainNode(audioContext);
|
|
1008
|
-
note.
|
|
1068
|
+
note.filterEnvelopeNode = new BiquadFilterNode(audioContext, {
|
|
1009
1069
|
type: "lowpass",
|
|
1010
1070
|
Q: voiceParams.initialFilterQ / 10, // dB
|
|
1011
1071
|
});
|
|
@@ -1016,8 +1076,8 @@ class MidyGM1 extends EventTarget {
|
|
|
1016
1076
|
if (0 < state.modulationDepthMSB) {
|
|
1017
1077
|
this.startModulation(channel, note, now);
|
|
1018
1078
|
}
|
|
1019
|
-
note.bufferSource.connect(note.
|
|
1020
|
-
note.
|
|
1079
|
+
note.bufferSource.connect(note.filterEnvelopeNode);
|
|
1080
|
+
note.filterEnvelopeNode.connect(note.volumeEnvelopeNode);
|
|
1021
1081
|
if (voiceParams.sample.type === "compressed") {
|
|
1022
1082
|
const offset = voiceParams.start / audioBuffer.sampleRate;
|
|
1023
1083
|
note.bufferSource.start(startTime, offset);
|
|
@@ -1083,19 +1143,19 @@ class MidyGM1 extends EventTarget {
|
|
|
1083
1143
|
}
|
|
1084
1144
|
disconnectNote(note) {
|
|
1085
1145
|
note.bufferSource.disconnect();
|
|
1086
|
-
note.
|
|
1146
|
+
note.filterEnvelopeNode.disconnect();
|
|
1087
1147
|
note.volumeEnvelopeNode.disconnect();
|
|
1088
|
-
if (note.
|
|
1089
|
-
note.
|
|
1090
|
-
note.
|
|
1091
|
-
note.
|
|
1148
|
+
if (note.modLfoToPitch) {
|
|
1149
|
+
note.modLfoToVolume.disconnect();
|
|
1150
|
+
note.modLfoToPitch.disconnect();
|
|
1151
|
+
note.modLfo.stop();
|
|
1092
1152
|
}
|
|
1093
1153
|
}
|
|
1094
1154
|
releaseNote(channel, note, endTime) {
|
|
1095
1155
|
endTime ??= this.audioContext.currentTime;
|
|
1096
1156
|
const volDuration = note.voiceParams.volRelease;
|
|
1097
1157
|
const volRelease = endTime + volDuration;
|
|
1098
|
-
note.
|
|
1158
|
+
note.filterEnvelopeNode.frequency
|
|
1099
1159
|
.cancelScheduledValues(endTime)
|
|
1100
1160
|
.setTargetAtTime(note.adjustedBaseFreq, endTime, note.voiceParams.modRelease * releaseCurve);
|
|
1101
1161
|
note.volumeEnvelopeNode.gain
|
|
@@ -1223,12 +1283,12 @@ class MidyGM1 extends EventTarget {
|
|
|
1223
1283
|
this.applyVoiceParams(channel, 14, scheduleTime);
|
|
1224
1284
|
}
|
|
1225
1285
|
setModLfoToPitch(channel, note, scheduleTime) {
|
|
1226
|
-
if (note.
|
|
1286
|
+
if (note.modLfoToPitch) {
|
|
1227
1287
|
const modLfoToPitch = note.voiceParams.modLfoToPitch;
|
|
1228
1288
|
const baseDepth = Math.abs(modLfoToPitch) +
|
|
1229
1289
|
channel.state.modulationDepthMSB;
|
|
1230
1290
|
const depth = baseDepth * Math.sign(modLfoToPitch);
|
|
1231
|
-
note.
|
|
1291
|
+
note.modLfoToPitch.gain
|
|
1232
1292
|
.cancelScheduledValues(scheduleTime)
|
|
1233
1293
|
.setValueAtTime(depth, scheduleTime);
|
|
1234
1294
|
}
|
|
@@ -1238,29 +1298,29 @@ class MidyGM1 extends EventTarget {
|
|
|
1238
1298
|
}
|
|
1239
1299
|
setModLfoToFilterFc(note, scheduleTime) {
|
|
1240
1300
|
const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc;
|
|
1241
|
-
note.
|
|
1301
|
+
note.modLfoToFilterFc.gain
|
|
1242
1302
|
.cancelScheduledValues(scheduleTime)
|
|
1243
1303
|
.setValueAtTime(modLfoToFilterFc, scheduleTime);
|
|
1244
1304
|
}
|
|
1245
1305
|
setModLfoToVolume(note, scheduleTime) {
|
|
1246
1306
|
const modLfoToVolume = note.voiceParams.modLfoToVolume;
|
|
1247
1307
|
const baseDepth = cbToRatio(Math.abs(modLfoToVolume)) - 1;
|
|
1248
|
-
const
|
|
1249
|
-
note.
|
|
1308
|
+
const depth = baseDepth * Math.sign(modLfoToVolume);
|
|
1309
|
+
note.modLfoToVolume.gain
|
|
1250
1310
|
.cancelScheduledValues(scheduleTime)
|
|
1251
|
-
.setValueAtTime(
|
|
1311
|
+
.setValueAtTime(depth, scheduleTime);
|
|
1252
1312
|
}
|
|
1253
1313
|
setDelayModLFO(note, scheduleTime) {
|
|
1254
1314
|
const startTime = note.startTime;
|
|
1255
1315
|
if (startTime < scheduleTime)
|
|
1256
1316
|
return;
|
|
1257
|
-
note.
|
|
1258
|
-
note.
|
|
1259
|
-
note.
|
|
1317
|
+
note.modLfo.stop(scheduleTime);
|
|
1318
|
+
note.modLfo.start(startTime + note.voiceParams.delayModLFO);
|
|
1319
|
+
note.modLfo.connect(note.modLfoToFilterFc);
|
|
1260
1320
|
}
|
|
1261
1321
|
setFreqModLFO(note, scheduleTime) {
|
|
1262
1322
|
const freqModLFO = note.voiceParams.freqModLFO;
|
|
1263
|
-
note.
|
|
1323
|
+
note.modLfo.frequency
|
|
1264
1324
|
.cancelScheduledValues(scheduleTime)
|
|
1265
1325
|
.setValueAtTime(freqModLFO, scheduleTime);
|
|
1266
1326
|
}
|
|
@@ -1357,6 +1417,8 @@ class MidyGM1 extends EventTarget {
|
|
|
1357
1417
|
return handlers;
|
|
1358
1418
|
}
|
|
1359
1419
|
setControlChange(channelNumber, controllerType, value, scheduleTime) {
|
|
1420
|
+
if (!(0 <= scheduleTime))
|
|
1421
|
+
scheduleTime = this.audioContext.currentTime;
|
|
1360
1422
|
const handler = this.controlChangeHandlers[controllerType];
|
|
1361
1423
|
if (handler) {
|
|
1362
1424
|
handler.call(this, channelNumber, value, scheduleTime);
|
|
@@ -1371,8 +1433,8 @@ class MidyGM1 extends EventTarget {
|
|
|
1371
1433
|
const depth = channel.state.modulationDepthMSB *
|
|
1372
1434
|
channel.modulationDepthRange;
|
|
1373
1435
|
this.processScheduledNotes(channel, (note) => {
|
|
1374
|
-
if (note.
|
|
1375
|
-
note.
|
|
1436
|
+
if (note.modLfoToPitch) {
|
|
1437
|
+
note.modLfoToPitch.gain.setValueAtTime(depth, scheduleTime);
|
|
1376
1438
|
}
|
|
1377
1439
|
else {
|
|
1378
1440
|
this.startModulation(channel, note, scheduleTime);
|
package/script/midy-GM2.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ export class MidyGM2 extends EventTarget {
|
|
|
46
46
|
voiceCounter: Map<any, any>;
|
|
47
47
|
voiceCache: Map<any, any>;
|
|
48
48
|
realtimeVoiceCache: Map<any, any>;
|
|
49
|
+
decodeMethod: string;
|
|
49
50
|
isPlaying: boolean;
|
|
50
51
|
isPausing: boolean;
|
|
51
52
|
isPaused: boolean;
|
|
@@ -80,6 +81,7 @@ export class MidyGM2 extends EventTarget {
|
|
|
80
81
|
};
|
|
81
82
|
controlChangeHandlers: any[];
|
|
82
83
|
keyBasedControllerHandlers: any[];
|
|
84
|
+
effectHandlers: any[];
|
|
83
85
|
channels: any[];
|
|
84
86
|
reverbEffect: {
|
|
85
87
|
input: any;
|
|
@@ -107,6 +109,7 @@ export class MidyGM2 extends EventTarget {
|
|
|
107
109
|
};
|
|
108
110
|
resetChannelTable(channel: any): void;
|
|
109
111
|
createChannels(audioContext: any): any[];
|
|
112
|
+
decodeOggVorbis(sample: any): Promise<any>;
|
|
110
113
|
createAudioBuffer(voiceParams: any): Promise<any>;
|
|
111
114
|
isLoopDrum(channel: any, noteNumber: any): boolean;
|
|
112
115
|
createBufferSource(channel: any, noteNumber: any, voiceParams: any, audioBuffer: any): any;
|
|
@@ -234,6 +237,7 @@ export class MidyGM2 extends EventTarget {
|
|
|
234
237
|
updatePortamento(channel: any, scheduleTime: any): void;
|
|
235
238
|
setPortamentoTime(channelNumber: any, value: any, scheduleTime: any): void;
|
|
236
239
|
setVolume(channelNumber: any, value: any, scheduleTime: any): void;
|
|
240
|
+
applyVolume(channel: any, scheduleTime: any): void;
|
|
237
241
|
panToGain(pan: any): {
|
|
238
242
|
gainLeft: number;
|
|
239
243
|
gainRight: number;
|
|
@@ -304,15 +308,23 @@ export class MidyGM2 extends EventTarget {
|
|
|
304
308
|
getChorusSendToReverb(value: any): number;
|
|
305
309
|
getChannelBitmap(data: any): any[];
|
|
306
310
|
handleScaleOctaveTuning1ByteFormatSysEx(data: any, realtime: any, scheduleTime: any): void;
|
|
311
|
+
calcEffectValue(channel: any, destination: any): number;
|
|
312
|
+
calcChannelEffectValue(channel: any, destination: any): number;
|
|
313
|
+
calcControlChangeEffectValue(channel: any, destination: any): number;
|
|
314
|
+
calcChannelPressureEffectValue(channel: any, destination: any): number;
|
|
315
|
+
getChannelPitchControl(channel: any): number;
|
|
316
|
+
getPitchControl(channel: any, note: any): number;
|
|
307
317
|
getFilterCutoffControl(channel: any): number;
|
|
308
|
-
|
|
318
|
+
getChannelAmplitudeControl(channel: any): number;
|
|
309
319
|
getLFOPitchDepth(channel: any): number;
|
|
310
320
|
getLFOFilterDepth(channel: any): number;
|
|
311
321
|
getLFOAmplitudeDepth(channel: any): number;
|
|
312
|
-
|
|
322
|
+
createEffectHandlers(): any[];
|
|
323
|
+
setControlChangeEffects(channel: any, note: any, scheduleTime: any): void;
|
|
324
|
+
setChannelPressureEffects(channel: any, note: any, scheduleTime: any): void;
|
|
325
|
+
setPressureEffects(channel: any, note: any, tableName: any, scheduleTime: any): void;
|
|
326
|
+
handleChannelPressureSysEx(data: any, scheduleTime: any): void;
|
|
313
327
|
handlePressureSysEx(data: any, tableName: any, scheduleTime: any): void;
|
|
314
|
-
initControlTable(): Int8Array<ArrayBuffer>;
|
|
315
|
-
setControlChangeEffects(channel: any, controllerType: any, scheduleTime: any): void;
|
|
316
328
|
handleControlChangeSysEx(data: any, scheduleTime: any): void;
|
|
317
329
|
getKeyBasedValue(channel: any, keyNumber: any, controllerType: any): any;
|
|
318
330
|
createKeyBasedControllerHandlers(): 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":"AAwLA;IAwDE;;;;;;;;;;;;;;MAcE;IAEF,+BAsBC;IAzFD,gCAAgC;IAChC,aAAa;IACb,yBAAqB;IACrB,2BAAuB;IACvB;;;;MAIE;IACF;;;;;;MAME;IACF,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAsB;IACtB,+BAA6B;IAC7B,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,0BAAuD;IACvD,4BAAyB;IACzB,0BAAuB;IACvB,kCAA+B;IAC/B,qBAAqC;IACrC,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,iCAEG;IACH,cAAU;IACV,cAAa;IACb,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IACrC,+BAEE;IAoBA,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF,uBAAmD;IACnD;;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,kCAAyE;IACzE,sBAAiD;IACjD,gBAAiD;IACjD;;;kBAAyD;IACzD;;;;;;;;MAAyD;IAQ3D,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAeC;IAED;;;;MAeC;IAED,sCAKC;IAED,yCAqBC;IAED,2CAsBC;IAED,kDA6BC;IAED,mDAIC;IAED,2FAWC;IAED,gEAyDC;IAED,mCASC;IAED,uBAUC;IAED,yDAqCC;IAED,2BAoFC;IAED,uDAEC;IAED,wDAEC;IAED,qCAMC;IAED;;;MAqFC;IAED,kGAeC;IAED,mGAeC;IAED,wEAQC;IAED,uBAMC;IAED,sBAIC;IAED,uBAMC;IAED,wBAIC;IAED,0BAKC;IAED,8BAMC;IAED,wBAYC;IAED,sBAIC;IAED,kEAWC;IAED,kFAYC;IAED,kFAuBC;IAED;;;;MASC;IAED,gFAUC;IAED,mFAYC;IAED,sGAcC;IAID;;;MA8BC;IAED;;;kBA6BC;IAED;;;;;;;;MA0CC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAWC;IAED,2DAQC;IAED,oDAEC;IAED,6CAIC;IAED,mDAIC;IAED,2CAoDC;IAED,8EASC;IAED,oEAgBC;IAED,sEASC;IAED,4DASC;IAED,6EAOC;IAED,qDAkBC;IAED,6CAIC;IAED,8EAmBC;IAED,oEA+BC;IAED,kEAqBC;IAED,+DAeC;IAED,4GAkCC;IAED,uEAkEC;IAED,0EAiBC;IAED,8EAoBC;IAED,oEAuBC;IAED,0FAuBC;IAED,gCAmBC;IAED,iEAwBC;IAED,4FA2BC;IAED,6CAUC;IAED,qDAUC;IAED,qFAeC;IAED,uFAkBC;IAED,+BAuBC;IAED,kDAOC;IAED,sBAEC;IAED,mFAcC;IAED,4EAYC;IAED,wFAGC;IAED,sEAWC;IAED,mEAaC;IAED,mEAYC;IAED,sEAMC;IAED,oEAQC;IAED,gEAyBC;IAED,gEAyBC;IAED,gCAKC;IAED,kDAKC;IAED,8CAOC;IAED,gEAMC;IAED;;;;;;;;;;;;MAwDC;IAED,oFAOC;IAED,6EA+BC;IAED,qCA2BC;IAED,+FAeC;IAED,+CAEC;IAED,wDAUC;IAED,4EAMC;IAED,wDAeC;IAED,2EAMC;IAED,mEAKC;IAED,mDAQC;IAED;;;MAMC;IAED,gEAWC;IAED,uEAKC;IAED,+CAEC;IAED,sEAGC;IAED,2DAWC;IAED,4EAoBC;IAED,yEAYC;IAED,+CAEC;IAED,uEAMC;IAED,2EAcC;IAED,oDAEC;IAED,0EAeC;IAED,sFAQC;IAED,sFAQC;IAED,kFAeC;IAED,2DAMC;IAED,uDAuBC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAWC;IAED,iEAMC;IAED,uEASC;IAED,mEAKC;IAED,yEASC;IAED,2EAKC;IAED,iFAMC;IAED,gFAGC;IAED,6CAwBC;IAGD,8EAoCC;IAED,gFAGC;IAED,iEAEC;IAED,gEAEC;IAED,gEAIC;IAED,gEAIC;IAED,+EAgCC;IAED,qCAaC;IAED,qCAaC;IAED,4EAwCC;IAED,4DAGC;IAED,qDAKC;IAED,gEAIC;IAED,yDAYC;IAED,kEAGC;IAED,2DAYC;IAED,sEAeC;IAED,4CAOC;IAED,+BAIC;IAED,qDAiBC;IAED,gCAGC;IAED,kCAEC;IA6BD,4CAEC;IAED,+DAaC;IAED,kDAiBC;IAED,2GAKC;IAED,sDAIC;IAED,qCAEC;IAED,uDAMC;IAED,sCAEC;IAED,uDASC;IAED,sCAEC;IAED,2DAqBC;IAED,0CAEC;IAED,mCAeC;IAED,2FAgBC;IAED,wDAEC;IAED,+DAGC;IAED,qEASC;IAED,uEAOC;IAED,6CAEC;IAED,iDAEC;IAED,6CAEC;IAED,iDAEC;IAED,uCAEC;IAED,wCAEC;IAED,2CAEC;IAED,8BAyBC;IAED,0EAQC;IAED,4EAOC;IAED,qFASC;IAED,+DAEC;IAED,wEAcC;IAED,6DAiBC;IAED,yEAIC;IAED,0CAmBC;IAED,yEAcC;IAED,gDAYC;IAGD,6DAgBC;CACF"}
|