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.

416 lines
13KB

  1. #pragma once
  2. #include <rack.hpp>
  3. using namespace rack;
  4. extern Plugin* pluginInstance;
  5. extern Model* modelEvenVCO;
  6. extern Model* modelRampage;
  7. extern Model* modelABC;
  8. extern Model* modelSpringReverb;
  9. extern Model* modelMixer;
  10. extern Model* modelSlewLimiter;
  11. extern Model* modelDualAtenuverter;
  12. extern Model* modelPercall;
  13. extern Model* modelHexmixVCA;
  14. extern Model* modelChoppingKinky;
  15. extern Model* modelKickall;
  16. extern Model* modelSamplingModulator;
  17. extern Model* modelMorphader;
  18. extern Model* modelADSR;
  19. extern Model* modelSTMix;
  20. extern Model* modelMuxlicer;
  21. extern Model* modelMex;
  22. extern Model* modelNoisePlethora;
  23. extern Model* modelChannelStrip;
  24. extern Model* modelPonyVCO;
  25. extern Model* modelMotionMTR;
  26. extern Model* modelBurst;
  27. extern Model* modelMidiThing;
  28. extern Model* modelVoltio;
  29. extern Model* modelOctaves;
  30. extern Model* modelBypass;
  31. extern Model* modelBandit;
  32. struct Knurlie : SvgScrew {
  33. Knurlie() {
  34. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Knurlie.svg")));
  35. }
  36. };
  37. struct BefacoTinyKnobWhite : BefacoTinyKnob {
  38. BefacoTinyKnobWhite() {}
  39. };
  40. struct BefacoTinyKnobRed : BefacoTinyKnob {
  41. BefacoTinyKnobRed() {
  42. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoTinyPointWhite.svg")));
  43. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoTinyKnobRed_bg.svg")));
  44. }
  45. };
  46. struct BefacoTinyKnobDarkGrey : BefacoTinyKnob {
  47. BefacoTinyKnobDarkGrey() {
  48. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoTinyPointWhite.svg")));
  49. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoTinyKnobDarkGrey_bg.svg")));
  50. }
  51. };
  52. struct BefacoTinyKnobLightGrey : BefacoTinyKnob {
  53. BefacoTinyKnobLightGrey() {
  54. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoTinyKnobLightGrey_bg.svg")));
  55. }
  56. };
  57. struct BefacoTinyKnobBlack : BefacoTinyKnob {
  58. BefacoTinyKnobBlack() {
  59. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoTinyPointWhite.svg")));
  60. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoTinyKnobBlack_bg.svg")));
  61. }
  62. };
  63. struct Davies1900hLargeGreyKnob : Davies1900hKnob {
  64. Davies1900hLargeGreyKnob() {
  65. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hLargeGrey.svg")));
  66. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hLargeGrey_bg.svg")));
  67. }
  68. };
  69. struct Davies1900hLightGreyKnob : Davies1900hKnob {
  70. Davies1900hLightGreyKnob() {
  71. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hLightGrey.svg")));
  72. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hLightGrey_bg.svg")));
  73. }
  74. };
  75. struct Davies1900hDarkGreyKnob : Davies1900hKnob {
  76. Davies1900hDarkGreyKnob() {
  77. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hDarkGrey.svg")));
  78. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hDarkGrey_bg.svg")));
  79. }
  80. };
  81. /** Deprecated alias */
  82. using Davies1900hDarkBlackAlt = Davies1900hBlackKnob;
  83. struct BananutRed : app::SvgPort {
  84. BananutRed() {
  85. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BananutRed.svg")));
  86. }
  87. };
  88. /** Deprecated alias */
  89. using BefacoOutputPort = BananutRed;
  90. struct BananutBlack : app::SvgPort {
  91. BananutBlack() {
  92. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BananutBlack.svg")));
  93. }
  94. };
  95. /** Deprecated alias */
  96. using BefacoInputPort = BananutBlack;
  97. struct CKSSNarrow : app::SvgSwitch {
  98. CKSSNarrow() {
  99. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchNarrow_0.svg")));
  100. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchNarrow_2.svg")));
  101. }
  102. };
  103. struct Crossfader : app::SvgSlider {
  104. Crossfader() {
  105. setBackgroundSvg(Svg::load(asset::plugin(pluginInstance, "res/components/CrossfaderBackground.svg")));
  106. setHandleSvg(Svg::load(asset::plugin(pluginInstance, "res/components/CrossfaderHandle.svg")));
  107. minHandlePos = mm2px(Vec(4.5f, -0.8f));
  108. maxHandlePos = mm2px(Vec(34.5, -0.8f));
  109. horizontal = true;
  110. math::Vec margin = math::Vec(15, 5);
  111. background->box.pos = margin;
  112. box.size = background->box.size.plus(margin.mult(2));
  113. }
  114. };
  115. struct BefacoSwitchHorizontal : app::SvgSwitch {
  116. BefacoSwitchHorizontal() {
  117. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoSwitchHoriz_0.svg")));
  118. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoSwitchHoriz_1.svg")));
  119. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoSwitchHoriz_2.svg")));
  120. }
  121. };
  122. struct CKSSHoriz2 : app::SvgSwitch {
  123. CKSSHoriz2() {
  124. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchNarrowHoriz_0.svg")));
  125. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchNarrowHoriz_1.svg")));
  126. }
  127. };
  128. struct CKSSVert7 : app::SvgSlider {
  129. CKSSVert7() {
  130. math::Vec margin = math::Vec(3.5, 3.5);
  131. maxHandlePos = math::Vec(1, 1).plus(margin);
  132. minHandlePos = math::Vec(1, 45).plus(margin);
  133. setBackgroundSvg(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchTallVert_bg.svg")));
  134. setHandleSvg(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchTallVert_fg.svg")));
  135. background->box.pos = margin;
  136. box.size = background->box.size.plus(margin.mult(2));
  137. }
  138. // disable double click as this messes with click to advance
  139. void onDoubleClick(const event::DoubleClick& e) override { }
  140. // cycle through the values (with reset) on click only (not drag)
  141. void onAction(const ActionEvent& e) override {
  142. ParamQuantity* paramQuantity = getParamQuantity();
  143. float range = paramQuantity->maxValue - paramQuantity->minValue;
  144. float newValue = paramQuantity->getValue() + 1.f;
  145. if (newValue > paramQuantity->maxValue) {
  146. newValue -= range + 1.f;
  147. }
  148. paramQuantity->setValue(newValue);
  149. }
  150. };
  151. struct CKSSHoriz4 : app::SvgSlider {
  152. CKSSHoriz4() {
  153. setBackgroundSvg(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchWideHoriz_bg.svg")));
  154. setHandleSvg(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchWideHoriz_fg.svg")));
  155. minHandlePos = mm2px(Vec(0.3f, 0.3f));
  156. maxHandlePos = mm2px(Vec(6.3f, 0.3f));
  157. horizontal = true;
  158. math::Vec margin = math::Vec(0, 0);
  159. background->box.pos = margin;
  160. box.size = background->box.size.plus(margin.mult(2));
  161. }
  162. // disable double click as this messes with click to advance
  163. void onDoubleClick(const event::DoubleClick& e) override { }
  164. // cycle through the values (with reset) on click only (not drag)
  165. void onAction(const ActionEvent& e) override {
  166. ParamQuantity* paramQuantity = getParamQuantity();
  167. float range = paramQuantity->maxValue - paramQuantity->minValue;
  168. float newValue = paramQuantity->getValue() + 1.f;
  169. if (newValue > paramQuantity->maxValue) {
  170. newValue -= range + 1.f;
  171. }
  172. paramQuantity->setValue(newValue);
  173. }
  174. };
  175. struct CKSSNarrow3 : app::SvgSwitch {
  176. CKSSNarrow3() {
  177. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchNarrow_0.svg")));
  178. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchNarrow_1.svg")));
  179. addFrame(Svg::load(asset::plugin(pluginInstance, "res/components/SwitchNarrow_2.svg")));
  180. }
  181. };
  182. struct Davies1900hLargeLightGreyKnob : Davies1900hKnob {
  183. Davies1900hLargeLightGreyKnob() {
  184. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hLargeLightGrey.svg")));
  185. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hLargeLightGrey_bg.svg")));
  186. }
  187. };
  188. struct BefacoSlidePotSmall : app::SvgSlider {
  189. BefacoSlidePotSmall() {
  190. math::Vec margin = math::Vec(3.5, 3.5);
  191. maxHandlePos = math::Vec(-2, -2).plus(margin);
  192. minHandlePos = math::Vec(-2, 60).plus(margin);
  193. setBackgroundSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoSlidePotSmall.svg")));
  194. setHandleSvg(Svg::load(asset::plugin(pluginInstance, "res/components/BefacoSlidePotHandleSmall.svg")));
  195. background->box.pos = margin;
  196. box.size = background->box.size.plus(margin.mult(2));
  197. }
  198. };
  199. struct BefacoButton : app::SvgSwitch {
  200. BefacoButton() {
  201. momentary = true;
  202. addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/components/BefacoButton_0.svg")));
  203. addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/components/BefacoButton_1.svg")));
  204. }
  205. };
  206. struct Davies1900hWhiteKnobEndless : Davies1900hKnob {
  207. Davies1900hWhiteKnobEndless() {
  208. setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hWhiteEndless.svg")));
  209. bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/Davies1900hWhiteEndless_bg.svg")));
  210. }
  211. };
  212. template <typename TBase = WhiteLight>
  213. struct VeryLargeSimpleLight : TBase {
  214. VeryLargeSimpleLight() {
  215. this->box.size = mm2px(math::Vec(7, 7));
  216. }
  217. };
  218. inline int unsigned_modulo(int a, int b) {
  219. return ((a % b) + b) % b;
  220. }
  221. template <typename T>
  222. T sin2pi_pade_05_5_4(T x) {
  223. x -= 0.5f;
  224. return (T(-6.283185307) * x + T(33.19863968) * simd::pow(x, 3) - T(32.44191367) * simd::pow(x, 5))
  225. / (1 + T(1.296008659) * simd::pow(x, 2) + T(0.7028072946) * simd::pow(x, 4));
  226. }
  227. template <typename T>
  228. T tanh_pade(T x) {
  229. T x2 = x * x;
  230. T q = 12.f + x2;
  231. return 12.f * x * q / (36.f * x2 + q * q);
  232. }
  233. template <typename T>
  234. T exponentialBipolar80Pade_5_4(T x) {
  235. return (T(0.109568) * x + T(0.281588) * simd::pow(x, 3) + T(0.133841) * simd::pow(x, 5))
  236. / (T(1.) - T(0.630374) * simd::pow(x, 2) + T(0.166271) * simd::pow(x, 4));
  237. }
  238. struct ADEnvelope {
  239. enum Stage {
  240. STAGE_OFF,
  241. STAGE_ATTACK,
  242. STAGE_DECAY
  243. };
  244. Stage stage = STAGE_OFF;
  245. float env = 0.f;
  246. float attackTime = 0.1, decayTime = 0.1;
  247. float attackShape = 1.0, decayShape = 1.0;
  248. ADEnvelope() { };
  249. void process(const float& sampleTime) {
  250. if (stage == STAGE_OFF) {
  251. env = envLinear = 0.0f;
  252. }
  253. else if (stage == STAGE_ATTACK) {
  254. envLinear += sampleTime / attackTime;
  255. env = std::pow(envLinear, attackShape);
  256. }
  257. else if (stage == STAGE_DECAY) {
  258. envLinear -= sampleTime / decayTime;
  259. env = std::pow(envLinear, decayShape);
  260. }
  261. if (envLinear >= 1.0f) {
  262. stage = STAGE_DECAY;
  263. env = envLinear = 1.0f;
  264. }
  265. else if (envLinear <= 0.0f) {
  266. stage = STAGE_OFF;
  267. env = envLinear = 0.0f;
  268. }
  269. }
  270. void trigger() {
  271. stage = ADEnvelope::STAGE_ATTACK;
  272. // non-linear envelopes won't retrigger at the correct starting point if
  273. // attackShape != decayShape, so we advance the linear envelope
  274. envLinear = std::pow(env, 1.0f / attackShape);
  275. }
  276. private:
  277. float envLinear = 0.f;
  278. };
  279. // Creates a Butterworth 2*Nth order highpass filter for blocking DC
  280. template<int N, typename T>
  281. struct DCBlockerT {
  282. DCBlockerT() {
  283. setFrequency(0.1f);
  284. }
  285. // set frequency (in normalised units, 0 < fc < 1)
  286. void setFrequency(float fc) {
  287. fc_ = fc;
  288. recalculateCoefficients();
  289. }
  290. T process(T x) {
  291. for (int idx = 0; idx < N; idx++) {
  292. x = blockDCFilter[idx].process(x);
  293. }
  294. return x;
  295. }
  296. private:
  297. // https://www.earlevel.com/main/2016/09/29/cascading-filters/
  298. void recalculateCoefficients() {
  299. float poleInc = M_PI / order;
  300. float firstAngle = poleInc / 2;
  301. for (int idx = 0; idx < N; idx++) {
  302. float Q = 1.0f / (2.0f * std::cos(firstAngle + idx * poleInc));
  303. blockDCFilter[idx].setParameters(dsp::TBiquadFilter<T>::HIGHPASS, fc_, Q, 1.0f);
  304. }
  305. }
  306. float fc_;
  307. static const int order = 2 * N;
  308. dsp::TBiquadFilter<T> blockDCFilter[N];
  309. };
  310. typedef DCBlockerT<2, float> DCBlocker;
  311. /** When triggered, holds a high value for a specified time before going low again */
  312. struct PulseGenerator_4 {
  313. simd::float_4 remaining = 0.f;
  314. /** Immediately disables the pulse */
  315. void reset() {
  316. remaining = 0.f;
  317. }
  318. /** Advances the state by `deltaTime`. Returns whether the pulse is in the HIGH state. */
  319. simd::float_4 process(float deltaTime) {
  320. simd::float_4 mask = (remaining > 0.f);
  321. remaining -= ifelse(mask, deltaTime, 0.f);
  322. return ifelse(mask, simd::float_4::mask(), 0.f);
  323. }
  324. /** Begins a trigger with the given `duration`. */
  325. void trigger(simd::float_4 mask, float duration = 1e-3f) {
  326. // Keep the previous pulse if the existing pulse will be held longer than the currently requested one.
  327. remaining = ifelse(mask & (duration > remaining), duration, remaining);
  328. }
  329. };
  330. // Zavalishin 2018, "The Art of VA Filter Design", http://www.native-instruments.com/fileadmin/ni_media/downloads/pdf/VAFilterDesign_2.0.0a.pdf
  331. // Section 6.7, adopted from BogAudio Saturator https://github.com/bogaudio/BogaudioModules/blob/master/src/dsp/signal.cpp
  332. template <class T>
  333. struct Saturator {
  334. // saturate input at around ~[-1, +1] V with soft clipping
  335. static T process(T sample) {
  336. return simd::ifelse(sample < 0.f, -saturation(-sample), saturation(sample));
  337. }
  338. private:
  339. static T saturation(T sample) {
  340. const float limit = 1.05f;
  341. const float y1 = 0.98765f; // (2*x - 1)/x**2 where x is 0.9.
  342. // correction so that saturation(0) = 0
  343. const float offset = 0.0062522; // -0.5f + sqrtf(0.5f * 0.5f) / y1;
  344. T x = sample / limit;
  345. T x1 = (x + 1.0f) * 0.5f;
  346. return limit * (offset + x1 - simd::sqrt(x1 * x1 - y1 * x) * (1.0f / y1));
  347. }
  348. };