@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/esm/midy-GM1.d.ts
CHANGED
package/esm/midy-GM1.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAqBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA9CD,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAyBhB,kBAAgC;IAChC,gBAA4C;IAE5C,gBAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED
|
|
1
|
+
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAqBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA9CD,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAyBhB,kBAAgC;IAChC,gBAA4C;IAE5C,gBAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAcC;IAED,yCAUC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EA+CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA8DC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,kDAGC;IAED,2BAEC;IAED,4BAEC;IAED,sCAGC;IAED,mFAGC;IAED,iDAiBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHA6BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIA8CC;IAED,0FAGC;IAED,kEAeC;IAED,wFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,uDAOC;IAED,mFA+BC;IAED,qCAcC;IAED,yDAIC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,sCAUC;IAED,sDAMC;IAED,kFAeC;IAED,2DAMC;IAED,oCAkBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAUC;IAED,kDAKC;IAED,iEAOC;IAED,8CAKC;IAED,yDAMC;IAED,gDAKC;IAED,6DAMC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAnjCD;IAOE,gFAKC;IAXD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|
package/esm/midy-GM1.js
CHANGED
|
@@ -189,14 +189,10 @@ export class MidyGM1 {
|
|
|
189
189
|
const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
|
|
190
190
|
gainL.connect(merger, 0, 0);
|
|
191
191
|
gainR.connect(merger, 0, 1);
|
|
192
|
-
const reverbEffect = this.createConvolutionReverb(audioContext);
|
|
193
|
-
const chorusEffect = this.createChorusEffect(audioContext);
|
|
194
192
|
return {
|
|
195
193
|
gainL,
|
|
196
194
|
gainR,
|
|
197
195
|
merger,
|
|
198
|
-
reverbEffect,
|
|
199
|
-
chorusEffect,
|
|
200
196
|
};
|
|
201
197
|
}
|
|
202
198
|
createChannels(audioContext) {
|
|
@@ -956,11 +952,11 @@ export class MidyGM1 {
|
|
|
956
952
|
case 2: // GM System Off
|
|
957
953
|
break;
|
|
958
954
|
default:
|
|
959
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
955
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
960
956
|
}
|
|
961
957
|
break;
|
|
962
958
|
default:
|
|
963
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
959
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
964
960
|
}
|
|
965
961
|
}
|
|
966
962
|
GM1SystemOn() {
|
|
@@ -979,11 +975,11 @@ export class MidyGM1 {
|
|
|
979
975
|
case 1:
|
|
980
976
|
return this.handleMasterVolumeSysEx(data);
|
|
981
977
|
default:
|
|
982
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
978
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
983
979
|
}
|
|
984
980
|
break;
|
|
985
981
|
default:
|
|
986
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
982
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
987
983
|
}
|
|
988
984
|
}
|
|
989
985
|
handleMasterVolumeSysEx(data) {
|
|
@@ -1001,7 +997,7 @@ export class MidyGM1 {
|
|
|
1001
997
|
}
|
|
1002
998
|
}
|
|
1003
999
|
handleExclusiveMessage(data) {
|
|
1004
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1000
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1005
1001
|
}
|
|
1006
1002
|
handleSysEx(data) {
|
|
1007
1003
|
switch (data[0]) {
|
package/esm/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/esm/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/esm/midy-GM2.js
CHANGED
|
@@ -64,12 +64,6 @@ export class MidyGM2 {
|
|
|
64
64
|
writable: true,
|
|
65
65
|
value: 0
|
|
66
66
|
});
|
|
67
|
-
Object.defineProperty(this, "reverbFactor", {
|
|
68
|
-
enumerable: true,
|
|
69
|
-
configurable: true,
|
|
70
|
-
writable: true,
|
|
71
|
-
value: 0.1
|
|
72
|
-
});
|
|
73
67
|
Object.defineProperty(this, "masterFineTuning", {
|
|
74
68
|
enumerable: true,
|
|
75
69
|
configurable: true,
|
|
@@ -82,6 +76,26 @@ export class MidyGM2 {
|
|
|
82
76
|
writable: true,
|
|
83
77
|
value: 0
|
|
84
78
|
}); // cb
|
|
79
|
+
Object.defineProperty(this, "reverb", {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
configurable: true,
|
|
82
|
+
writable: true,
|
|
83
|
+
value: {
|
|
84
|
+
time: this.getReverbTime(64),
|
|
85
|
+
feedback: 0.2,
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
Object.defineProperty(this, "chorus", {
|
|
89
|
+
enumerable: true,
|
|
90
|
+
configurable: true,
|
|
91
|
+
writable: true,
|
|
92
|
+
value: {
|
|
93
|
+
modRate: 3 * 0.122,
|
|
94
|
+
modDepth: (3 + 1) / 3.2,
|
|
95
|
+
feedback: 8 * 0.763,
|
|
96
|
+
sendToReverb: 0 * 0.787,
|
|
97
|
+
}
|
|
98
|
+
});
|
|
85
99
|
Object.defineProperty(this, "mono", {
|
|
86
100
|
enumerable: true,
|
|
87
101
|
configurable: true,
|
|
@@ -190,8 +204,19 @@ export class MidyGM2 {
|
|
|
190
204
|
writable: true,
|
|
191
205
|
value: {
|
|
192
206
|
reverbAlgorithm: (audioContext) => {
|
|
193
|
-
|
|
194
|
-
|
|
207
|
+
const { time: rt60, feedback } = this.reverb;
|
|
208
|
+
// const delay = this.calcDelay(rt60, feedback);
|
|
209
|
+
// const impulse = this.createConvolutionReverbImpulse(
|
|
210
|
+
// audioContext,
|
|
211
|
+
// rt60,
|
|
212
|
+
// delay,
|
|
213
|
+
// );
|
|
214
|
+
// return this.createConvolutionReverb(audioContext, impulse);
|
|
215
|
+
const combFeedbacks = this.generateDistributedArray(feedback, 4);
|
|
216
|
+
const combDelays = combFeedbacks.map((feedback) => this.calcDelay(rt60, feedback));
|
|
217
|
+
const allpassFeedbacks = this.generateDistributedArray(feedback, 4);
|
|
218
|
+
const allpassDelays = allpassFeedbacks.map((feedback) => this.calcDelay(rt60, feedback));
|
|
219
|
+
return this.createSchroederReverb(audioContext, combFeedbacks, combDelays, allpassFeedbacks, allpassDelays);
|
|
195
220
|
},
|
|
196
221
|
}
|
|
197
222
|
});
|
|
@@ -590,12 +615,7 @@ export class MidyGM2 {
|
|
|
590
615
|
}
|
|
591
616
|
return noteList[0];
|
|
592
617
|
}
|
|
593
|
-
|
|
594
|
-
const { decay = 0.8, preDecay = 0, } = options;
|
|
595
|
-
const input = new GainNode(audioContext);
|
|
596
|
-
const output = new GainNode(audioContext);
|
|
597
|
-
const dryGain = new GainNode(audioContext);
|
|
598
|
-
const wetGain = new GainNode(audioContext);
|
|
618
|
+
createConvolutionReverbImpulse(audioContext, decay, preDecay) {
|
|
599
619
|
const sampleRate = audioContext.sampleRate;
|
|
600
620
|
const length = sampleRate * decay;
|
|
601
621
|
const impulse = new AudioBuffer({
|
|
@@ -615,18 +635,17 @@ export class MidyGM2 {
|
|
|
615
635
|
channelData[i] = (Math.random() * 2 - 1) * attenuation;
|
|
616
636
|
}
|
|
617
637
|
}
|
|
638
|
+
return impulse;
|
|
639
|
+
}
|
|
640
|
+
createConvolutionReverb(audioContext, impulse) {
|
|
641
|
+
const output = new GainNode(audioContext);
|
|
618
642
|
const convolverNode = new ConvolverNode(audioContext, {
|
|
619
643
|
buffer: impulse,
|
|
620
644
|
});
|
|
621
|
-
|
|
622
|
-
convolverNode.connect(wetGain);
|
|
623
|
-
wetGain.connect(output);
|
|
624
|
-
dryGain.connect(output);
|
|
645
|
+
convolverNode.connect(output);
|
|
625
646
|
return {
|
|
626
|
-
input,
|
|
647
|
+
input: convolverNode,
|
|
627
648
|
output,
|
|
628
|
-
dryGain,
|
|
629
|
-
wetGain,
|
|
630
649
|
convolverNode,
|
|
631
650
|
};
|
|
632
651
|
}
|
|
@@ -654,17 +673,24 @@ export class MidyGM2 {
|
|
|
654
673
|
delayNode.connect(passGain);
|
|
655
674
|
return passGain;
|
|
656
675
|
}
|
|
676
|
+
generateDistributedArray(center, count, varianceRatio = 0.1, randomness = 0.05) {
|
|
677
|
+
const variance = center * varianceRatio;
|
|
678
|
+
const array = new Array(count);
|
|
679
|
+
for (let i = 0; i < count; i++) {
|
|
680
|
+
const fraction = i / (count - 1 || 1);
|
|
681
|
+
const value = center - variance + fraction * 2 * variance;
|
|
682
|
+
array[i] = value * (1 - (Math.random() * 2 - 1) * randomness);
|
|
683
|
+
}
|
|
684
|
+
return array;
|
|
685
|
+
}
|
|
657
686
|
// https://hajim.rochester.edu/ece/sites/zduan/teaching/ece472/reading/Schroeder_1962.pdf
|
|
658
687
|
// M.R.Schroeder, "Natural Sounding Artificial Reverberation", J.Audio Eng. Soc., vol.10, p.219, 1962
|
|
659
|
-
createSchroederReverb(audioContext,
|
|
660
|
-
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;
|
|
688
|
+
createSchroederReverb(audioContext, combDelays, combFeedbacks, allpassDelays, allpassFeedbacks) {
|
|
661
689
|
const input = new GainNode(audioContext);
|
|
662
690
|
const output = new GainNode(audioContext);
|
|
663
691
|
const mergerGain = new GainNode(audioContext, {
|
|
664
692
|
gain: 1 / (combDelays.length * 2),
|
|
665
693
|
});
|
|
666
|
-
const dryGain = new GainNode(audioContext, { gain: 1 - mix });
|
|
667
|
-
const wetGain = new GainNode(audioContext, { gain: mix });
|
|
668
694
|
for (let i = 0; i < combDelays.length; i++) {
|
|
669
695
|
const comb = this.createCombFilter(audioContext, input, combDelays[i], combFeedbacks[i]);
|
|
670
696
|
comb.connect(mergerGain);
|
|
@@ -674,11 +700,8 @@ export class MidyGM2 {
|
|
|
674
700
|
const allpass = this.createAllpassFilter(audioContext, (i === 0) ? mergerGain : allpasses.at(-1), allpassDelays[i], allpassFeedbacks[i]);
|
|
675
701
|
allpasses.push(allpass);
|
|
676
702
|
}
|
|
677
|
-
allpasses.at(-1).connect(
|
|
678
|
-
input
|
|
679
|
-
dryGain.connect(output);
|
|
680
|
-
wetGain.connect(output);
|
|
681
|
-
return { input, output, dryGain, wetGain };
|
|
703
|
+
allpasses.at(-1).connect(output);
|
|
704
|
+
return { input, output };
|
|
682
705
|
}
|
|
683
706
|
createChorusEffect(audioContext, options = {}) {
|
|
684
707
|
const { chorusCount = 2, chorusRate = 0.6, chorusDepth = 0.15, delay = 0.01, variance = delay * 0.1, } = options;
|
|
@@ -713,11 +736,9 @@ export class MidyGM2 {
|
|
|
713
736
|
}
|
|
714
737
|
connectEffects(channel, gainNode) {
|
|
715
738
|
gainNode.connect(channel.merger);
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
}
|
|
720
|
-
else { // chorus
|
|
739
|
+
channel.merger.connect(this.masterGain);
|
|
740
|
+
if (channel.reverbSendLevel === 0) {
|
|
741
|
+
if (channel.chorusSendLevel !== 0) { // chorus
|
|
721
742
|
channel.chorusEffect.delayNodes.forEach((delayNode) => {
|
|
722
743
|
channel.merger.connect(delayNode);
|
|
723
744
|
});
|
|
@@ -725,7 +746,7 @@ export class MidyGM2 {
|
|
|
725
746
|
}
|
|
726
747
|
}
|
|
727
748
|
else {
|
|
728
|
-
if (channel.
|
|
749
|
+
if (channel.chorusSendLevel === 0) { // reverb
|
|
729
750
|
channel.merger.connect(channel.reverbEffect.input);
|
|
730
751
|
channel.reverbEffect.output.connect(this.masterGain);
|
|
731
752
|
}
|
|
@@ -1136,23 +1157,22 @@ export class MidyGM2 {
|
|
|
1136
1157
|
this.releaseSustainPedal(channelNumber, value);
|
|
1137
1158
|
}
|
|
1138
1159
|
}
|
|
1160
|
+
// TODO
|
|
1139
1161
|
setPortamento(channelNumber, value) {
|
|
1140
1162
|
this.channels[channelNumber].portamento = value >= 64;
|
|
1141
1163
|
}
|
|
1142
|
-
setReverbSendLevel(channelNumber,
|
|
1164
|
+
setReverbSendLevel(channelNumber, reverbSendLevel) {
|
|
1143
1165
|
const now = this.audioContext.currentTime;
|
|
1144
1166
|
const channel = this.channels[channelNumber];
|
|
1145
1167
|
const reverbEffect = channel.reverbEffect;
|
|
1146
|
-
channel.
|
|
1147
|
-
reverbEffect.
|
|
1148
|
-
reverbEffect.
|
|
1149
|
-
reverbEffect.wetGain.gain.cancelScheduledValues(now);
|
|
1150
|
-
reverbEffect.wetGain.gain.setValueAtTime(channel.reverb, now);
|
|
1168
|
+
channel.reverbSendLevel = reverbSendLevel / 127;
|
|
1169
|
+
reverbEffect.output.gain.cancelScheduledValues(now);
|
|
1170
|
+
reverbEffect.output.gain.setValueAtTime(channel.reverbSendLevel, now);
|
|
1151
1171
|
}
|
|
1152
|
-
setChorusSendLevel(channelNumber,
|
|
1172
|
+
setChorusSendLevel(channelNumber, chorusSendLevel) {
|
|
1153
1173
|
const channel = this.channels[channelNumber];
|
|
1154
|
-
channel.
|
|
1155
|
-
channel.chorusEffect.lfoGain = channel.
|
|
1174
|
+
channel.chorusSendLevel = chorusSendLevel / 127;
|
|
1175
|
+
channel.chorusEffect.lfoGain = channel.chorusSendLevel;
|
|
1156
1176
|
}
|
|
1157
1177
|
setSostenutoPedal(channelNumber, value) {
|
|
1158
1178
|
const isOn = value >= 64;
|
|
@@ -1348,11 +1368,11 @@ export class MidyGM2 {
|
|
|
1348
1368
|
this.GM2SystemOn();
|
|
1349
1369
|
break;
|
|
1350
1370
|
default:
|
|
1351
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1371
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1352
1372
|
}
|
|
1353
1373
|
break;
|
|
1354
1374
|
default:
|
|
1355
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1375
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1356
1376
|
}
|
|
1357
1377
|
}
|
|
1358
1378
|
GM1SystemOn() {
|
|
@@ -1383,9 +1403,10 @@ export class MidyGM2 {
|
|
|
1383
1403
|
return this.handleMasterFineTuningSysEx(data);
|
|
1384
1404
|
case 4: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
|
|
1385
1405
|
return this.handleMasterCoarseTuningSysEx(data);
|
|
1386
|
-
|
|
1406
|
+
case 5:
|
|
1407
|
+
return this.handleGlobalParameterControl(data);
|
|
1387
1408
|
default:
|
|
1388
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1409
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1389
1410
|
}
|
|
1390
1411
|
break;
|
|
1391
1412
|
case 8:
|
|
@@ -1394,7 +1415,7 @@ export class MidyGM2 {
|
|
|
1394
1415
|
// // TODO
|
|
1395
1416
|
// return this.handleScaleOctaveTuning1ByteFormat();
|
|
1396
1417
|
default:
|
|
1397
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1418
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1398
1419
|
}
|
|
1399
1420
|
break;
|
|
1400
1421
|
case 9:
|
|
@@ -1406,7 +1427,7 @@ export class MidyGM2 {
|
|
|
1406
1427
|
// // TODO
|
|
1407
1428
|
// return this.setControlChange();
|
|
1408
1429
|
default:
|
|
1409
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1430
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1410
1431
|
}
|
|
1411
1432
|
break;
|
|
1412
1433
|
case 10:
|
|
@@ -1415,11 +1436,11 @@ export class MidyGM2 {
|
|
|
1415
1436
|
// // TODO
|
|
1416
1437
|
// return this.handleKeyBasedInstrumentControl();
|
|
1417
1438
|
default:
|
|
1418
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1439
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1419
1440
|
}
|
|
1420
1441
|
break;
|
|
1421
1442
|
default:
|
|
1422
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1443
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1423
1444
|
}
|
|
1424
1445
|
}
|
|
1425
1446
|
handleMasterVolumeSysEx(data) {
|
|
@@ -1460,8 +1481,124 @@ export class MidyGM2 {
|
|
|
1460
1481
|
this.masterCoarseTuning = coarseTuning - 64;
|
|
1461
1482
|
}
|
|
1462
1483
|
}
|
|
1484
|
+
handleGlobalParameterControl(data) {
|
|
1485
|
+
if (data[5] === 1) {
|
|
1486
|
+
switch (data[6]) {
|
|
1487
|
+
case 1:
|
|
1488
|
+
return this.handleReverbParameter(data);
|
|
1489
|
+
case 2:
|
|
1490
|
+
return this.handleChorusParameter(data);
|
|
1491
|
+
default:
|
|
1492
|
+
console.warn(`Unsupported Global Parameter Control Message: ${data}`);
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
else {
|
|
1496
|
+
console.warn(`Unsupported Global Parameter Control Message: ${data}`);
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
handleReverbParameter(data) {
|
|
1500
|
+
switch (data[7]) {
|
|
1501
|
+
case 0:
|
|
1502
|
+
return this.setReverbType(data[8]);
|
|
1503
|
+
case 1:
|
|
1504
|
+
return this.setReverbTime(data[8]);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
setReverbType(type) {
|
|
1508
|
+
this.reverb.time = this.getReverbTimeFromType(type);
|
|
1509
|
+
this.reverb.feedback = (type === 8) ? 0.1 : 0.2;
|
|
1510
|
+
const { audioContext, channels, options } = this;
|
|
1511
|
+
for (let i = 0; i < channels.length; i++) {
|
|
1512
|
+
channels[i].reverbEffect = options.reverbAlgorithm(audioContext);
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
getReverbTimeFromType(type) {
|
|
1516
|
+
switch (type) {
|
|
1517
|
+
case 0:
|
|
1518
|
+
return this.getReverbTime(44);
|
|
1519
|
+
case 1:
|
|
1520
|
+
return this.getReverbTime(50);
|
|
1521
|
+
case 2:
|
|
1522
|
+
return this.getReverbTime(56);
|
|
1523
|
+
case 3:
|
|
1524
|
+
return this.getReverbTime(64);
|
|
1525
|
+
case 4:
|
|
1526
|
+
return this.getReverbTime(64);
|
|
1527
|
+
case 8:
|
|
1528
|
+
return this.getReverbTime(50);
|
|
1529
|
+
default:
|
|
1530
|
+
console.warn(`Unsupported Reverb Time: ${type}`);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
setReverbTime(value) {
|
|
1534
|
+
this.reverb.time = this.getReverbTime(value);
|
|
1535
|
+
const { audioContext, channels, options } = this;
|
|
1536
|
+
for (let i = 0; i < channels.length; i++) {
|
|
1537
|
+
channels[i].reverbEffect = options.reverbAlgorithm(audioContext);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
getReverbTime(value) {
|
|
1541
|
+
return Math.pow(Math.E, (value - 40) * 0.025);
|
|
1542
|
+
}
|
|
1543
|
+
// mean free path equation
|
|
1544
|
+
// https://repository.dl.itc.u-tokyo.ac.jp/record/8550/files/A31912.pdf
|
|
1545
|
+
// 江田和司, 拡散性制御に基づく室内音響設計に向けた音場解析に関する研究, 2015
|
|
1546
|
+
// V: room size (m^3)
|
|
1547
|
+
// S: room surface area (m^2)
|
|
1548
|
+
// meanFreePath = 4V / S (m)
|
|
1549
|
+
// delay estimation using mean free path
|
|
1550
|
+
// t: degree Celsius, generally used 20
|
|
1551
|
+
// c: speed of sound = 331.5 + 0.61t = 331.5 * 0.61 * 20 = 343.7 (m/s)
|
|
1552
|
+
// delay = meanFreePath / c (s)
|
|
1553
|
+
// feedback equation
|
|
1554
|
+
// RT60 means that the energy is reduced to Math.pow(10, -6).
|
|
1555
|
+
// Since energy is proportional to the square of the amplitude,
|
|
1556
|
+
// the amplitude is reduced to Math.pow(10, -3).
|
|
1557
|
+
// When this is done through n feedbacks,
|
|
1558
|
+
// Math.pow(feedback, n) = Math.pow(10, -3)
|
|
1559
|
+
// Math.pow(feedback, RT60 / delay) = Math.pow(10, -3)
|
|
1560
|
+
// RT60 / delay * Math.log10(feedback) = -3
|
|
1561
|
+
// RT60 = -3 * delay / Math.log10(feedback)
|
|
1562
|
+
// feedback = Math.pow(10, -3 * delay / RT60)
|
|
1563
|
+
// delay estimation using ideal feedback
|
|
1564
|
+
// A suitable average sound absorption coefficient is 0.18-0.28.
|
|
1565
|
+
// Since the structure of the hall is complex,
|
|
1566
|
+
// It would be easier to determine the delay based on the ideal feedback.
|
|
1567
|
+
// delay = -RT60 * Math.log10(feedback) / 3
|
|
1568
|
+
calcDelay(rt60, feedback) {
|
|
1569
|
+
return -rt60 * Math.log10(feedback) / 3;
|
|
1570
|
+
}
|
|
1571
|
+
handleChorusParameter(data) {
|
|
1572
|
+
switch (data[7]) {
|
|
1573
|
+
case 0:
|
|
1574
|
+
return this.setChorusType(data[8]);
|
|
1575
|
+
case 1:
|
|
1576
|
+
return this.setChorusModRate(data[8]);
|
|
1577
|
+
case 2:
|
|
1578
|
+
return this.setChorusModDepth(data[8]);
|
|
1579
|
+
case 3:
|
|
1580
|
+
return this.setChorusFeedback(data[8]);
|
|
1581
|
+
case 4:
|
|
1582
|
+
return this.setChorusSendToReverb(data[8]);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
setChorusType(type) {
|
|
1586
|
+
// TODO
|
|
1587
|
+
}
|
|
1588
|
+
setChorusModRate(value) {
|
|
1589
|
+
// TODO
|
|
1590
|
+
}
|
|
1591
|
+
setChorusModDepth(value) {
|
|
1592
|
+
// TODO
|
|
1593
|
+
}
|
|
1594
|
+
setChorusFeedback(value) {
|
|
1595
|
+
// TODO
|
|
1596
|
+
}
|
|
1597
|
+
setChorusSendToReverb(value) {
|
|
1598
|
+
// TODO
|
|
1599
|
+
}
|
|
1463
1600
|
handleExclusiveMessage(data) {
|
|
1464
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
1601
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
1465
1602
|
}
|
|
1466
1603
|
handleSysEx(data) {
|
|
1467
1604
|
switch (data[0]) {
|
|
@@ -1494,8 +1631,8 @@ Object.defineProperty(MidyGM2, "channelSettings", {
|
|
|
1494
1631
|
volume: 100 / 127,
|
|
1495
1632
|
pan: 64,
|
|
1496
1633
|
portamentoTime: 0,
|
|
1497
|
-
|
|
1498
|
-
|
|
1634
|
+
reverbSendLevel: 0,
|
|
1635
|
+
chorusSendLevel: 0,
|
|
1499
1636
|
bank: 121 * 128,
|
|
1500
1637
|
bankMSB: 121,
|
|
1501
1638
|
bankLSB: 0,
|
package/esm/midy-GMLite.js
CHANGED
|
@@ -893,11 +893,11 @@ export class MidyGMLite {
|
|
|
893
893
|
case 2: // GM System Off
|
|
894
894
|
break;
|
|
895
895
|
default:
|
|
896
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
896
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
897
897
|
}
|
|
898
898
|
break;
|
|
899
899
|
default:
|
|
900
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
900
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
901
901
|
}
|
|
902
902
|
}
|
|
903
903
|
GM1SystemOn() {
|
|
@@ -916,11 +916,11 @@ export class MidyGMLite {
|
|
|
916
916
|
case 1:
|
|
917
917
|
return this.handleMasterVolumeSysEx(data);
|
|
918
918
|
default:
|
|
919
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
919
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
920
920
|
}
|
|
921
921
|
break;
|
|
922
922
|
default:
|
|
923
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
923
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
924
924
|
}
|
|
925
925
|
}
|
|
926
926
|
handleMasterVolumeSysEx(data) {
|
|
@@ -938,7 +938,7 @@ export class MidyGMLite {
|
|
|
938
938
|
}
|
|
939
939
|
}
|
|
940
940
|
handleExclusiveMessage(data) {
|
|
941
|
-
console.warn(`Unsupported Exclusive Message ${data}`);
|
|
941
|
+
console.warn(`Unsupported Exclusive Message: ${data}`);
|
|
942
942
|
}
|
|
943
943
|
handleSysEx(data) {
|
|
944
944
|
switch (data[0]) {
|