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.

120 lines
3.1KB

  1. namespace rack_plugin_BaconMusic {
  2. template <typename TBase>
  3. struct Glissinator : public TBase {
  4. enum ParamIds {
  5. GLISS_TIME,
  6. NUM_PARAMS
  7. };
  8. enum InputIds {
  9. SOURCE_INPUT,
  10. NUM_INPUTS
  11. };
  12. enum OutputIds {
  13. SLID_OUTPUT,
  14. GLISSING_GATE,
  15. NUM_OUTPUTS
  16. };
  17. enum LightIds {
  18. SLIDING_LIGHT,
  19. NUM_LIGHTS
  20. };
  21. float priorIn;
  22. float targetIn;
  23. int offsetCount;
  24. // Hey thanks https://stackoverflow.com/a/4643091
  25. using TBase::params;
  26. using TBase::inputs;
  27. using TBase::outputs;
  28. using TBase::lights;
  29. Glissinator() : TBase( NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS ) {
  30. offsetCount = -1;
  31. params[ GLISS_TIME ].value = 0.1;
  32. }
  33. void step() override
  34. {
  35. float glist_sec = params[ GLISS_TIME ].value;
  36. int shift_time = engineGetSampleRate() * glist_sec;
  37. if( shift_time < 10 ) shift_time = 10;
  38. float thisIn = inputs[ SOURCE_INPUT ].value;
  39. // This means I am being intialized
  40. if( offsetCount < 0 )
  41. {
  42. priorIn = thisIn;
  43. offsetCount = 0;
  44. }
  45. bool inGliss = offsetCount != 0;
  46. float thisOut = thisIn;
  47. // When I begin the cycle, the shift_time may be a different shift_time than the
  48. // prior cycle. This is not a problem unless the shift time is now shorter than
  49. // the offset_time. If that's the case we have basically finished the gliss.
  50. // This check used to be at the end of the loop but that lead to one bad value
  51. // even with the >=
  52. if( offsetCount >= shift_time )
  53. {
  54. offsetCount = 0;
  55. priorIn = thisIn;
  56. targetIn = thisIn;
  57. inGliss = false;
  58. }
  59. // I am not glissing
  60. if( ! inGliss )
  61. {
  62. // But I have a new target, so start glissing by setting offset count to 1.
  63. if( thisIn != priorIn )
  64. {
  65. targetIn = thisIn;
  66. offsetCount = 1;
  67. inGliss = true;
  68. }
  69. }
  70. // I am glissing (note this is NOT in an else since inGliss can be reset above)
  71. if( inGliss )
  72. {
  73. // OK this means my note has changed underneath me so I have to simulate my
  74. // starting point.
  75. if( thisIn != targetIn )
  76. {
  77. // This "-1" is here because we want to know the LAST known step - so at the prior
  78. // offset count. Without this a turnaround will tick above the turnaround point for one
  79. // sample.
  80. float lastKnown = ( ( shift_time - (offsetCount-1) ) * priorIn +
  81. (offsetCount-1) * targetIn) / shift_time;
  82. targetIn = thisIn;
  83. priorIn = lastKnown;
  84. offsetCount = 0;
  85. }
  86. // Then the output is just the weighted sum of the prior input and this input.
  87. thisOut = ( ( shift_time - offsetCount ) * priorIn +
  88. offsetCount * thisIn ) / shift_time;
  89. // and step along one.
  90. offsetCount ++;
  91. }
  92. lights[ SLIDING_LIGHT ].value = inGliss ? 1 : 0;
  93. outputs[ SLID_OUTPUT ].value = thisOut;
  94. outputs[ GLISSING_GATE ].value = inGliss ? 10 : 0;
  95. }
  96. };
  97. } // namespace rack_plugin_BaconMusic