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.

262 lines
10KB

  1. #include "Additator.hpp"
  2. void Additator::onReset() {
  3. _syncTrigger.reset();
  4. _steps = modulationSteps;
  5. _phase = PHASE_RESET;
  6. }
  7. void Additator::onSampleRateChange() {
  8. float sampleRate = engineGetSampleRate();
  9. _oscillator.setSampleRate(sampleRate);
  10. _maxFrequency = 0.475f * sampleRate;
  11. _steps = modulationSteps;
  12. _phase = PHASE_RESET;
  13. _widthSL.setParams(sampleRate, slewLimitTime, maxWidth);
  14. _oddSkewSL.setParams(sampleRate, slewLimitTime, 2.0f * maxSkew);
  15. _evenSkewSL.setParams(sampleRate, slewLimitTime, 2.0f * maxSkew);
  16. _amplitudeNormalizationSL.setParams(sampleRate, slewLimitTime, maxAmplitudeNormalization - minAmplitudeNormalization);
  17. _decaySL.setParams(sampleRate, slewLimitTime, maxDecay - minDecay);
  18. _balanceSL.setParams(sampleRate, slewLimitTime, 2.0f);
  19. _filterSL.setParams(sampleRate, slewLimitTime, maxFilter - minFilter);
  20. }
  21. float Additator::cvValue(Input& cv, bool dc) {
  22. if (!cv.active) {
  23. return dc ? 1.0f : 0.0f;
  24. }
  25. if (dc) {
  26. return clamp(cv.value / 10.0f, 0.0f, 1.0f);
  27. }
  28. return clamp(cv.value / 5.0f, -1.0f, 1.0f);
  29. }
  30. void Additator::step() {
  31. if (!outputs[AUDIO_OUTPUT].active) {
  32. Phase phase = params[PHASE_PARAM].value > 1.5f ? PHASE_COSINE : PHASE_SINE;
  33. lights[SINE_LIGHT].value = phase == PHASE_SINE;
  34. lights[COSINE_LIGHT].value = phase == PHASE_COSINE;
  35. return;
  36. }
  37. lights[SINE_LIGHT].value = _phase == PHASE_SINE;
  38. lights[COSINE_LIGHT].value = _phase == PHASE_COSINE;
  39. ++_steps;
  40. if (_steps >= modulationSteps) {
  41. _steps = 0;
  42. float width = _widthSL.next(clamp(params[WIDTH_PARAM].value + (maxWidth / 2.0f) * cvValue(inputs[WIDTH_INPUT]), 0.0f, maxWidth));
  43. float oddSkew = _oddSkewSL.next(clamp(params[ODD_SKEW_PARAM].value + cvValue(inputs[ODD_SKEW_INPUT]), -maxSkew, maxSkew));
  44. float evenSkew = _evenSkewSL.next(clamp(params[EVEN_SKEW_PARAM].value + cvValue(inputs[EVEN_SKEW_INPUT]), -maxSkew, maxSkew));
  45. if (
  46. _width != width ||
  47. _oddSkew != oddSkew ||
  48. _evenSkew != evenSkew
  49. ) {
  50. _width = width;
  51. _oddSkew = oddSkew;
  52. _evenSkew = evenSkew;
  53. float multiple = 1.0f;
  54. _oscillator.setPartialFrequencyRatio(1, multiple);
  55. _activePartials = 1;
  56. for (int i = 2, n = _oscillator.partialCount(); i <= n; ++i) {
  57. float ii = i;
  58. if (i % 2 == 0) {
  59. ii += _evenSkew;
  60. }
  61. else {
  62. ii += _oddSkew;
  63. }
  64. if (_oscillator.setPartialFrequencyRatio(i, powf(ii, _width))) {
  65. _activePartials = i;
  66. }
  67. }
  68. }
  69. int partials = clamp((int)roundf(params[PARTIALS_PARAM].value * cvValue(inputs[PARTIALS_INPUT], true)), 0, maxPartials);
  70. float amplitudeNormalization = _amplitudeNormalizationSL.next(clamp(params[GAIN_PARAM].value + ((maxAmplitudeNormalization - minAmplitudeNormalization) / 2.0f) * cvValue(inputs[GAIN_INPUT]), minAmplitudeNormalization, maxAmplitudeNormalization));
  71. float decay = _decaySL.next(clamp(params[DECAY_PARAM].value + ((maxDecay - minDecay) / 2.0f) * cvValue(inputs[DECAY_INPUT]), minDecay, maxDecay));
  72. float balance = _balanceSL.next(clamp(params[BALANCE_PARAM].value + cvValue(inputs[BALANCE_INPUT]), -1.0f, 1.0f));
  73. float filter = _filterSL.next(clamp(params[FILTER_PARAM].value + cvValue(inputs[FILTER_INPUT]), minFilter, maxFilter));
  74. if (
  75. _partials != partials ||
  76. _amplitudeNormalization != amplitudeNormalization ||
  77. _decay != decay ||
  78. _balance != balance ||
  79. _filter != filter
  80. ) {
  81. int envelopes = _partials != partials ? std::max(_partials, partials) : 0;
  82. _partials = partials;
  83. _amplitudeNormalization = amplitudeNormalization;
  84. _decay = decay;
  85. _balance = balance;
  86. _filter = filter;
  87. #ifdef _MSC_VER
  88. float *as = new float[maxPartials + 1];
  89. #else
  90. float as[maxPartials + 1];
  91. #endif
  92. float total = as[1] = 1.0f;
  93. filter = log10f(_filter) + 1.0f;
  94. int np = std::min(_partials, _activePartials);
  95. for (int i = 2, n = _oscillator.partialCount(); i <= n; ++i) {
  96. as[i] = 0.0f;
  97. if (i <= np) {
  98. as[i] = powf(i, -_decay) * powf(_filter, i);
  99. if (i % 2 == 0) {
  100. if (_balance > 0.0f) {
  101. as[i] *= 1.0f - _balance;
  102. }
  103. }
  104. else {
  105. if (_balance < 0.0f) {
  106. as[i] *= 1.0f + _balance;
  107. }
  108. }
  109. total += as[i];
  110. }
  111. }
  112. float norm = std::max(np / (float)_oscillator.partialCount(), 0.1f);
  113. norm = 1.0f + (_amplitudeNormalization - 1.0f) * norm;
  114. norm = std::max(total / norm, 0.7f);
  115. for (int i = 1, n = _oscillator.partialCount(); i <= n; ++i) {
  116. as[i] /= norm;
  117. _oscillator.setPartialAmplitude(i, as[i], i <= envelopes);
  118. }
  119. #ifdef _MSC_VER
  120. delete [] as;
  121. #endif
  122. }
  123. float frequency = params[FREQUENCY_PARAM].value;
  124. frequency += params[FINE_PARAM].value / 12.0f;;
  125. if (inputs[PITCH_INPUT].active) {
  126. frequency += clamp(inputs[PITCH_INPUT].value, -5.0f, 5.0f);
  127. }
  128. frequency = clamp(cvToFrequency(frequency), 20.0f, _maxFrequency);
  129. _oscillator.setFrequency(frequency);
  130. Phase phase = params[PHASE_PARAM].value > 1.5f ? PHASE_COSINE : PHASE_SINE;
  131. if (_phase != phase) {
  132. _phase = phase;
  133. _oscillator.syncToPhase(_phase == PHASE_SINE ? 0.0f : M_PI / 2.0f);
  134. }
  135. }
  136. if (_syncTrigger.next(inputs[SYNC_INPUT].value)) {
  137. _oscillator.syncToPhase(_phase == PHASE_SINE ? 0.0f : M_PI / 2.0f);
  138. }
  139. outputs[AUDIO_OUTPUT].value = _oscillator.next() * 5.0;
  140. }
  141. struct AdditatorWidget : ModuleWidget {
  142. static constexpr int hp = 15;
  143. AdditatorWidget(Additator* module) : ModuleWidget(module) {
  144. box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
  145. {
  146. SVGPanel *panel = new SVGPanel();
  147. panel->box.size = box.size;
  148. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Additator.svg")));
  149. addChild(panel);
  150. }
  151. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  152. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)));
  153. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  154. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)));
  155. // generated by svg_widgets.rb
  156. auto frequencyParamPosition = Vec(40.0, 45.0);
  157. auto partialsParamPosition = Vec(165.0, 60.0);
  158. auto fineParamPosition = Vec(30.0, 160.0);
  159. auto widthParamPosition = Vec(79.0, 155.0);
  160. auto oddSkewParamPosition = Vec(132.0, 155.0);
  161. auto evenSkewParamPosition = Vec(184.0, 155.0);
  162. auto gainParamPosition = Vec(25.0, 218.0);
  163. auto decayParamPosition = Vec(79.0, 218.0);
  164. auto balanceParamPosition = Vec(132.0, 218.0);
  165. auto filterParamPosition = Vec(184.0, 218.0);
  166. auto phaseParamPosition = Vec(194.0, 299.0);
  167. auto syncInputPosition = Vec(16.0, 274.0);
  168. auto partialsInputPosition = Vec(50.0, 274.0);
  169. auto widthInputPosition = Vec(84.0, 274.0);
  170. auto oddSkewInputPosition = Vec(118.0, 274.0);
  171. auto evenSkewInputPosition = Vec(152.0, 274.0);
  172. auto pitchInputPosition = Vec(16.0, 318.0);
  173. auto gainInputPosition = Vec(50.0, 318.0);
  174. auto decayInputPosition = Vec(84.0, 318.0);
  175. auto balanceInputPosition = Vec(118.0, 318.0);
  176. auto filterInputPosition = Vec(152.0, 318.0);
  177. auto audioOutputPosition = Vec(186.0, 318.0);
  178. auto sineLightPosition = Vec(185.0, 272.0);
  179. auto cosineLightPosition = Vec(185.0, 287.0);
  180. // end generated by svg_widgets.rb
  181. addParam(ParamWidget::create<Knob68>(frequencyParamPosition, module, Additator::FREQUENCY_PARAM, -3.0, 6.0, 0.0));
  182. {
  183. auto w = ParamWidget::create<Knob38>(partialsParamPosition, module, Additator::PARTIALS_PARAM, 1.0, module->maxPartials, module->maxPartials / 5.0);
  184. dynamic_cast<Knob*>(w)->snap = true;
  185. addParam(w);
  186. }
  187. addParam(ParamWidget::create<Knob16>(fineParamPosition, module, Additator::FINE_PARAM, -1.0, 1.0, 0.0));
  188. addParam(ParamWidget::create<Knob26>(widthParamPosition, module, Additator::WIDTH_PARAM, 0.0, module->maxWidth, module->maxWidth / 2.0));
  189. addParam(ParamWidget::create<Knob26>(oddSkewParamPosition, module, Additator::ODD_SKEW_PARAM, -module->maxSkew, module->maxSkew, 0.0));
  190. addParam(ParamWidget::create<Knob26>(evenSkewParamPosition, module, Additator::EVEN_SKEW_PARAM, -module->maxSkew, module->maxSkew, 0.0));
  191. addParam(ParamWidget::create<Knob26>(
  192. gainParamPosition,
  193. module,
  194. Additator::GAIN_PARAM,
  195. module->minAmplitudeNormalization,
  196. module->maxAmplitudeNormalization,
  197. (module->maxAmplitudeNormalization - module->minAmplitudeNormalization) / 2.0 + module->minAmplitudeNormalization
  198. ));
  199. addParam(ParamWidget::create<Knob26>(
  200. decayParamPosition,
  201. module,
  202. Additator::DECAY_PARAM,
  203. module->minDecay,
  204. module->maxDecay,
  205. (module->maxDecay - module->minDecay) / 2.0 + module->minDecay
  206. ));
  207. addParam(ParamWidget::create<Knob26>(balanceParamPosition, module, Additator::BALANCE_PARAM, -1.0, 1.0, 0.0));
  208. addParam(ParamWidget::create<Knob26>(
  209. filterParamPosition,
  210. module,
  211. Additator::FILTER_PARAM,
  212. module->minFilter,
  213. module->maxFilter,
  214. (module->maxFilter - module->minFilter) / 2.0 + module->minFilter
  215. ));
  216. addParam(ParamWidget::create<StatefulButton9>(phaseParamPosition, module, Additator::PHASE_PARAM, 1.0, 2.0, 1.0));
  217. addInput(Port::create<Port24>(partialsInputPosition, Port::INPUT, module, Additator::PARTIALS_INPUT));
  218. addInput(Port::create<Port24>(widthInputPosition, Port::INPUT, module, Additator::WIDTH_INPUT));
  219. addInput(Port::create<Port24>(oddSkewInputPosition, Port::INPUT, module, Additator::ODD_SKEW_INPUT));
  220. addInput(Port::create<Port24>(evenSkewInputPosition, Port::INPUT, module, Additator::EVEN_SKEW_INPUT));
  221. addInput(Port::create<Port24>(gainInputPosition, Port::INPUT, module, Additator::GAIN_INPUT));
  222. addInput(Port::create<Port24>(decayInputPosition, Port::INPUT, module, Additator::DECAY_INPUT));
  223. addInput(Port::create<Port24>(balanceInputPosition, Port::INPUT, module, Additator::BALANCE_INPUT));
  224. addInput(Port::create<Port24>(filterInputPosition, Port::INPUT, module, Additator::FILTER_INPUT));
  225. addInput(Port::create<Port24>(pitchInputPosition, Port::INPUT, module, Additator::PITCH_INPUT));
  226. addInput(Port::create<Port24>(syncInputPosition, Port::INPUT, module, Additator::SYNC_INPUT));
  227. addOutput(Port::create<Port24>(audioOutputPosition, Port::OUTPUT, module, Additator::AUDIO_OUTPUT));
  228. addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(sineLightPosition, module, Additator::SINE_LIGHT));
  229. addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(cosineLightPosition, module, Additator::COSINE_LIGHT));
  230. }
  231. };
  232. RACK_PLUGIN_MODEL_INIT(Bogaudio, Additator) {
  233. Model *modelAdditator = createModel<Additator, AdditatorWidget>("Bogaudio-Additator", "Additator", "additive oscillator", OSCILLATOR_TAG);
  234. return modelAdditator;
  235. }