Audio plugin host https://kx.studio/carla
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.

194 lines
5.4KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. LFO.cpp - LFO implementation
  4. Copyright (C) 2002-2005 Nasca Octavian Paul
  5. Author: Nasca Octavian Paul
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. */
  11. #include "LFO.h"
  12. #include "../Params/LFOParams.h"
  13. #include "../Misc/Util.h"
  14. #include <cstdlib>
  15. #include <cstdio>
  16. #include <cmath>
  17. LFO::LFO(const LFOParams &lfopars, float basefreq, const AbsTime &t, WatchManager *m,
  18. const char *watch_prefix)
  19. :first_half(-1),
  20. delayTime(t, lfopars.Pdelay / 127.0f * 4.0f), //0..4 sec
  21. waveShape(lfopars.PLFOtype),
  22. deterministic(!lfopars.Pfreqrand),
  23. dt_(t.dt()),
  24. lfopars_(lfopars), basefreq_(basefreq),
  25. watchOut(m, watch_prefix, "out")
  26. {
  27. int stretch = lfopars.Pstretch;
  28. if(stretch == 0)
  29. stretch = 1;
  30. //max 2x/octave
  31. const float lfostretch = powf(basefreq / 440.0f, (stretch - 64.0f) / 63.0f);
  32. const float lfofreq =
  33. (powf(2, lfopars.Pfreq * 10.0f) - 1.0f) / 12.0f * lfostretch;
  34. phaseInc = fabs(lfofreq) * t.dt();
  35. if(!lfopars.Pcontinous) {
  36. if(lfopars.Pstartphase == 0)
  37. phase = RND;
  38. else
  39. phase = fmod((lfopars.Pstartphase - 64.0f) / 127.0f + 1.0f, 1.0f);
  40. }
  41. else {
  42. const float tmp = fmod(t.time() * phaseInc, 1.0f);
  43. phase = fmod((lfopars.Pstartphase - 64.0f) / 127.0f + 1.0f + tmp, 1.0f);
  44. }
  45. //Limit the Frequency(or else...)
  46. if(phaseInc > 0.49999999f)
  47. phaseInc = 0.499999999f;
  48. lfornd = limit(lfopars.Prandomness / 127.0f, 0.0f, 1.0f);
  49. lfofreqrnd = powf(lfopars.Pfreqrand / 127.0f, 2.0f) * 4.0f;
  50. switch(lfopars.fel) {
  51. case 1:
  52. lfointensity = lfopars.Pintensity / 127.0f;
  53. break;
  54. case 2:
  55. lfointensity = lfopars.Pintensity / 127.0f * 4.0f;
  56. break; //in octave
  57. default:
  58. lfointensity = powf(2, lfopars.Pintensity / 127.0f * 11.0f) - 1.0f; //in centi
  59. phase -= 0.25f; //chance the starting phase
  60. break;
  61. }
  62. amp1 = (1 - lfornd) + lfornd * RND;
  63. amp2 = (1 - lfornd) + lfornd * RND;
  64. incrnd = nextincrnd = 1.0f;
  65. computeNextFreqRnd();
  66. computeNextFreqRnd(); //twice because I want incrnd & nextincrnd to be random
  67. }
  68. LFO::~LFO()
  69. {}
  70. float LFO::baseOut(const char waveShape, const float phase)
  71. {
  72. switch(waveShape) {
  73. case LFO_TRIANGLE:
  74. if(phase >= 0.0f && phase < 0.25f)
  75. return 4.0f * phase;
  76. else if(phase > 0.25f && phase < 0.75f)
  77. return 2 - 4 * phase;
  78. else
  79. return 4.0f * phase - 4.0f;
  80. break;
  81. case LFO_SQUARE:
  82. if(phase < 0.5f)
  83. return -1;
  84. else
  85. return 1;
  86. break;
  87. case LFO_RAMPUP: return (phase - 0.5f) * 2.0f;
  88. case LFO_RAMPDOWN: return (0.5f - phase) * 2.0f;
  89. case LFO_EXP_DOWN1: return powf(0.05f, phase) * 2.0f - 1.0f;
  90. case LFO_EXP_DOWN2: return powf(0.001f, phase) * 2.0f - 1.0f;
  91. case LFO_RANDOM:
  92. if ((phase < 0.5) != first_half) {
  93. first_half = phase < 0.5;
  94. last_random = 2*RND-1;
  95. }
  96. return last_random;
  97. default: return cosf(phase * 2.0f * PI); //LFO_SINE
  98. }
  99. }
  100. float LFO::lfoout()
  101. {
  102. //update internals XXX TODO cleanup
  103. if ( ! lfopars_.time || lfopars_.last_update_timestamp == lfopars_.time->time())
  104. {
  105. waveShape = lfopars_.PLFOtype;
  106. int stretch = lfopars_.Pstretch;
  107. if(stretch == 0)
  108. stretch = 1;
  109. const float lfostretch = powf(basefreq_ / 440.0f, (stretch - 64.0f) / 63.0f);
  110. float lfofreq =
  111. (powf(2, lfopars_.Pfreq * 10.0f) - 1.0f) / 12.0f * lfostretch;
  112. phaseInc = fabs(lfofreq) * dt_;
  113. switch(lfopars_.fel) {
  114. case 1:
  115. lfointensity = lfopars_.Pintensity / 127.0f;
  116. break;
  117. case 2:
  118. lfointensity = lfopars_.Pintensity / 127.0f * 4.0f;
  119. break; //in octave
  120. default:
  121. lfointensity = powf(2, lfopars_.Pintensity / 127.0f * 11.0f) - 1.0f; //in centi
  122. //x -= 0.25f; //chance the starting phase
  123. break;
  124. }
  125. }
  126. float out = baseOut(waveShape, phase);
  127. if(waveShape == LFO_SINE || waveShape == LFO_TRIANGLE)
  128. out *= lfointensity * (amp1 + phase * (amp2 - amp1));
  129. else
  130. out *= lfointensity * amp2;
  131. if(delayTime.inFuture())
  132. return out;
  133. //Start oscillating
  134. if(deterministic)
  135. phase += phaseInc;
  136. else {
  137. const float tmp = (incrnd * (1.0f - phase) + nextincrnd * phase);
  138. phase += phaseInc * limit(tmp, 0.0f, 1.0f);
  139. }
  140. if(phase >= 1) {
  141. phase = fmod(phase, 1.0f);
  142. amp1 = amp2;
  143. amp2 = (1 - lfornd) + lfornd * RND;
  144. computeNextFreqRnd();
  145. }
  146. float watch_data[2] = {phase, out};
  147. watchOut(watch_data, 2);
  148. return out;
  149. }
  150. /*
  151. * LFO out (for amplitude)
  152. */
  153. float LFO::amplfoout()
  154. {
  155. return limit(1.0f - lfointensity + lfoout(), -1.0f, 1.0f);
  156. }
  157. void LFO::computeNextFreqRnd()
  158. {
  159. if(deterministic)
  160. return;
  161. incrnd = nextincrnd;
  162. nextincrnd = powf(0.5f, lfofreqrnd) + RND * (powf(2.0f, lfofreqrnd) - 1.0f);
  163. }