MicroDexed is a compatible 6-operator-FM-synth based on the Teensy(-3.6/-4.0) Microcontroller. https://www.parasitstudio.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
5.6KB

  1. /*
  2. * Copyright 2017 Pascal Gauthier.
  3. * Copyright 2012 Google Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include <math.h>
  18. #include "synth.h"
  19. #include "env.h"
  20. //using namespace std;
  21. uint32_t Env::sr_multiplier = (1<<24);
  22. const int levellut[] = {
  23. 0, 5, 9, 13, 17, 20, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46
  24. };
  25. #ifdef ACCURATE_ENVELOPE
  26. const int statics[] = {
  27. 1764000, 1764000, 1411200, 1411200, 1190700, 1014300, 992250,
  28. 882000, 705600, 705600, 584325, 507150, 502740, 441000, 418950,
  29. 352800, 308700, 286650, 253575, 220500, 220500, 176400, 145530,
  30. 145530, 125685, 110250, 110250, 88200, 88200, 74970, 61740,
  31. 61740, 55125, 48510, 44100, 37485, 31311, 30870, 27562, 27562,
  32. 22050, 18522, 17640, 15435, 14112, 13230, 11025, 9261, 9261, 7717,
  33. 6615, 6615, 5512, 5512, 4410, 3969, 3969, 3439, 2866, 2690, 2249,
  34. 1984, 1896, 1808, 1411, 1367, 1234, 1146, 926, 837, 837, 705,
  35. 573, 573, 529, 441, 441
  36. // and so on, I stopped measuring after R=76 (needs to be FRAC_NUM-checked anyway)
  37. };
  38. #endif
  39. void Env::init_sr(FRAC_NUM sampleRate) {
  40. sr_multiplier = (44100.0 / sampleRate) * (1<<24);
  41. }
  42. void Env::init(const int r[4], const int l[4], int ol, int rate_scaling) {
  43. for (int i = 0; i < 4; i++) {
  44. rates_[i] = r[i];
  45. levels_[i] = l[i];
  46. }
  47. outlevel_ = ol;
  48. rate_scaling_ = rate_scaling;
  49. level_ = 0;
  50. down_ = true;
  51. advance(0);
  52. }
  53. int32_t Env::getsample() {
  54. #ifdef ACCURATE_ENVELOPE
  55. if (staticcount_) {
  56. staticcount_ -= N;
  57. if (staticcount_ <= 0) {
  58. staticcount_ = 0;
  59. advance(ix_ + 1);
  60. }
  61. }
  62. #endif
  63. if (ix_ < 3 || ((ix_ < 4) && !down_)) {
  64. if (rising_) {
  65. const int jumptarget = 1716;
  66. if (level_ < (jumptarget << 16)) {
  67. level_ = jumptarget << 16;
  68. }
  69. level_ += (((17 << 24) - level_) >> 24) * inc_;
  70. // TODO: should probably be more accurate when inc is large
  71. if (level_ >= targetlevel_) {
  72. level_ = targetlevel_;
  73. advance(ix_ + 1);
  74. }
  75. }
  76. else if (staticcount_) {
  77. ;
  78. }
  79. else { // !rising
  80. level_ -= inc_;
  81. if (level_ <= targetlevel_) {
  82. level_ = targetlevel_;
  83. advance(ix_ + 1);
  84. }
  85. }
  86. }
  87. // TODO: this would be a good place to set level to 0 when under threshold
  88. return level_;
  89. }
  90. void Env::keydown(bool d) {
  91. if (down_ != d) {
  92. down_ = d;
  93. advance(d ? 0 : 3);
  94. }
  95. }
  96. int Env::scaleoutlevel(int outlevel) {
  97. return outlevel >= 20 ? 28 + outlevel : levellut[outlevel];
  98. }
  99. void Env::advance(int newix) {
  100. ix_ = newix;
  101. if (ix_ < 4) {
  102. int newlevel = levels_[ix_];
  103. int actuallevel = scaleoutlevel(newlevel) >> 1;
  104. actuallevel = (actuallevel << 6) + outlevel_ - 4256;
  105. actuallevel = actuallevel < 16 ? 16 : actuallevel;
  106. // level here is same as Java impl
  107. targetlevel_ = actuallevel << 16;
  108. rising_ = (targetlevel_ > level_);
  109. // rate
  110. int qrate = (rates_[ix_] * 41) >> 6;
  111. qrate += rate_scaling_;
  112. qrate = min(qrate, 63);
  113. #ifdef ACCURATE_ENVELOPE
  114. if (targetlevel_ == level_) {
  115. // approximate number of samples at 44.100 kHz to achieve the time
  116. // empirically gathered using 2 TF1s, could probably use some FRAC_NUM-checking
  117. // and cleanup, but it's pretty close for now.
  118. int staticrate = rates_[ix_];
  119. staticrate += rate_scaling_; // needs to be checked, as well, but seems correct
  120. staticrate = min(staticrate, 99);
  121. staticcount_ = staticrate < 77 ? statics[staticrate] : 20 * (99 - staticrate);
  122. staticcount_ = (int)(((int64_t)staticcount_ * (int64_t)sr_multiplier) >> 24);
  123. }
  124. else {
  125. staticcount_ = 0;
  126. }
  127. #endif
  128. inc_ = (4 + (qrate & 3)) << (2 + LG_N + (qrate >> 2));
  129. // meh, this should be fixed elsewhere
  130. inc_ = (int)(((int64_t)inc_ * (int64_t)sr_multiplier) >> 24);
  131. }
  132. }
  133. void Env::update(const int r[4], const int l[4], int ol, int rate_scaling) {
  134. for (int i = 0; i < 4; i++) {
  135. rates_[i] = r[i];
  136. levels_[i] = l[i];
  137. }
  138. outlevel_ = ol;
  139. rate_scaling_ = rate_scaling;
  140. if ( down_ ) {
  141. // for now we simply reset ourselve at level 3
  142. int newlevel = levels_[2];
  143. int actuallevel = scaleoutlevel(newlevel) >> 1;
  144. actuallevel = (actuallevel << 6) - 4256;
  145. actuallevel = actuallevel < 16 ? 16 : actuallevel;
  146. targetlevel_ = actuallevel << 16;
  147. advance(2);
  148. }
  149. }
  150. void Env::getPosition(char *step) {
  151. *step = ix_;
  152. }
  153. void Env::transfer(Env &src) {
  154. for(int i=0;i<4;i++) {
  155. rates_[i] = src.rates_[i];
  156. levels_[i] = src.levels_[i];
  157. }
  158. outlevel_ = src.outlevel_;
  159. rate_scaling_ = src.rate_scaling_;
  160. level_ = src.level_;
  161. targetlevel_ = src.targetlevel_;
  162. rising_= src.rising_;
  163. ix_ = src.ix_;
  164. down_ = src.down_;
  165. #ifdef ACCURATE_ENVELOPE
  166. staticcount_ = src.staticcount_;
  167. #endif
  168. inc_ = src.inc_;
  169. }