@marmooo/midy 0.1.0 → 0.1.1

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.
@@ -85,7 +85,7 @@ class MidyGM2 {
85
85
  writable: true,
86
86
  value: {
87
87
  time: this.getReverbTime(64),
88
- feedback: 0.2,
88
+ feedback: 0.25,
89
89
  }
90
90
  });
91
91
  Object.defineProperty(this, "chorus", {
@@ -93,10 +93,11 @@ class MidyGM2 {
93
93
  configurable: true,
94
94
  writable: true,
95
95
  value: {
96
- modRate: 3 * 0.122,
97
- modDepth: (3 + 1) / 3.2,
98
- feedback: 8 * 0.763,
99
- sendToReverb: 0 * 0.787,
96
+ modRate: this.getChorusModRate(3),
97
+ modDepth: this.getChorusModDepth(19),
98
+ feedback: this.getChorusFeedback(8),
99
+ sendToReverb: this.getChorusSendToReverb(0),
100
+ delayTimes: this.generateDistributedArray(0.02, 2, 0.5),
100
101
  }
101
102
  });
102
103
  Object.defineProperty(this, "mono", {
@@ -691,9 +692,7 @@ class MidyGM2 {
691
692
  createSchroederReverb(audioContext, combDelays, combFeedbacks, allpassDelays, allpassFeedbacks) {
692
693
  const input = new GainNode(audioContext);
693
694
  const output = new GainNode(audioContext);
694
- const mergerGain = new GainNode(audioContext, {
695
- gain: 1 / (combDelays.length * 2),
696
- });
695
+ const mergerGain = new GainNode(audioContext);
697
696
  for (let i = 0; i < combDelays.length; i++) {
698
697
  const comb = this.createCombFilter(audioContext, input, combDelays[i], combFeedbacks[i]);
699
698
  comb.connect(mergerGain);
@@ -706,60 +705,62 @@ class MidyGM2 {
706
705
  allpasses.at(-1).connect(output);
707
706
  return { input, output };
708
707
  }
709
- createChorusEffect(audioContext, options = {}) {
710
- const { chorusCount = 2, chorusRate = 0.6, chorusDepth = 0.15, delay = 0.01, variance = delay * 0.1, } = options;
711
- const lfo = new OscillatorNode(audioContext, { frequency: chorusRate });
712
- const lfoGain = new GainNode(audioContext, { gain: chorusDepth });
708
+ createChorusEffect(audioContext) {
709
+ const input = new GainNode(audioContext);
713
710
  const output = new GainNode(audioContext);
714
- const chorusGains = [];
711
+ const sendGain = new GainNode(audioContext);
712
+ const lfo = new OscillatorNode(audioContext, {
713
+ frequency: this.chorus.modRate,
714
+ });
715
+ const lfoGain = new GainNode(audioContext, {
716
+ gain: this.chorus.modDepth / 2,
717
+ });
718
+ const delayTimes = this.chorus.delayTimes;
715
719
  const delayNodes = [];
716
- const baseGain = 1 / chorusCount;
717
- for (let i = 0; i < chorusCount; i++) {
718
- const randomDelayFactor = (Math.random() - 0.5) * variance;
719
- const delayTime = (i + 1) * delay + randomDelayFactor;
720
+ const feedbackGains = [];
721
+ for (let i = 0; i < delayTimes.length; i++) {
722
+ const delayTime = delayTimes[i];
720
723
  const delayNode = new DelayNode(audioContext, {
721
- maxDelayTime: delayTime,
724
+ maxDelayTime: 0.1, // generally, 5ms < delayTime < 50ms
725
+ delayTime,
726
+ });
727
+ const feedbackGain = new GainNode(audioContext, {
728
+ gain: this.chorus.feedback,
722
729
  });
723
- const chorusGain = new GainNode(audioContext, { gain: baseGain });
724
730
  delayNodes.push(delayNode);
725
- chorusGains.push(chorusGain);
731
+ feedbackGains.push(feedbackGain);
732
+ input.connect(delayNode);
726
733
  lfoGain.connect(delayNode.delayTime);
727
- delayNode.connect(chorusGain);
728
- chorusGain.connect(output);
734
+ delayNode.connect(feedbackGain);
735
+ feedbackGain.connect(delayNode);
736
+ delayNode.connect(output);
729
737
  }
738
+ output.connect(sendGain);
730
739
  lfo.connect(lfoGain);
731
740
  lfo.start();
732
741
  return {
742
+ input,
743
+ output,
744
+ sendGain,
733
745
  lfo,
734
746
  lfoGain,
735
747
  delayNodes,
736
- chorusGains,
737
- output,
748
+ feedbackGains,
738
749
  };
739
750
  }
740
751
  connectEffects(channel, gainNode) {
741
752
  gainNode.connect(channel.merger);
742
753
  channel.merger.connect(this.masterGain);
743
- if (channel.reverbSendLevel === 0) {
744
- if (channel.chorusSendLevel !== 0) { // chorus
745
- channel.chorusEffect.delayNodes.forEach((delayNode) => {
746
- channel.merger.connect(delayNode);
747
- });
748
- channel.chorusEffect.output.connect(this.masterGain);
749
- }
754
+ if (0 < channel.reverbSendLevel) {
755
+ channel.merger.connect(channel.reverbEffect.input);
756
+ channel.reverbEffect.output.connect(this.masterGain);
750
757
  }
751
- else {
752
- if (channel.chorusSendLevel === 0) { // reverb
753
- channel.merger.connect(channel.reverbEffect.input);
754
- channel.reverbEffect.output.connect(this.masterGain);
755
- }
756
- else { // reverb + chorus
757
- channel.chorusEffect.delayNodes.forEach((delayNode) => {
758
- channel.merger.connect(delayNode);
759
- });
760
- channel.merger.connect(channel.reverbEffect.input);
761
- channel.reverbEffect.output.connect(this.masterGain);
762
- }
758
+ if (0 < channel.chorusSendLevel) {
759
+ channel.merger.connect(channel.chorusEffect.input);
760
+ channel.reverbEffect.output.connect(this.masterGain);
761
+ }
762
+ if (0 < this.chorus.sendToReverb) {
763
+ channel.chorusEffect.sendGain.connect(channel.reverbEffect.input);
763
764
  }
764
765
  }
765
766
  cbToRatio(cb) {
@@ -1173,9 +1174,12 @@ class MidyGM2 {
1173
1174
  reverbEffect.output.gain.setValueAtTime(channel.reverbSendLevel, now);
1174
1175
  }
1175
1176
  setChorusSendLevel(channelNumber, chorusSendLevel) {
1177
+ const now = this.audioContext.currentTime;
1176
1178
  const channel = this.channels[channelNumber];
1179
+ const chorusEffect = channel.chorusEffect;
1177
1180
  channel.chorusSendLevel = chorusSendLevel / 127;
1178
- channel.chorusEffect.lfoGain = channel.chorusSendLevel;
1181
+ chorusEffect.output.gain.cancelScheduledValues(now);
1182
+ chorusEffect.output.gain.setValueAtTime(channel.chorusSendLevel, now);
1179
1183
  }
1180
1184
  setSostenutoPedal(channelNumber, value) {
1181
1185
  const isOn = value >= 64;
@@ -1407,7 +1411,7 @@ class MidyGM2 {
1407
1411
  case 4: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
1408
1412
  return this.handleMasterCoarseTuningSysEx(data);
1409
1413
  case 5:
1410
- return this.handleGlobalParameterControl(data);
1414
+ return this.handleGlobalParameterControlSysEx(data);
1411
1415
  default:
1412
1416
  console.warn(`Unsupported Exclusive Message: ${data}`);
1413
1417
  }
@@ -1484,13 +1488,13 @@ class MidyGM2 {
1484
1488
  this.masterCoarseTuning = coarseTuning - 64;
1485
1489
  }
1486
1490
  }
1487
- handleGlobalParameterControl(data) {
1488
- if (data[5] === 1) {
1489
- switch (data[6]) {
1491
+ handleGlobalParameterControlSysEx(data) {
1492
+ if (data[7] === 1) {
1493
+ switch (data[8]) {
1490
1494
  case 1:
1491
- return this.handleReverbParameter(data);
1495
+ return this.handleReverbParameterSysEx(data);
1492
1496
  case 2:
1493
- return this.handleChorusParameter(data);
1497
+ return this.handleChorusParameterSysEx(data);
1494
1498
  default:
1495
1499
  console.warn(`Unsupported Global Parameter Control Message: ${data}`);
1496
1500
  }
@@ -1499,12 +1503,12 @@ class MidyGM2 {
1499
1503
  console.warn(`Unsupported Global Parameter Control Message: ${data}`);
1500
1504
  }
1501
1505
  }
1502
- handleReverbParameter(data) {
1503
- switch (data[7]) {
1506
+ handleReverbParameterSysEx(data) {
1507
+ switch (data[9]) {
1504
1508
  case 0:
1505
- return this.setReverbType(data[8]);
1509
+ return this.setReverbType(data[10]);
1506
1510
  case 1:
1507
- return this.setReverbTime(data[8]);
1511
+ return this.setReverbTime(data[10]);
1508
1512
  }
1509
1513
  }
1510
1514
  setReverbType(type) {
@@ -1564,41 +1568,109 @@ class MidyGM2 {
1564
1568
  // RT60 = -3 * delay / Math.log10(feedback)
1565
1569
  // feedback = Math.pow(10, -3 * delay / RT60)
1566
1570
  // 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.
1571
+ // The structure of a concert hall is complex,
1572
+ // so estimates based on mean free path are unstable.
1573
+ // It is easier to determine the delay based on ideal feedback.
1574
+ // The average sound absorption coefficient
1575
+ // suitable for playing musical instruments is 0.18 to 0.28.
1570
1576
  // delay = -RT60 * Math.log10(feedback) / 3
1571
1577
  calcDelay(rt60, feedback) {
1572
1578
  return -rt60 * Math.log10(feedback) / 3;
1573
1579
  }
1574
- handleChorusParameter(data) {
1575
- switch (data[7]) {
1580
+ handleChorusParameterSysEx(data) {
1581
+ switch (data[9]) {
1576
1582
  case 0:
1577
- return this.setChorusType(data[8]);
1583
+ return this.setChorusType(data[10]);
1578
1584
  case 1:
1579
- return this.setChorusModRate(data[8]);
1585
+ return this.setChorusModRate(data[10]);
1580
1586
  case 2:
1581
- return this.setChorusModDepth(data[8]);
1587
+ return this.setChorusModDepth(data[10]);
1582
1588
  case 3:
1583
- return this.setChorusFeedback(data[8]);
1589
+ return this.setChorusFeedback(data[10]);
1584
1590
  case 4:
1585
- return this.setChorusSendToReverb(data[8]);
1591
+ return this.setChorusSendToReverb(data[10]);
1586
1592
  }
1587
1593
  }
1588
1594
  setChorusType(type) {
1589
- // TODO
1595
+ switch (type) {
1596
+ case 0:
1597
+ return this.setChorusParameter(3, 5, 0, 0);
1598
+ case 1:
1599
+ return this.setChorusParameter(9, 19, 5, 0);
1600
+ case 2:
1601
+ return this.setChorusParameter(3, 19, 8, 0);
1602
+ case 3:
1603
+ return this.setChorusParameter(9, 16, 16, 0);
1604
+ case 4:
1605
+ return this.setChorusParameter(2, 24, 64, 0);
1606
+ case 5:
1607
+ return this.setChorusParameter(1, 5, 112, 0);
1608
+ default:
1609
+ console.warn(`Unsupported Chorus Type: ${type}`);
1610
+ }
1611
+ }
1612
+ setChorusParameter(modRate, modDepth, feedback, sendToReverb) {
1613
+ this.setChorusModRate(modRate);
1614
+ this.setChorusModDepth(modDepth);
1615
+ this.setChorusFeedback(feedback);
1616
+ this.setChorusSendToReverb(sendToReverb);
1590
1617
  }
1591
1618
  setChorusModRate(value) {
1592
- // TODO
1619
+ const now = this.audioContext.currentTime;
1620
+ const modRate = this.getChorusModRate(value);
1621
+ this.chorus.modRate = modRate;
1622
+ for (let i = 0; i < this.channels.length; i++) {
1623
+ const lfo = this.channels[i].chorusEffect.lfo;
1624
+ lfo.frequency.setValueAtTime(modRate, now);
1625
+ }
1626
+ }
1627
+ getChorusModRate(value) {
1628
+ return value * 0.122; // Hz
1593
1629
  }
1594
1630
  setChorusModDepth(value) {
1595
- // TODO
1631
+ const now = this.audioContext.currentTime;
1632
+ const modDepth = this.getChorusModDepth(value);
1633
+ this.chorus.modDepth = modDepth;
1634
+ for (let i = 0; i < this.channels.length; i++) {
1635
+ const chorusEffect = this.channels[i].chorusEffect;
1636
+ chorusEffect.lfoGain.gain
1637
+ .cancelScheduledValues(now)
1638
+ .setValueAtTime(modDepth / 2, now);
1639
+ }
1640
+ }
1641
+ getChorusModDepth(value) {
1642
+ return (value + 1) / 3200; // second
1596
1643
  }
1597
1644
  setChorusFeedback(value) {
1598
- // TODO
1645
+ const now = this.audioContext.currentTime;
1646
+ const feedback = this.getChorusFeedback(value);
1647
+ this.chorus.feedback = feedback;
1648
+ for (let i = 0; i < this.channels.length; i++) {
1649
+ const chorusEffect = this.channels[i].chorusEffect;
1650
+ for (let j = 0; j < chorusEffect.feedbackGains.length; j++) {
1651
+ const feedbackGain = chorusEffect.feedbackGains[j];
1652
+ feedbackGain.gain
1653
+ .cancelScheduledValues(now)
1654
+ .setValueAtTime(feedback, now);
1655
+ }
1656
+ }
1657
+ }
1658
+ getChorusFeedback(value) {
1659
+ return value * 0.00763;
1599
1660
  }
1600
1661
  setChorusSendToReverb(value) {
1601
- // TODO
1662
+ const now = this.audioContext.currentTime;
1663
+ const sendToReverb = this.getChorusSendToReverb(value);
1664
+ this.chorus.sendToReverb = sendToReverb;
1665
+ for (let i = 0; i < this.channels.length; i++) {
1666
+ const chorusEffect = this.channels[i].chorusEffect;
1667
+ chorusEffect.sendGain.gain
1668
+ .cancelScheduledValues(now)
1669
+ .setValueAtTime(sendToReverb, now);
1670
+ }
1671
+ }
1672
+ getChorusSendToReverb(value) {
1673
+ return value * 0.00787;
1602
1674
  }
1603
1675
  handleExclusiveMessage(data) {
1604
1676
  console.warn(`Unsupported Exclusive Message: ${data}`);
package/script/midy.d.ts CHANGED
@@ -59,6 +59,7 @@ export class Midy {
59
59
  modDepth: number;
60
60
  feedback: number;
61
61
  sendToReverb: number;
62
+ delayTimes: any[];
62
63
  };
63
64
  mono: boolean;
64
65
  omni: boolean;
@@ -105,11 +106,13 @@ export class Midy {
105
106
  output: any;
106
107
  };
107
108
  chorusEffect: {
109
+ input: any;
110
+ output: any;
111
+ sendGain: any;
108
112
  lfo: any;
109
113
  lfoGain: any;
110
114
  delayNodes: any[];
111
- chorusGains: any[];
112
- output: any;
115
+ feedbackGains: any[];
113
116
  };
114
117
  };
115
118
  createChannels(audioContext: any): any[];
@@ -148,12 +151,14 @@ export class Midy {
148
151
  input: any;
149
152
  output: any;
150
153
  };
151
- createChorusEffect(audioContext: any, options?: {}): {
154
+ createChorusEffect(audioContext: any): {
155
+ input: any;
156
+ output: any;
157
+ sendGain: any;
152
158
  lfo: any;
153
159
  lfoGain: any;
154
160
  delayNodes: any[];
155
- chorusGains: any[];
156
- output: any;
161
+ feedbackGains: any[];
157
162
  };
158
163
  connectEffects(channel: any, gainNode: any): void;
159
164
  cbToRatio(cb: any): number;
@@ -236,19 +241,24 @@ export class Midy {
236
241
  setMasterFineTuning(fineTuning: any): void;
237
242
  handleMasterCoarseTuningSysEx(data: any): void;
238
243
  setMasterCoarseTuning(coarseTuning: any): void;
239
- handleGlobalParameterControl(data: any): void;
240
- handleReverbParameter(data: any): void;
244
+ handleGlobalParameterControlSysEx(data: any): void;
245
+ handleReverbParameterSysEx(data: any): void;
241
246
  setReverbType(type: any): void;
242
247
  getReverbTimeFromType(type: any): number | undefined;
243
248
  setReverbTime(value: any): void;
244
249
  getReverbTime(value: any): number;
245
250
  calcDelay(rt60: any, feedback: any): number;
246
- handleChorusParameter(data: any): void;
251
+ handleChorusParameterSysEx(data: any): void;
247
252
  setChorusType(type: any): void;
253
+ setChorusParameter(modRate: any, modDepth: any, feedback: any, sendToReverb: any): void;
248
254
  setChorusModRate(value: any): void;
255
+ getChorusModRate(value: any): number;
249
256
  setChorusModDepth(value: any): void;
257
+ getChorusModDepth(value: any): number;
250
258
  setChorusFeedback(value: any): void;
259
+ getChorusFeedback(value: any): number;
251
260
  setChorusSendToReverb(value: any): void;
261
+ getChorusSendToReverb(value: any): number;
252
262
  handleExclusiveMessage(data: any): void;
253
263
  handleSysEx(data: any): void;
254
264
  scheduleTask(callback: any, startTime: any): Promise<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}