@marmooo/midy 0.0.9 → 0.1.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 +0 -2
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +5 -9
- package/esm/midy-GM2.d.ts +31 -19
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +193 -56
- package/esm/midy-GMLite.js +5 -5
- package/esm/midy.d.ts +31 -19
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +193 -56
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +0 -2
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +5 -9
- package/script/midy-GM2.d.ts +31 -19
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +193 -56
- package/script/midy-GMLite.js +5 -5
- package/script/midy.d.ts +31 -19
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +193 -56
package/script/midy-GM2.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export class MidyGM2 {
|
|
|
4
4
|
volume: number;
|
|
5
5
|
pan: number;
|
|
6
6
|
portamentoTime: number;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
reverbSendLevel: number;
|
|
8
|
+
chorusSendLevel: number;
|
|
9
9
|
bank: number;
|
|
10
10
|
bankMSB: number;
|
|
11
11
|
bankLSB: number;
|
|
@@ -41,15 +41,22 @@ export class MidyGM2 {
|
|
|
41
41
|
reverbAlgorithm: (audioContext: any) => {
|
|
42
42
|
input: any;
|
|
43
43
|
output: any;
|
|
44
|
-
dryGain: any;
|
|
45
|
-
wetGain: any;
|
|
46
44
|
};
|
|
47
45
|
});
|
|
48
46
|
ticksPerBeat: number;
|
|
49
47
|
totalTime: number;
|
|
50
|
-
reverbFactor: number;
|
|
51
48
|
masterFineTuning: number;
|
|
52
49
|
masterCoarseTuning: number;
|
|
50
|
+
reverb: {
|
|
51
|
+
time: number;
|
|
52
|
+
feedback: number;
|
|
53
|
+
};
|
|
54
|
+
chorus: {
|
|
55
|
+
modRate: number;
|
|
56
|
+
modDepth: number;
|
|
57
|
+
feedback: number;
|
|
58
|
+
sendToReverb: number;
|
|
59
|
+
};
|
|
53
60
|
mono: boolean;
|
|
54
61
|
omni: boolean;
|
|
55
62
|
noteCheckInterval: number;
|
|
@@ -71,8 +78,6 @@ export class MidyGM2 {
|
|
|
71
78
|
reverbAlgorithm: (audioContext: any) => {
|
|
72
79
|
input: any;
|
|
73
80
|
output: any;
|
|
74
|
-
dryGain: any;
|
|
75
|
-
wetGain: any;
|
|
76
81
|
};
|
|
77
82
|
};
|
|
78
83
|
audioContext: any;
|
|
@@ -80,8 +85,6 @@ export class MidyGM2 {
|
|
|
80
85
|
reverbAlgorithm: (audioContext: any) => {
|
|
81
86
|
input: any;
|
|
82
87
|
output: any;
|
|
83
|
-
dryGain: any;
|
|
84
|
-
wetGain: any;
|
|
85
88
|
};
|
|
86
89
|
};
|
|
87
90
|
masterGain: any;
|
|
@@ -97,8 +100,6 @@ export class MidyGM2 {
|
|
|
97
100
|
reverbEffect: {
|
|
98
101
|
input: any;
|
|
99
102
|
output: any;
|
|
100
|
-
dryGain: any;
|
|
101
|
-
wetGain: any;
|
|
102
103
|
};
|
|
103
104
|
chorusEffect: {
|
|
104
105
|
lfo: any;
|
|
@@ -131,20 +132,18 @@ export class MidyGM2 {
|
|
|
131
132
|
currentTime(): number;
|
|
132
133
|
getActiveNotes(channel: any, time: any): Map<any, any>;
|
|
133
134
|
getActiveNote(noteList: any, time: any): any;
|
|
134
|
-
|
|
135
|
+
createConvolutionReverbImpulse(audioContext: any, decay: any, preDecay: any): any;
|
|
136
|
+
createConvolutionReverb(audioContext: any, impulse: any): {
|
|
135
137
|
input: any;
|
|
136
138
|
output: any;
|
|
137
|
-
dryGain: any;
|
|
138
|
-
wetGain: any;
|
|
139
139
|
convolverNode: any;
|
|
140
140
|
};
|
|
141
141
|
createCombFilter(audioContext: any, input: any, delay: any, feedback: any): any;
|
|
142
142
|
createAllpassFilter(audioContext: any, input: any, delay: any, feedback: any): any;
|
|
143
|
-
|
|
143
|
+
generateDistributedArray(center: any, count: any, varianceRatio?: number, randomness?: number): any[];
|
|
144
|
+
createSchroederReverb(audioContext: any, combDelays: any, combFeedbacks: any, allpassDelays: any, allpassFeedbacks: any): {
|
|
144
145
|
input: any;
|
|
145
146
|
output: any;
|
|
146
|
-
dryGain: any;
|
|
147
|
-
wetGain: any;
|
|
148
147
|
};
|
|
149
148
|
createChorusEffect(audioContext: any, options?: {}): {
|
|
150
149
|
lfo: any;
|
|
@@ -191,8 +190,8 @@ export class MidyGM2 {
|
|
|
191
190
|
updateChannelGain(channel: any): void;
|
|
192
191
|
setSustainPedal(channelNumber: any, value: any): void;
|
|
193
192
|
setPortamento(channelNumber: any, value: any): void;
|
|
194
|
-
setReverbSendLevel(channelNumber: any,
|
|
195
|
-
setChorusSendLevel(channelNumber: any,
|
|
193
|
+
setReverbSendLevel(channelNumber: any, reverbSendLevel: any): void;
|
|
194
|
+
setChorusSendLevel(channelNumber: any, chorusSendLevel: any): void;
|
|
196
195
|
setSostenutoPedal(channelNumber: any, value: any): void;
|
|
197
196
|
setSoftPedal(channelNumber: any, softPedal: any): void;
|
|
198
197
|
limitData(channel: any, minMSB: any, maxMSB: any, minLSB: any, maxLSB: any): void;
|
|
@@ -227,6 +226,19 @@ export class MidyGM2 {
|
|
|
227
226
|
setMasterFineTuning(fineTuning: any): void;
|
|
228
227
|
handleMasterCoarseTuningSysEx(data: any): void;
|
|
229
228
|
setMasterCoarseTuning(coarseTuning: any): void;
|
|
229
|
+
handleGlobalParameterControl(data: any): void;
|
|
230
|
+
handleReverbParameter(data: any): void;
|
|
231
|
+
setReverbType(type: any): void;
|
|
232
|
+
getReverbTimeFromType(type: any): number | undefined;
|
|
233
|
+
setReverbTime(value: any): void;
|
|
234
|
+
getReverbTime(value: any): number;
|
|
235
|
+
calcDelay(rt60: any, feedback: any): number;
|
|
236
|
+
handleChorusParameter(data: any): void;
|
|
237
|
+
setChorusType(type: any): void;
|
|
238
|
+
setChorusModRate(value: any): void;
|
|
239
|
+
setChorusModDepth(value: any): void;
|
|
240
|
+
setChorusFeedback(value: any): void;
|
|
241
|
+
setChorusSendToReverb(value: any): void;
|
|
230
242
|
handleExclusiveMessage(data: any): void;
|
|
231
243
|
handleSysEx(data: any): void;
|
|
232
244
|
scheduleTask(callback: any, startTime: any): Promise<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":"AAuBA;
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAuBA;IAiCE;;;;;;;;;;;;;;;;;MAiBE;IAEF;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAgCF;;;;;OAOC;IA9GD,qBAAmB;IACnB,kBAAc;IACd,yBAAqB;IACrB,2BAAuB;IACvB;;;MAGE;IACF;;;;;MAKE;IACF,cAAa;IACb,cAAa;IACb,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;IA2ClB;;;;;MA4BE;IAGA,kBAAgC;IAChC;;;;;MAAqD;IACrD,gBAA4C;IAE5C,gBAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;;;;;;;;;;;;MAkBC;IAED,yCAcC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EAkDC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgGC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,kFAuBC;IAED;;;;MAWC;IAED,gFAUC;IAED,mFAYC;IAED,sGAcC;IAID;;;MAiCC;IAED;;;;;;MAoCC;IAED,kDAsBC;IAED,2BAEC;IAED,4BAEC;IAED,sCAKC;IAED,mFAGC;IAED,iDAiBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHAiCC;IAED,gDAQC;IAED,kGAgCC;IAED,0EAGC;IAED,sIAiDC;IAED,0FAGC;IAED,kEAeC;IAED,oEAYC;IAED,wFAmBC;IAED,4DAIC;IAED,+DAcC;IAED,qEAGC;IAED,uDAOC;IAED,mFAuDC;IAED,+CAEC;IAED,qCAcC;IAED,yDAIC;IAED,iEAEC;IAED,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,+CAEC;IAED,mDAGC;IAED,sCAUC;IAED,sDAMC;IAGD,oDAEC;IAED,mEAOC;IAED,mEAIC;IAED,wDAWC;IAED,uDAGC;IAED,kFAeC;IAED,2DAMC;IAED,oCAqBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAUC;IAED,kDAKC;IAED,iEAOC;IAED,8CAKC;IAED,yDAMC;IAED,gDAKC;IAED,6DAMC;IAED,wDAKC;IAED,6EAKC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,gBAEC;IAED,eAEC;IAED,eAEC;IAED,eAEC;IAED,4DAmBC;IAED,oBAQC;IAED,oBAQC;IAED,yDAiDC;IAED,yCAGC;IAED,mCAQC;IAED,6CAGC;IAED,2CAMC;IAED,+CAGC;IAED,+CAMC;IAED,8CAeC;IAED,uCAOC;IAED,+BAOC;IAED,qDAiBC;IAED,gCAMC;IAED,kCAEC;IA2BD,4CAEC;IAED,uCAaC;IAED,+BAEC;IAED,mCAEC;IAED,oCAEC;IAED,oCAEC;IAED,wCAEC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAhsDD;IASE,gFAKC;IAbD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|
package/script/midy-GM2.js
CHANGED
|
@@ -67,12 +67,6 @@ class MidyGM2 {
|
|
|
67
67
|
writable: true,
|
|
68
68
|
value: 0
|
|
69
69
|
});
|
|
70
|
-
Object.defineProperty(this, "reverbFactor", {
|
|
71
|
-
enumerable: true,
|
|
72
|
-
configurable: true,
|
|
73
|
-
writable: true,
|
|
74
|
-
value: 0.1
|
|
75
|
-
});
|
|
76
70
|
Object.defineProperty(this, "masterFineTuning", {
|
|
77
71
|
enumerable: true,
|
|
78
72
|
configurable: true,
|
|
@@ -85,6 +79,26 @@ class MidyGM2 {
|
|
|
85
79
|
writable: true,
|
|
86
80
|
value: 0
|
|
87
81
|
}); // cb
|
|
82
|
+
Object.defineProperty(this, "reverb", {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
configurable: true,
|
|
85
|
+
writable: true,
|
|
86
|
+
value: {
|
|
87
|
+
time: this.getReverbTime(64),
|
|
88
|
+
feedback: 0.2,
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
Object.defineProperty(this, "chorus", {
|
|
92
|
+
enumerable: true,
|
|
93
|
+
configurable: true,
|
|
94
|
+
writable: true,
|
|
95
|
+
value: {
|
|
96
|
+
modRate: 3 * 0.122,
|
|
97
|
+
modDepth: (3 + 1) / 3.2,
|
|
98
|
+
feedback: 8 * 0.763,
|
|
99
|
+
sendToReverb: 0 * 0.787,
|
|
100
|
+
}
|
|
101
|
+
});
|
|
88
102
|
Object.defineProperty(this, "mono", {
|
|
89
103
|
enumerable: true,
|
|
90
104
|
configurable: true,
|
|
@@ -193,8 +207,19 @@ class MidyGM2 {
|
|
|
193
207
|
writable: true,
|
|
194
208
|
value: {
|
|
195
209
|
reverbAlgorithm: (audioContext) => {
|
|
196
|
-
|
|
197
|
-
|
|
210
|
+
const { time: rt60, feedback } = this.reverb;
|
|
211
|
+
// const delay = this.calcDelay(rt60, feedback);
|
|
212
|
+
// const impulse = this.createConvolutionReverbImpulse(
|
|
213
|
+
// audioContext,
|
|
214
|
+
// rt60,
|
|
215
|
+
// delay,
|
|
216
|
+
// );
|
|
217
|
+
// return this.createConvolutionReverb(audioContext, impulse);
|
|
218
|
+
const combFeedbacks = this.generateDistributedArray(feedback, 4);
|
|
219
|
+
const combDelays = combFeedbacks.map((feedback) => this.calcDelay(rt60, feedback));
|
|
220
|
+
const allpassFeedbacks = this.generateDistributedArray(feedback, 4);
|
|
221
|
+
const allpassDelays = allpassFeedbacks.map((feedback) => this.calcDelay(rt60, feedback));
|
|
222
|
+
return this.createSchroederReverb(audioContext, combFeedbacks, combDelays, allpassFeedbacks, allpassDelays);
|
|
198
223
|
},
|
|
199
224
|
}
|
|
200
225
|
});
|
|
@@ -593,12 +618,7 @@ class MidyGM2 {
|
|
|
593
618
|
}
|
|
594
619
|
return noteList[0];
|
|
595
620
|
}
|
|
596
|
-
|
|
597
|
-
const { decay = 0.8, preDecay = 0, } = options;
|
|
598
|
-
const input = new GainNode(audioContext);
|
|
599
|
-
const output = new GainNode(audioContext);
|
|
600
|
-
const dryGain = new GainNode(audioContext);
|
|
601
|
-
const wetGain = new GainNode(audioContext);
|
|
621
|
+
createConvolutionReverbImpulse(audioContext, decay, preDecay) {
|
|
602
622
|
const sampleRate = audioContext.sampleRate;
|
|
603
623
|
const length = sampleRate * decay;
|
|
604
624
|
const impulse = new AudioBuffer({
|
|
@@ -618,18 +638,17 @@ class MidyGM2 {
|
|
|
618
638
|
channelData[i] = (Math.random() * 2 - 1) * attenuation;
|
|
619
639
|
}
|
|
620
640
|
}
|
|
641
|
+
return impulse;
|
|
642
|
+
}
|
|
643
|
+
createConvolutionReverb(audioContext, impulse) {
|
|
644
|
+
const output = new GainNode(audioContext);
|
|
621
645
|
const convolverNode = new ConvolverNode(audioContext, {
|
|
622
646
|
buffer: impulse,
|
|
623
647
|
});
|
|
624
|
-
|
|
625
|
-
convolverNode.connect(wetGain);
|
|
626
|
-
wetGain.connect(output);
|
|
627
|
-
dryGain.connect(output);
|
|
648
|
+
convolverNode.connect(output);
|
|
628
649
|
return {
|
|
629
|
-
input,
|
|
650
|
+
input: convolverNode,
|
|
630
651
|
output,
|
|
631
|
-
dryGain,
|
|
632
|
-
wetGain,
|
|
633
652
|
convolverNode,
|
|
634
653
|
};
|
|
635
654
|
}
|
|
@@ -657,17 +676,24 @@ class MidyGM2 {
|
|
|
657
676
|
delayNode.connect(passGain);
|
|
658
677
|
return passGain;
|
|
659
678
|
}
|
|
679
|
+
generateDistributedArray(center, count, varianceRatio = 0.1, randomness = 0.05) {
|
|
680
|
+
const variance = center * varianceRatio;
|
|
681
|
+
const array = new Array(count);
|
|
682
|
+
for (let i = 0; i < count; i++) {
|
|
683
|
+
const fraction = i / (count - 1 || 1);
|
|
684
|
+
const value = center - variance + fraction * 2 * variance;
|
|
685
|
+
array[i] = value * (1 - (Math.random() * 2 - 1) * randomness);
|
|
686
|
+
}
|
|
687
|
+
return array;
|
|
688
|
+
}
|
|
660
689
|
// https://hajim.rochester.edu/ece/sites/zduan/teaching/ece472/reading/Schroeder_1962.pdf
|
|
661
690
|
// M.R.Schroeder, "Natural Sounding Artificial Reverberation", J.Audio Eng. Soc., vol.10, p.219, 1962
|
|
662
|
-
createSchroederReverb(audioContext,
|
|
663
|
-
const { combDelays = [0.31, 0.34, 0.37, 0.40], combFeedbacks = [0.86, 0.87, 0.88, 0.89], allpassDelays = [0.02, 0.05], allpassFeedbacks = [0.7, 0.7], mix = 0.5, } = options;
|
|
691
|
+
createSchroederReverb(audioContext, combDelays, combFeedbacks, allpassDelays, allpassFeedbacks) {
|
|
664
692
|
const input = new GainNode(audioContext);
|
|
665
693
|
const output = new GainNode(audioContext);
|
|
666
694
|
const mergerGain = new GainNode(audioContext, {
|
|
667
695
|
gain: 1 / (combDelays.length * 2),
|
|
668
696
|
});
|
|
669
|
-
const dryGain = new GainNode(audioContext, { gain: 1 - mix });
|
|
670
|
-
const wetGain = new GainNode(audioContext, { gain: mix });
|
|
671
697
|
for (let i = 0; i < combDelays.length; i++) {
|
|
672
698
|
const comb = this.createCombFilter(audioContext, input, combDelays[i], combFeedbacks[i]);
|
|
673
699
|
comb.connect(mergerGain);
|
|
@@ -677,11 +703,8 @@ class MidyGM2 {
|
|
|
677
703
|
const allpass = this.createAllpassFilter(audioContext, (i === 0) ? mergerGain : allpasses.at(-1), allpassDelays[i], allpassFeedbacks[i]);
|
|
678
704
|
allpasses.push(allpass);
|
|
679
705
|
}
|
|
680
|
-
allpasses.at(-1).connect(
|
|
681
|
-
input
|
|
682
|
-
dryGain.connect(output);
|
|
683
|
-
wetGain.connect(output);
|
|
684
|
-
return { input, output, dryGain, wetGain };
|
|
706
|
+
allpasses.at(-1).connect(output);
|
|
707
|
+
return { input, output };
|
|
685
708
|
}
|
|
686
709
|
createChorusEffect(audioContext, options = {}) {
|
|
687
710
|
const { chorusCount = 2, chorusRate = 0.6, chorusDepth = 0.15, delay = 0.01, variance = delay * 0.1, } = options;
|
|
@@ -716,11 +739,9 @@ class MidyGM2 {
|
|
|
716
739
|
}
|
|
717
740
|
connectEffects(channel, gainNode) {
|
|
718
741
|
gainNode.connect(channel.merger);
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
}
|
|
723
|
-
else { // chorus
|
|
742
|
+
channel.merger.connect(this.masterGain);
|
|
743
|
+
if (channel.reverbSendLevel === 0) {
|
|
744
|
+
if (channel.chorusSendLevel !== 0) { // chorus
|
|
724
745
|
channel.chorusEffect.delayNodes.forEach((delayNode) => {
|
|
725
746
|
channel.merger.connect(delayNode);
|
|
726
747
|
});
|
|
@@ -728,7 +749,7 @@ class MidyGM2 {
|
|
|
728
749
|
}
|
|
729
750
|
}
|
|
730
751
|
else {
|
|
731
|
-
if (channel.
|
|
752
|
+
if (channel.chorusSendLevel === 0) { // reverb
|
|
732
753
|
channel.merger.connect(channel.reverbEffect.input);
|
|
733
754
|
channel.reverbEffect.output.connect(this.masterGain);
|
|
734
755
|
}
|
|
@@ -1139,23 +1160,22 @@ class MidyGM2 {
|
|
|
1139
1160
|
this.releaseSustainPedal(channelNumber, value);
|
|
1140
1161
|
}
|
|
1141
1162
|
}
|
|
1163
|
+
// TODO
|
|
1142
1164
|
setPortamento(channelNumber, value) {
|
|
1143
1165
|
this.channels[channelNumber].portamento = value >= 64;
|
|
1144
1166
|
}
|
|
1145
|
-
setReverbSendLevel(channelNumber,
|
|
1167
|
+
setReverbSendLevel(channelNumber, reverbSendLevel) {
|
|
1146
1168
|
const now = this.audioContext.currentTime;
|
|
1147
1169
|
const channel = this.channels[channelNumber];
|
|
1148
1170
|
const reverbEffect = channel.reverbEffect;
|
|
1149
|
-
channel.
|
|
1150
|
-
reverbEffect.
|
|
1151
|
-
reverbEffect.
|
|
1152
|
-
reverbEffect.wetGain.gain.cancelScheduledValues(now);
|
|
1153
|
-
reverbEffect.wetGain.gain.setValueAtTime(channel.reverb, now);
|
|
1171
|
+
channel.reverbSendLevel = reverbSendLevel / 127;
|
|
1172
|
+
reverbEffect.output.gain.cancelScheduledValues(now);
|
|
1173
|
+
reverbEffect.output.gain.setValueAtTime(channel.reverbSendLevel, now);
|
|
1154
1174
|
}
|
|
1155
|
-
setChorusSendLevel(channelNumber,
|
|
1175
|
+
setChorusSendLevel(channelNumber, chorusSendLevel) {
|
|
1156
1176
|
const channel = this.channels[channelNumber];
|
|
1157
|
-
channel.
|
|
1158
|
-
channel.chorusEffect.lfoGain = channel.
|
|
1177
|
+
channel.chorusSendLevel = chorusSendLevel / 127;
|
|
1178
|
+
channel.chorusEffect.lfoGain = channel.chorusSendLevel;
|
|
1159
1179
|
}
|
|
1160
1180
|
setSostenutoPedal(channelNumber, value) {
|
|
1161
1181
|
const isOn = value >= 64;
|
|
@@ -1351,11 +1371,11 @@ class MidyGM2 {
|
|
|
1351
1371
|
this.GM2SystemOn();
|
|
1352
1372
|
break;
|
|
1353
1373
|
default:
|
|
1354
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1374
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1355
1375
|
}
|
|
1356
1376
|
break;
|
|
1357
1377
|
default:
|
|
1358
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1378
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1359
1379
|
}
|
|
1360
1380
|
}
|
|
1361
1381
|
GM1SystemOn() {
|
|
@@ -1386,9 +1406,10 @@ class MidyGM2 {
|
|
|
1386
1406
|
return this.handleMasterFineTuningSysEx(data);
|
|
1387
1407
|
case 4: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
|
|
1388
1408
|
return this.handleMasterCoarseTuningSysEx(data);
|
|
1389
|
-
|
|
1409
|
+
case 5:
|
|
1410
|
+
return this.handleGlobalParameterControl(data);
|
|
1390
1411
|
default:
|
|
1391
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1412
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1392
1413
|
}
|
|
1393
1414
|
break;
|
|
1394
1415
|
case 8:
|
|
@@ -1397,7 +1418,7 @@ class MidyGM2 {
|
|
|
1397
1418
|
// // TODO
|
|
1398
1419
|
// return this.handleScaleOctaveTuning1ByteFormat();
|
|
1399
1420
|
default:
|
|
1400
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1421
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1401
1422
|
}
|
|
1402
1423
|
break;
|
|
1403
1424
|
case 9:
|
|
@@ -1409,7 +1430,7 @@ class MidyGM2 {
|
|
|
1409
1430
|
// // TODO
|
|
1410
1431
|
// return this.setControlChange();
|
|
1411
1432
|
default:
|
|
1412
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1433
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1413
1434
|
}
|
|
1414
1435
|
break;
|
|
1415
1436
|
case 10:
|
|
@@ -1418,11 +1439,11 @@ class MidyGM2 {
|
|
|
1418
1439
|
// // TODO
|
|
1419
1440
|
// return this.handleKeyBasedInstrumentControl();
|
|
1420
1441
|
default:
|
|
1421
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1442
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1422
1443
|
}
|
|
1423
1444
|
break;
|
|
1424
1445
|
default:
|
|
1425
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1446
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1426
1447
|
}
|
|
1427
1448
|
}
|
|
1428
1449
|
handleMasterVolumeSysEx(data) {
|
|
@@ -1463,8 +1484,124 @@ class MidyGM2 {
|
|
|
1463
1484
|
this.masterCoarseTuning = coarseTuning - 64;
|
|
1464
1485
|
}
|
|
1465
1486
|
}
|
|
1487
|
+
handleGlobalParameterControl(data) {
|
|
1488
|
+
if (data[5] === 1) {
|
|
1489
|
+
switch (data[6]) {
|
|
1490
|
+
case 1:
|
|
1491
|
+
return this.handleReverbParameter(data);
|
|
1492
|
+
case 2:
|
|
1493
|
+
return this.handleChorusParameter(data);
|
|
1494
|
+
default:
|
|
1495
|
+
console.warn(`Unsupported Global Parameter Control Message: ${data}`);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
else {
|
|
1499
|
+
console.warn(`Unsupported Global Parameter Control Message: ${data}`);
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
handleReverbParameter(data) {
|
|
1503
|
+
switch (data[7]) {
|
|
1504
|
+
case 0:
|
|
1505
|
+
return this.setReverbType(data[8]);
|
|
1506
|
+
case 1:
|
|
1507
|
+
return this.setReverbTime(data[8]);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
setReverbType(type) {
|
|
1511
|
+
this.reverb.time = this.getReverbTimeFromType(type);
|
|
1512
|
+
this.reverb.feedback = (type === 8) ? 0.1 : 0.2;
|
|
1513
|
+
const { audioContext, channels, options } = this;
|
|
1514
|
+
for (let i = 0; i < channels.length; i++) {
|
|
1515
|
+
channels[i].reverbEffect = options.reverbAlgorithm(audioContext);
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
getReverbTimeFromType(type) {
|
|
1519
|
+
switch (type) {
|
|
1520
|
+
case 0:
|
|
1521
|
+
return this.getReverbTime(44);
|
|
1522
|
+
case 1:
|
|
1523
|
+
return this.getReverbTime(50);
|
|
1524
|
+
case 2:
|
|
1525
|
+
return this.getReverbTime(56);
|
|
1526
|
+
case 3:
|
|
1527
|
+
return this.getReverbTime(64);
|
|
1528
|
+
case 4:
|
|
1529
|
+
return this.getReverbTime(64);
|
|
1530
|
+
case 8:
|
|
1531
|
+
return this.getReverbTime(50);
|
|
1532
|
+
default:
|
|
1533
|
+
console.warn(`Unsupported Reverb Time: ${type}`);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
setReverbTime(value) {
|
|
1537
|
+
this.reverb.time = this.getReverbTime(value);
|
|
1538
|
+
const { audioContext, channels, options } = this;
|
|
1539
|
+
for (let i = 0; i < channels.length; i++) {
|
|
1540
|
+
channels[i].reverbEffect = options.reverbAlgorithm(audioContext);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
getReverbTime(value) {
|
|
1544
|
+
return Math.pow(Math.E, (value - 40) * 0.025);
|
|
1545
|
+
}
|
|
1546
|
+
// mean free path equation
|
|
1547
|
+
// https://repository.dl.itc.u-tokyo.ac.jp/record/8550/files/A31912.pdf
|
|
1548
|
+
// 江田和司, 拡散性制御に基づく室内音響設計に向けた音場解析に関する研究, 2015
|
|
1549
|
+
// V: room size (m^3)
|
|
1550
|
+
// S: room surface area (m^2)
|
|
1551
|
+
// meanFreePath = 4V / S (m)
|
|
1552
|
+
// delay estimation using mean free path
|
|
1553
|
+
// t: degree Celsius, generally used 20
|
|
1554
|
+
// c: speed of sound = 331.5 + 0.61t = 331.5 * 0.61 * 20 = 343.7 (m/s)
|
|
1555
|
+
// delay = meanFreePath / c (s)
|
|
1556
|
+
// feedback equation
|
|
1557
|
+
// RT60 means that the energy is reduced to Math.pow(10, -6).
|
|
1558
|
+
// Since energy is proportional to the square of the amplitude,
|
|
1559
|
+
// the amplitude is reduced to Math.pow(10, -3).
|
|
1560
|
+
// When this is done through n feedbacks,
|
|
1561
|
+
// Math.pow(feedback, n) = Math.pow(10, -3)
|
|
1562
|
+
// Math.pow(feedback, RT60 / delay) = Math.pow(10, -3)
|
|
1563
|
+
// RT60 / delay * Math.log10(feedback) = -3
|
|
1564
|
+
// RT60 = -3 * delay / Math.log10(feedback)
|
|
1565
|
+
// feedback = Math.pow(10, -3 * delay / RT60)
|
|
1566
|
+
// delay estimation using ideal feedback
|
|
1567
|
+
// A suitable average sound absorption coefficient is 0.18-0.28.
|
|
1568
|
+
// Since the structure of the hall is complex,
|
|
1569
|
+
// It would be easier to determine the delay based on the ideal feedback.
|
|
1570
|
+
// delay = -RT60 * Math.log10(feedback) / 3
|
|
1571
|
+
calcDelay(rt60, feedback) {
|
|
1572
|
+
return -rt60 * Math.log10(feedback) / 3;
|
|
1573
|
+
}
|
|
1574
|
+
handleChorusParameter(data) {
|
|
1575
|
+
switch (data[7]) {
|
|
1576
|
+
case 0:
|
|
1577
|
+
return this.setChorusType(data[8]);
|
|
1578
|
+
case 1:
|
|
1579
|
+
return this.setChorusModRate(data[8]);
|
|
1580
|
+
case 2:
|
|
1581
|
+
return this.setChorusModDepth(data[8]);
|
|
1582
|
+
case 3:
|
|
1583
|
+
return this.setChorusFeedback(data[8]);
|
|
1584
|
+
case 4:
|
|
1585
|
+
return this.setChorusSendToReverb(data[8]);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
setChorusType(type) {
|
|
1589
|
+
// TODO
|
|
1590
|
+
}
|
|
1591
|
+
setChorusModRate(value) {
|
|
1592
|
+
// TODO
|
|
1593
|
+
}
|
|
1594
|
+
setChorusModDepth(value) {
|
|
1595
|
+
// TODO
|
|
1596
|
+
}
|
|
1597
|
+
setChorusFeedback(value) {
|
|
1598
|
+
// TODO
|
|
1599
|
+
}
|
|
1600
|
+
setChorusSendToReverb(value) {
|
|
1601
|
+
// TODO
|
|
1602
|
+
}
|
|
1466
1603
|
handleExclusiveMessage(data) {
|
|
1467
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1604
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1468
1605
|
}
|
|
1469
1606
|
handleSysEx(data) {
|
|
1470
1607
|
switch (data[0]) {
|
|
@@ -1498,8 +1635,8 @@ Object.defineProperty(MidyGM2, "channelSettings", {
|
|
|
1498
1635
|
volume: 100 / 127,
|
|
1499
1636
|
pan: 64,
|
|
1500
1637
|
portamentoTime: 0,
|
|
1501
|
-
|
|
1502
|
-
|
|
1638
|
+
reverbSendLevel: 0,
|
|
1639
|
+
chorusSendLevel: 0,
|
|
1503
1640
|
bank: 121 * 128,
|
|
1504
1641
|
bankMSB: 121,
|
|
1505
1642
|
bankLSB: 0,
|
package/script/midy-GMLite.js
CHANGED
|
@@ -896,11 +896,11 @@ class MidyGMLite {
|
|
|
896
896
|
case 2: // GM System Off
|
|
897
897
|
break;
|
|
898
898
|
default:
|
|
899
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
899
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
900
900
|
}
|
|
901
901
|
break;
|
|
902
902
|
default:
|
|
903
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
903
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
904
904
|
}
|
|
905
905
|
}
|
|
906
906
|
GM1SystemOn() {
|
|
@@ -919,11 +919,11 @@ class MidyGMLite {
|
|
|
919
919
|
case 1:
|
|
920
920
|
return this.handleMasterVolumeSysEx(data);
|
|
921
921
|
default:
|
|
922
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
922
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
923
923
|
}
|
|
924
924
|
break;
|
|
925
925
|
default:
|
|
926
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
926
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
927
927
|
}
|
|
928
928
|
}
|
|
929
929
|
handleMasterVolumeSysEx(data) {
|
|
@@ -941,7 +941,7 @@ class MidyGMLite {
|
|
|
941
941
|
}
|
|
942
942
|
}
|
|
943
943
|
handleExclusiveMessage(data) {
|
|
944
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
944
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
945
945
|
}
|
|
946
946
|
handleSysEx(data) {
|
|
947
947
|
switch (data[0]) {
|
package/script/midy.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export class Midy {
|
|
|
4
4
|
volume: number;
|
|
5
5
|
pan: number;
|
|
6
6
|
portamentoTime: number;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
reverbSendLevel: number;
|
|
8
|
+
chorusSendLevel: number;
|
|
9
9
|
vibratoRate: number;
|
|
10
10
|
vibratoDepth: number;
|
|
11
11
|
vibratoDelay: number;
|
|
@@ -44,15 +44,22 @@ export class Midy {
|
|
|
44
44
|
reverbAlgorithm: (audioContext: any) => {
|
|
45
45
|
input: any;
|
|
46
46
|
output: any;
|
|
47
|
-
dryGain: any;
|
|
48
|
-
wetGain: any;
|
|
49
47
|
};
|
|
50
48
|
});
|
|
51
49
|
ticksPerBeat: number;
|
|
52
50
|
totalTime: number;
|
|
53
|
-
reverbFactor: number;
|
|
54
51
|
masterFineTuning: number;
|
|
55
52
|
masterCoarseTuning: number;
|
|
53
|
+
reverb: {
|
|
54
|
+
time: number;
|
|
55
|
+
feedback: number;
|
|
56
|
+
};
|
|
57
|
+
chorus: {
|
|
58
|
+
modRate: number;
|
|
59
|
+
modDepth: number;
|
|
60
|
+
feedback: number;
|
|
61
|
+
sendToReverb: number;
|
|
62
|
+
};
|
|
56
63
|
mono: boolean;
|
|
57
64
|
omni: boolean;
|
|
58
65
|
noteCheckInterval: number;
|
|
@@ -74,8 +81,6 @@ export class Midy {
|
|
|
74
81
|
reverbAlgorithm: (audioContext: any) => {
|
|
75
82
|
input: any;
|
|
76
83
|
output: any;
|
|
77
|
-
dryGain: any;
|
|
78
|
-
wetGain: any;
|
|
79
84
|
};
|
|
80
85
|
};
|
|
81
86
|
audioContext: any;
|
|
@@ -83,8 +88,6 @@ export class Midy {
|
|
|
83
88
|
reverbAlgorithm: (audioContext: any) => {
|
|
84
89
|
input: any;
|
|
85
90
|
output: any;
|
|
86
|
-
dryGain: any;
|
|
87
|
-
wetGain: any;
|
|
88
91
|
};
|
|
89
92
|
};
|
|
90
93
|
masterGain: any;
|
|
@@ -100,8 +103,6 @@ export class Midy {
|
|
|
100
103
|
reverbEffect: {
|
|
101
104
|
input: any;
|
|
102
105
|
output: any;
|
|
103
|
-
dryGain: any;
|
|
104
|
-
wetGain: any;
|
|
105
106
|
};
|
|
106
107
|
chorusEffect: {
|
|
107
108
|
lfo: any;
|
|
@@ -134,20 +135,18 @@ export class Midy {
|
|
|
134
135
|
currentTime(): number;
|
|
135
136
|
getActiveNotes(channel: any, time: any): Map<any, any>;
|
|
136
137
|
getActiveNote(noteList: any, time: any): any;
|
|
137
|
-
|
|
138
|
+
createConvolutionReverbImpulse(audioContext: any, decay: any, preDecay: any): any;
|
|
139
|
+
createConvolutionReverb(audioContext: any, impulse: any): {
|
|
138
140
|
input: any;
|
|
139
141
|
output: any;
|
|
140
|
-
dryGain: any;
|
|
141
|
-
wetGain: any;
|
|
142
142
|
convolverNode: any;
|
|
143
143
|
};
|
|
144
144
|
createCombFilter(audioContext: any, input: any, delay: any, feedback: any): any;
|
|
145
145
|
createAllpassFilter(audioContext: any, input: any, delay: any, feedback: any): any;
|
|
146
|
-
|
|
146
|
+
generateDistributedArray(center: any, count: any, varianceRatio?: number, randomness?: number): any[];
|
|
147
|
+
createSchroederReverb(audioContext: any, combDelays: any, combFeedbacks: any, allpassDelays: any, allpassFeedbacks: any): {
|
|
147
148
|
input: any;
|
|
148
149
|
output: any;
|
|
149
|
-
dryGain: any;
|
|
150
|
-
wetGain: any;
|
|
151
150
|
};
|
|
152
151
|
createChorusEffect(audioContext: any, options?: {}): {
|
|
153
152
|
lfo: any;
|
|
@@ -196,8 +195,8 @@ export class Midy {
|
|
|
196
195
|
updateChannelGain(channel: any): void;
|
|
197
196
|
setSustainPedal(channelNumber: any, value: any): void;
|
|
198
197
|
setPortamento(channelNumber: any, value: any): void;
|
|
199
|
-
setReverbSendLevel(channelNumber: any,
|
|
200
|
-
setChorusSendLevel(channelNumber: any,
|
|
198
|
+
setReverbSendLevel(channelNumber: any, reverbSendLevel: any): void;
|
|
199
|
+
setChorusSendLevel(channelNumber: any, chorusSendLevel: any): void;
|
|
201
200
|
setSostenutoPedal(channelNumber: any, value: any): void;
|
|
202
201
|
setSoftPedal(channelNumber: any, softPedal: any): void;
|
|
203
202
|
setVibratoRate(channelNumber: any, vibratoRate: any): void;
|
|
@@ -237,6 +236,19 @@ export class Midy {
|
|
|
237
236
|
setMasterFineTuning(fineTuning: any): void;
|
|
238
237
|
handleMasterCoarseTuningSysEx(data: any): void;
|
|
239
238
|
setMasterCoarseTuning(coarseTuning: any): void;
|
|
239
|
+
handleGlobalParameterControl(data: any): void;
|
|
240
|
+
handleReverbParameter(data: any): void;
|
|
241
|
+
setReverbType(type: any): void;
|
|
242
|
+
getReverbTimeFromType(type: any): number | undefined;
|
|
243
|
+
setReverbTime(value: any): void;
|
|
244
|
+
getReverbTime(value: any): number;
|
|
245
|
+
calcDelay(rt60: any, feedback: any): number;
|
|
246
|
+
handleChorusParameter(data: any): void;
|
|
247
|
+
setChorusType(type: any): void;
|
|
248
|
+
setChorusModRate(value: any): void;
|
|
249
|
+
setChorusModDepth(value: any): void;
|
|
250
|
+
setChorusFeedback(value: any): void;
|
|
251
|
+
setChorusSendToReverb(value: any): void;
|
|
240
252
|
handleExclusiveMessage(data: any): void;
|
|
241
253
|
handleSysEx(data: any): void;
|
|
242
254
|
scheduleTask(callback: any, startTime: any): Promise<any>;
|