@marmooo/midy 0.0.9 → 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.
package/esm/midy.js CHANGED
@@ -64,12 +64,6 @@ export class Midy {
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,27 @@ export class Midy {
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.25,
86
+ }
87
+ });
88
+ Object.defineProperty(this, "chorus", {
89
+ enumerable: true,
90
+ configurable: true,
91
+ writable: true,
92
+ value: {
93
+ modRate: this.getChorusModRate(3),
94
+ modDepth: this.getChorusModDepth(19),
95
+ feedback: this.getChorusFeedback(8),
96
+ sendToReverb: this.getChorusSendToReverb(0),
97
+ delayTimes: this.generateDistributedArray(0.02, 2, 0.5),
98
+ }
99
+ });
85
100
  Object.defineProperty(this, "mono", {
86
101
  enumerable: true,
87
102
  configurable: true,
@@ -190,8 +205,19 @@ export class Midy {
190
205
  writable: true,
191
206
  value: {
192
207
  reverbAlgorithm: (audioContext) => {
193
- // return this.createConvolutionReverb(audioContext);
194
- return this.createSchroederReverb(audioContext);
208
+ const { time: rt60, feedback } = this.reverb;
209
+ // const delay = this.calcDelay(rt60, feedback);
210
+ // const impulse = this.createConvolutionReverbImpulse(
211
+ // audioContext,
212
+ // rt60,
213
+ // delay,
214
+ // );
215
+ // return this.createConvolutionReverb(audioContext, impulse);
216
+ const combFeedbacks = this.generateDistributedArray(feedback, 4);
217
+ const combDelays = combFeedbacks.map((feedback) => this.calcDelay(rt60, feedback));
218
+ const allpassFeedbacks = this.generateDistributedArray(feedback, 4);
219
+ const allpassDelays = allpassFeedbacks.map((feedback) => this.calcDelay(rt60, feedback));
220
+ return this.createSchroederReverb(audioContext, combFeedbacks, combDelays, allpassFeedbacks, allpassDelays);
195
221
  },
196
222
  }
197
223
  });
@@ -596,12 +622,7 @@ export class Midy {
596
622
  }
597
623
  return noteList[0];
598
624
  }
599
- createConvolutionReverb(audioContext, options = {}) {
600
- const { decay = 0.8, preDecay = 0, } = options;
601
- const input = new GainNode(audioContext);
602
- const output = new GainNode(audioContext);
603
- const dryGain = new GainNode(audioContext);
604
- const wetGain = new GainNode(audioContext);
625
+ createConvolutionReverbImpulse(audioContext, decay, preDecay) {
605
626
  const sampleRate = audioContext.sampleRate;
606
627
  const length = sampleRate * decay;
607
628
  const impulse = new AudioBuffer({
@@ -621,18 +642,17 @@ export class Midy {
621
642
  channelData[i] = (Math.random() * 2 - 1) * attenuation;
622
643
  }
623
644
  }
645
+ return impulse;
646
+ }
647
+ createConvolutionReverb(audioContext, impulse) {
648
+ const output = new GainNode(audioContext);
624
649
  const convolverNode = new ConvolverNode(audioContext, {
625
650
  buffer: impulse,
626
651
  });
627
- input.connect(convolverNode);
628
- convolverNode.connect(wetGain);
629
- wetGain.connect(output);
630
- dryGain.connect(output);
652
+ convolverNode.connect(output);
631
653
  return {
632
- input,
654
+ input: convolverNode,
633
655
  output,
634
- dryGain,
635
- wetGain,
636
656
  convolverNode,
637
657
  };
638
658
  }
@@ -660,17 +680,22 @@ export class Midy {
660
680
  delayNode.connect(passGain);
661
681
  return passGain;
662
682
  }
683
+ generateDistributedArray(center, count, varianceRatio = 0.1, randomness = 0.05) {
684
+ const variance = center * varianceRatio;
685
+ const array = new Array(count);
686
+ for (let i = 0; i < count; i++) {
687
+ const fraction = i / (count - 1 || 1);
688
+ const value = center - variance + fraction * 2 * variance;
689
+ array[i] = value * (1 - (Math.random() * 2 - 1) * randomness);
690
+ }
691
+ return array;
692
+ }
663
693
  // https://hajim.rochester.edu/ece/sites/zduan/teaching/ece472/reading/Schroeder_1962.pdf
664
694
  // M.R.Schroeder, "Natural Sounding Artificial Reverberation", J.Audio Eng. Soc., vol.10, p.219, 1962
665
- createSchroederReverb(audioContext, options = {}) {
666
- 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;
695
+ createSchroederReverb(audioContext, combDelays, combFeedbacks, allpassDelays, allpassFeedbacks) {
667
696
  const input = new GainNode(audioContext);
668
697
  const output = new GainNode(audioContext);
669
- const mergerGain = new GainNode(audioContext, {
670
- gain: 1 / (combDelays.length * 2),
671
- });
672
- const dryGain = new GainNode(audioContext, { gain: 1 - mix });
673
- const wetGain = new GainNode(audioContext, { gain: mix });
698
+ const mergerGain = new GainNode(audioContext);
674
699
  for (let i = 0; i < combDelays.length; i++) {
675
700
  const comb = this.createCombFilter(audioContext, input, combDelays[i], combFeedbacks[i]);
676
701
  comb.connect(mergerGain);
@@ -680,68 +705,65 @@ export class Midy {
680
705
  const allpass = this.createAllpassFilter(audioContext, (i === 0) ? mergerGain : allpasses.at(-1), allpassDelays[i], allpassFeedbacks[i]);
681
706
  allpasses.push(allpass);
682
707
  }
683
- allpasses.at(-1).connect(wetGain);
684
- input.connect(dryGain);
685
- dryGain.connect(output);
686
- wetGain.connect(output);
687
- return { input, output, dryGain, wetGain };
708
+ allpasses.at(-1).connect(output);
709
+ return { input, output };
688
710
  }
689
- createChorusEffect(audioContext, options = {}) {
690
- const { chorusCount = 2, chorusRate = 0.6, chorusDepth = 0.15, delay = 0.01, variance = delay * 0.1, } = options;
691
- const lfo = new OscillatorNode(audioContext, { frequency: chorusRate });
692
- const lfoGain = new GainNode(audioContext, { gain: chorusDepth });
711
+ createChorusEffect(audioContext) {
712
+ const input = new GainNode(audioContext);
693
713
  const output = new GainNode(audioContext);
694
- const chorusGains = [];
714
+ const sendGain = new GainNode(audioContext);
715
+ const lfo = new OscillatorNode(audioContext, {
716
+ frequency: this.chorus.modRate,
717
+ });
718
+ const lfoGain = new GainNode(audioContext, {
719
+ gain: this.chorus.modDepth / 2,
720
+ });
721
+ const delayTimes = this.chorus.delayTimes;
695
722
  const delayNodes = [];
696
- const baseGain = 1 / chorusCount;
697
- for (let i = 0; i < chorusCount; i++) {
698
- const randomDelayFactor = (Math.random() - 0.5) * variance;
699
- const delayTime = (i + 1) * delay + randomDelayFactor;
723
+ const feedbackGains = [];
724
+ for (let i = 0; i < delayTimes.length; i++) {
725
+ const delayTime = delayTimes[i];
700
726
  const delayNode = new DelayNode(audioContext, {
701
- maxDelayTime: delayTime,
727
+ maxDelayTime: 0.1, // generally, 5ms < delayTime < 50ms
728
+ delayTime,
729
+ });
730
+ const feedbackGain = new GainNode(audioContext, {
731
+ gain: this.chorus.feedback,
702
732
  });
703
- const chorusGain = new GainNode(audioContext, { gain: baseGain });
704
733
  delayNodes.push(delayNode);
705
- chorusGains.push(chorusGain);
734
+ feedbackGains.push(feedbackGain);
735
+ input.connect(delayNode);
706
736
  lfoGain.connect(delayNode.delayTime);
707
- delayNode.connect(chorusGain);
708
- chorusGain.connect(output);
737
+ delayNode.connect(feedbackGain);
738
+ feedbackGain.connect(delayNode);
739
+ delayNode.connect(output);
709
740
  }
741
+ output.connect(sendGain);
710
742
  lfo.connect(lfoGain);
711
743
  lfo.start();
712
744
  return {
745
+ input,
746
+ output,
747
+ sendGain,
713
748
  lfo,
714
749
  lfoGain,
715
750
  delayNodes,
716
- chorusGains,
717
- output,
751
+ feedbackGains,
718
752
  };
719
753
  }
720
754
  connectEffects(channel, gainNode) {
721
755
  gainNode.connect(channel.merger);
722
- if (channel.reverb === 0) {
723
- if (channel.chorus === 0) { // no effect
724
- channel.merger.connect(this.masterGain);
725
- }
726
- else { // chorus
727
- channel.chorusEffect.delayNodes.forEach((delayNode) => {
728
- channel.merger.connect(delayNode);
729
- });
730
- channel.chorusEffect.output.connect(this.masterGain);
731
- }
756
+ channel.merger.connect(this.masterGain);
757
+ if (0 < channel.reverbSendLevel) {
758
+ channel.merger.connect(channel.reverbEffect.input);
759
+ channel.reverbEffect.output.connect(this.masterGain);
732
760
  }
733
- else {
734
- if (channel.chorus === 0) { // reverb
735
- channel.merger.connect(channel.reverbEffect.input);
736
- channel.reverbEffect.output.connect(this.masterGain);
737
- }
738
- else { // reverb + chorus
739
- channel.chorusEffect.delayNodes.forEach((delayNode) => {
740
- channel.merger.connect(delayNode);
741
- });
742
- channel.merger.connect(channel.reverbEffect.input);
743
- channel.reverbEffect.output.connect(this.masterGain);
744
- }
761
+ if (0 < channel.chorusSendLevel) {
762
+ channel.merger.connect(channel.chorusEffect.input);
763
+ channel.reverbEffect.output.connect(this.masterGain);
764
+ }
765
+ if (0 < this.chorus.sendToReverb) {
766
+ channel.chorusEffect.sendGain.connect(channel.reverbEffect.input);
745
767
  }
746
768
  }
747
769
  cbToRatio(cb) {
@@ -1187,23 +1209,25 @@ export class Midy {
1187
1209
  this.releaseSustainPedal(channelNumber, value);
1188
1210
  }
1189
1211
  }
1212
+ // TODO
1190
1213
  setPortamento(channelNumber, value) {
1191
1214
  this.channels[channelNumber].portamento = value >= 64;
1192
1215
  }
1193
- setReverbSendLevel(channelNumber, reverb) {
1216
+ setReverbSendLevel(channelNumber, reverbSendLevel) {
1194
1217
  const now = this.audioContext.currentTime;
1195
1218
  const channel = this.channels[channelNumber];
1196
1219
  const reverbEffect = channel.reverbEffect;
1197
- channel.reverb = reverb / 127 * this.reverbFactor;
1198
- reverbEffect.dryGain.gain.cancelScheduledValues(now);
1199
- reverbEffect.dryGain.gain.setValueAtTime(1 - channel.reverb, now);
1200
- reverbEffect.wetGain.gain.cancelScheduledValues(now);
1201
- reverbEffect.wetGain.gain.setValueAtTime(channel.reverb, now);
1220
+ channel.reverbSendLevel = reverbSendLevel / 127;
1221
+ reverbEffect.output.gain.cancelScheduledValues(now);
1222
+ reverbEffect.output.gain.setValueAtTime(channel.reverbSendLevel, now);
1202
1223
  }
1203
- setChorusSendLevel(channelNumber, chorus) {
1224
+ setChorusSendLevel(channelNumber, chorusSendLevel) {
1225
+ const now = this.audioContext.currentTime;
1204
1226
  const channel = this.channels[channelNumber];
1205
- channel.chorus = chorus / 127;
1206
- channel.chorusEffect.lfoGain = channel.chorus;
1227
+ const chorusEffect = channel.chorusEffect;
1228
+ channel.chorusSendLevel = chorusSendLevel / 127;
1229
+ chorusEffect.output.gain.cancelScheduledValues(now);
1230
+ chorusEffect.output.gain.setValueAtTime(channel.chorusSendLevel, now);
1207
1231
  }
1208
1232
  setSostenutoPedal(channelNumber, value) {
1209
1233
  const isOn = value >= 64;
@@ -1427,11 +1451,11 @@ export class Midy {
1427
1451
  this.GM2SystemOn();
1428
1452
  break;
1429
1453
  default:
1430
- console.warn(`Unsupported Exclusive Message ${data}`);
1454
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1431
1455
  }
1432
1456
  break;
1433
1457
  default:
1434
- console.warn(`Unsupported Exclusive Message ${data}`);
1458
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1435
1459
  }
1436
1460
  }
1437
1461
  GM1SystemOn() {
@@ -1462,9 +1486,10 @@ export class Midy {
1462
1486
  return this.handleMasterFineTuningSysEx(data);
1463
1487
  case 4: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca25.pdf
1464
1488
  return this.handleMasterCoarseTuningSysEx(data);
1465
- // case 5: // TODO: Global Parameter Control
1489
+ case 5:
1490
+ return this.handleGlobalParameterControlSysEx(data);
1466
1491
  default:
1467
- console.warn(`Unsupported Exclusive Message ${data}`);
1492
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1468
1493
  }
1469
1494
  break;
1470
1495
  case 8:
@@ -1473,7 +1498,7 @@ export class Midy {
1473
1498
  // // TODO
1474
1499
  // return this.handleScaleOctaveTuning1ByteFormat();
1475
1500
  default:
1476
- console.warn(`Unsupported Exclusive Message ${data}`);
1501
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1477
1502
  }
1478
1503
  break;
1479
1504
  case 9:
@@ -1485,7 +1510,7 @@ export class Midy {
1485
1510
  // // TODO
1486
1511
  // return this.setControlChange();
1487
1512
  default:
1488
- console.warn(`Unsupported Exclusive Message ${data}`);
1513
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1489
1514
  }
1490
1515
  break;
1491
1516
  case 10:
@@ -1494,11 +1519,11 @@ export class Midy {
1494
1519
  // // TODO
1495
1520
  // return this.handleKeyBasedInstrumentControl();
1496
1521
  default:
1497
- console.warn(`Unsupported Exclusive Message ${data}`);
1522
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1498
1523
  }
1499
1524
  break;
1500
1525
  default:
1501
- console.warn(`Unsupported Exclusive Message ${data}`);
1526
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1502
1527
  }
1503
1528
  }
1504
1529
  handleMasterVolumeSysEx(data) {
@@ -1539,8 +1564,192 @@ export class Midy {
1539
1564
  this.masterCoarseTuning = coarseTuning - 64;
1540
1565
  }
1541
1566
  }
1567
+ handleGlobalParameterControlSysEx(data) {
1568
+ if (data[7] === 1) {
1569
+ switch (data[8]) {
1570
+ case 1:
1571
+ return this.handleReverbParameterSysEx(data);
1572
+ case 2:
1573
+ return this.handleChorusParameterSysEx(data);
1574
+ default:
1575
+ console.warn(`Unsupported Global Parameter Control Message: ${data}`);
1576
+ }
1577
+ }
1578
+ else {
1579
+ console.warn(`Unsupported Global Parameter Control Message: ${data}`);
1580
+ }
1581
+ }
1582
+ handleReverbParameterSysEx(data) {
1583
+ switch (data[9]) {
1584
+ case 0:
1585
+ return this.setReverbType(data[10]);
1586
+ case 1:
1587
+ return this.setReverbTime(data[10]);
1588
+ }
1589
+ }
1590
+ setReverbType(type) {
1591
+ this.reverb.time = this.getReverbTimeFromType(type);
1592
+ this.reverb.feedback = (type === 8) ? 0.1 : 0.2;
1593
+ const { audioContext, channels, options } = this;
1594
+ for (let i = 0; i < channels.length; i++) {
1595
+ channels[i].reverbEffect = options.reverbAlgorithm(audioContext);
1596
+ }
1597
+ }
1598
+ getReverbTimeFromType(type) {
1599
+ switch (type) {
1600
+ case 0:
1601
+ return this.getReverbTime(44);
1602
+ case 1:
1603
+ return this.getReverbTime(50);
1604
+ case 2:
1605
+ return this.getReverbTime(56);
1606
+ case 3:
1607
+ return this.getReverbTime(64);
1608
+ case 4:
1609
+ return this.getReverbTime(64);
1610
+ case 8:
1611
+ return this.getReverbTime(50);
1612
+ default:
1613
+ console.warn(`Unsupported Reverb Time: ${type}`);
1614
+ }
1615
+ }
1616
+ setReverbTime(value) {
1617
+ this.reverb.time = this.getReverbTime(value);
1618
+ const { audioContext, channels, options } = this;
1619
+ for (let i = 0; i < channels.length; i++) {
1620
+ channels[i].reverbEffect = options.reverbAlgorithm(audioContext);
1621
+ }
1622
+ }
1623
+ getReverbTime(value) {
1624
+ return Math.pow(Math.E, (value - 40) * 0.025);
1625
+ }
1626
+ // mean free path equation
1627
+ // https://repository.dl.itc.u-tokyo.ac.jp/record/8550/files/A31912.pdf
1628
+ // 江田和司, 拡散性制御に基づく室内音響設計に向けた音場解析に関する研究, 2015
1629
+ // V: room size (m^3)
1630
+ // S: room surface area (m^2)
1631
+ // meanFreePath = 4V / S (m)
1632
+ // delay estimation using mean free path
1633
+ // t: degree Celsius, generally used 20
1634
+ // c: speed of sound = 331.5 + 0.61t = 331.5 * 0.61 * 20 = 343.7 (m/s)
1635
+ // delay = meanFreePath / c (s)
1636
+ // feedback equation
1637
+ // RT60 means that the energy is reduced to Math.pow(10, -6).
1638
+ // Since energy is proportional to the square of the amplitude,
1639
+ // the amplitude is reduced to Math.pow(10, -3).
1640
+ // When this is done through n feedbacks,
1641
+ // Math.pow(feedback, n) = Math.pow(10, -3)
1642
+ // Math.pow(feedback, RT60 / delay) = Math.pow(10, -3)
1643
+ // RT60 / delay * Math.log10(feedback) = -3
1644
+ // RT60 = -3 * delay / Math.log10(feedback)
1645
+ // feedback = Math.pow(10, -3 * delay / RT60)
1646
+ // delay estimation using ideal feedback
1647
+ // The structure of a concert hall is complex,
1648
+ // so estimates based on mean free path are unstable.
1649
+ // It is easier to determine the delay based on ideal feedback.
1650
+ // The average sound absorption coefficient
1651
+ // suitable for playing musical instruments is 0.18 to 0.28.
1652
+ // delay = -RT60 * Math.log10(feedback) / 3
1653
+ calcDelay(rt60, feedback) {
1654
+ return -rt60 * Math.log10(feedback) / 3;
1655
+ }
1656
+ handleChorusParameterSysEx(data) {
1657
+ switch (data[9]) {
1658
+ case 0:
1659
+ return this.setChorusType(data[10]);
1660
+ case 1:
1661
+ return this.setChorusModRate(data[10]);
1662
+ case 2:
1663
+ return this.setChorusModDepth(data[10]);
1664
+ case 3:
1665
+ return this.setChorusFeedback(data[10]);
1666
+ case 4:
1667
+ return this.setChorusSendToReverb(data[10]);
1668
+ }
1669
+ }
1670
+ setChorusType(type) {
1671
+ switch (type) {
1672
+ case 0:
1673
+ return this.setChorusParameter(3, 5, 0, 0);
1674
+ case 1:
1675
+ return this.setChorusParameter(9, 19, 5, 0);
1676
+ case 2:
1677
+ return this.setChorusParameter(3, 19, 8, 0);
1678
+ case 3:
1679
+ return this.setChorusParameter(9, 16, 16, 0);
1680
+ case 4:
1681
+ return this.setChorusParameter(2, 24, 64, 0);
1682
+ case 5:
1683
+ return this.setChorusParameter(1, 5, 112, 0);
1684
+ default:
1685
+ console.warn(`Unsupported Chorus Type: ${type}`);
1686
+ }
1687
+ }
1688
+ setChorusParameter(modRate, modDepth, feedback, sendToReverb) {
1689
+ this.setChorusModRate(modRate);
1690
+ this.setChorusModDepth(modDepth);
1691
+ this.setChorusFeedback(feedback);
1692
+ this.setChorusSendToReverb(sendToReverb);
1693
+ }
1694
+ setChorusModRate(value) {
1695
+ const now = this.audioContext.currentTime;
1696
+ const modRate = this.getChorusModRate(value);
1697
+ this.chorus.modRate = modRate;
1698
+ for (let i = 0; i < this.channels.length; i++) {
1699
+ const lfo = this.channels[i].chorusEffect.lfo;
1700
+ lfo.frequency.setValueAtTime(modRate, now);
1701
+ }
1702
+ }
1703
+ getChorusModRate(value) {
1704
+ return value * 0.122; // Hz
1705
+ }
1706
+ setChorusModDepth(value) {
1707
+ const now = this.audioContext.currentTime;
1708
+ const modDepth = this.getChorusModDepth(value);
1709
+ this.chorus.modDepth = modDepth;
1710
+ for (let i = 0; i < this.channels.length; i++) {
1711
+ const chorusEffect = this.channels[i].chorusEffect;
1712
+ chorusEffect.lfoGain.gain
1713
+ .cancelScheduledValues(now)
1714
+ .setValueAtTime(modDepth / 2, now);
1715
+ }
1716
+ }
1717
+ getChorusModDepth(value) {
1718
+ return (value + 1) / 3200; // second
1719
+ }
1720
+ setChorusFeedback(value) {
1721
+ const now = this.audioContext.currentTime;
1722
+ const feedback = this.getChorusFeedback(value);
1723
+ this.chorus.feedback = feedback;
1724
+ for (let i = 0; i < this.channels.length; i++) {
1725
+ const chorusEffect = this.channels[i].chorusEffect;
1726
+ for (let j = 0; j < chorusEffect.feedbackGains.length; j++) {
1727
+ const feedbackGain = chorusEffect.feedbackGains[j];
1728
+ feedbackGain.gain
1729
+ .cancelScheduledValues(now)
1730
+ .setValueAtTime(feedback, now);
1731
+ }
1732
+ }
1733
+ }
1734
+ getChorusFeedback(value) {
1735
+ return value * 0.00763;
1736
+ }
1737
+ setChorusSendToReverb(value) {
1738
+ const now = this.audioContext.currentTime;
1739
+ const sendToReverb = this.getChorusSendToReverb(value);
1740
+ this.chorus.sendToReverb = sendToReverb;
1741
+ for (let i = 0; i < this.channels.length; i++) {
1742
+ const chorusEffect = this.channels[i].chorusEffect;
1743
+ chorusEffect.sendGain.gain
1744
+ .cancelScheduledValues(now)
1745
+ .setValueAtTime(sendToReverb, now);
1746
+ }
1747
+ }
1748
+ getChorusSendToReverb(value) {
1749
+ return value * 0.00787;
1750
+ }
1542
1751
  handleExclusiveMessage(data) {
1543
- console.warn(`Unsupported Exclusive Message ${data}`);
1752
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1544
1753
  }
1545
1754
  handleSysEx(data) {
1546
1755
  switch (data[0]) {
@@ -1573,8 +1782,8 @@ Object.defineProperty(Midy, "channelSettings", {
1573
1782
  volume: 100 / 127,
1574
1783
  pan: 64,
1575
1784
  portamentoTime: 0,
1576
- reverb: 0,
1577
- chorus: 0,
1785
+ reverbSendLevel: 0,
1786
+ chorusSendLevel: 0,
1578
1787
  vibratoRate: 5,
1579
1788
  vibratoDepth: 0.5,
1580
1789
  vibratoDelay: 2.5,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marmooo/midy",
3
- "version": "0.0.9",
3
+ "version": "0.1.1",
4
4
  "description": "A MIDI player/synthesizer written in JavaScript that supports GM-Lite/GM1 and SF2/SF3.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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"}
@@ -192,14 +192,10 @@ class MidyGM1 {
192
192
  const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
193
193
  gainL.connect(merger, 0, 0);
194
194
  gainR.connect(merger, 0, 1);
195
- const reverbEffect = this.createConvolutionReverb(audioContext);
196
- const chorusEffect = this.createChorusEffect(audioContext);
197
195
  return {
198
196
  gainL,
199
197
  gainR,
200
198
  merger,
201
- reverbEffect,
202
- chorusEffect,
203
199
  };
204
200
  }
205
201
  createChannels(audioContext) {
@@ -959,11 +955,11 @@ class MidyGM1 {
959
955
  case 2: // GM System Off
960
956
  break;
961
957
  default:
962
- console.warn(`Unsupported Exclusive Message ${data}`);
958
+ console.warn(`Unsupported Exclusive Message: ${data}`);
963
959
  }
964
960
  break;
965
961
  default:
966
- console.warn(`Unsupported Exclusive Message ${data}`);
962
+ console.warn(`Unsupported Exclusive Message: ${data}`);
967
963
  }
968
964
  }
969
965
  GM1SystemOn() {
@@ -982,11 +978,11 @@ class MidyGM1 {
982
978
  case 1:
983
979
  return this.handleMasterVolumeSysEx(data);
984
980
  default:
985
- console.warn(`Unsupported Exclusive Message ${data}`);
981
+ console.warn(`Unsupported Exclusive Message: ${data}`);
986
982
  }
987
983
  break;
988
984
  default:
989
- console.warn(`Unsupported Exclusive Message ${data}`);
985
+ console.warn(`Unsupported Exclusive Message: ${data}`);
990
986
  }
991
987
  }
992
988
  handleMasterVolumeSysEx(data) {
@@ -1004,7 +1000,7 @@ class MidyGM1 {
1004
1000
  }
1005
1001
  }
1006
1002
  handleExclusiveMessage(data) {
1007
- console.warn(`Unsupported Exclusive Message ${data}`);
1003
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1008
1004
  }
1009
1005
  handleSysEx(data) {
1010
1006
  switch (data[0]) {