@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 CHANGED
@@ -48,8 +48,6 @@ export class MidyGM1 {
48
48
  gainL: any;
49
49
  gainR: any;
50
50
  merger: any;
51
- reverbEffect: any;
52
- chorusEffect: any;
53
51
  };
54
52
  createChannels(audioContext: any): any[];
55
53
  createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
@@ -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;;;;;;MAkBC;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;AAvjCD;IAOE,gFAKC;IAXD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
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
- reverb: number;
8
- chorus: number;
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
- createConvolutionReverb(audioContext: any, options?: {}): {
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
- createSchroederReverb(audioContext: any, options?: {}): {
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, reverb: any): void;
195
- setChorusSendLevel(channelNumber: any, chorus: any): void;
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>;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAuBA;IAwBE;;;;;;;;;;;;;;;;;MAiBE;IAEF;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IASF;;;;;;;OAOC;IA9ED,qBAAmB;IACnB,kBAAc;IACd,qBAAmB;IACnB,yBAAqB;IACrB,2BAAuB;IACvB,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;;;;;;;MAKE;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;;;;;;MA4CC;IAED,gFAUC;IAED,mFAYC;IAID;;;;;MAuCC;IAED;;;;;;MAoCC;IAED,kDAuBC;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;IAED,oDAEC;IAED,0DASC;IAED,0DAIC;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,yDAgDC;IAED,yCAGC;IAED,mCAQC;IAED,6CAGC;IAED,2CAMC;IAED,+CAGC;IAED,+CAMC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AA7hDD;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"}
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
- // return this.createConvolutionReverb(audioContext);
194
- return this.createSchroederReverb(audioContext);
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
- createConvolutionReverb(audioContext, options = {}) {
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
- input.connect(convolverNode);
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, options = {}) {
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(wetGain);
678
- input.connect(dryGain);
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
- if (channel.reverb === 0) {
717
- if (channel.chorus === 0) { // no effect
718
- channel.merger.connect(this.masterGain);
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.chorus === 0) { // reverb
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, reverb) {
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.reverb = reverb / 127 * this.reverbFactor;
1147
- reverbEffect.dryGain.gain.cancelScheduledValues(now);
1148
- reverbEffect.dryGain.gain.setValueAtTime(1 - channel.reverb, now);
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, chorus) {
1172
+ setChorusSendLevel(channelNumber, chorusSendLevel) {
1153
1173
  const channel = this.channels[channelNumber];
1154
- channel.chorus = chorus / 127;
1155
- channel.chorusEffect.lfoGain = channel.chorus;
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
- // case 5: // TODO: Global Parameter Control
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
- reverb: 0,
1498
- chorus: 0,
1634
+ reverbSendLevel: 0,
1635
+ chorusSendLevel: 0,
1499
1636
  bank: 121 * 128,
1500
1637
  bankMSB: 121,
1501
1638
  bankLSB: 0,
@@ -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]) {