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.

199 lines
4.8KB

  1. //**************************************************************************************
  2. //BitCrusher Module for VCV Rack by Autodafe http://www.autodafe.net
  3. //
  4. //Based on code taken from the Fundamentals plugins by Andrew Belt http://www.vcvrack.com
  5. //And part of code on musicdsp.org: http://musicdsp.org/showArchiveComment.php?ArchiveID=78
  6. //**************************************************************************************
  7. #include "Autodafe.hpp"
  8. #include <stdlib.h>
  9. namespace rack_plugin_Autodafe {
  10. #define SR (44100.f) // (todo) hardcoded sample rate
  11. #define F_PI (3.14159f)
  12. class Phaser{
  13. public:
  14. Phaser() //initialise to some usefull defaults...
  15. : _fb( .7f )
  16. , _lfoPhase( 0.f )
  17. , _depth( 1.f )
  18. , _zm1( 0.f )
  19. {
  20. Range( 440.f, 1600.f );
  21. Rate( .5f );
  22. }
  23. void Range( float fMin, float fMax ){ // Hz
  24. _dmin = fMin / (SR/2.f);
  25. _dmax = fMax / (SR/2.f);
  26. }
  27. void Rate( float rate ){ // cps
  28. _lfoInc = 2.f * F_PI * (rate / SR);
  29. }
  30. void Feedback( float fb ){ // 0 -> <1.
  31. _fb = fb;
  32. }
  33. void Depth( float depth ){ // 0 -> 1.
  34. _depth = depth;
  35. }
  36. float Update( float inSamp ){
  37. //calculate and update phaser sweep lfo...
  38. float d = _dmin + (_dmax-_dmin) * ((sin( _lfoPhase ) +
  39. 1.f)/2.f);
  40. _lfoPhase += _lfoInc;
  41. if( _lfoPhase >= F_PI * 2.f )
  42. _lfoPhase -= F_PI * 2.f;
  43. //update filter coeffs
  44. for( int i=0; i<6; i++ )
  45. _alps[i].Delay( d );
  46. //calculate output
  47. float y = _alps[0].Update(
  48. _alps[1].Update(
  49. _alps[2].Update(
  50. _alps[3].Update(
  51. _alps[4].Update(
  52. _alps[5].Update( inSamp + _zm1 * _fb ))))));
  53. _zm1 = y;
  54. return inSamp + y * _depth;
  55. }
  56. private:
  57. class AllpassDelay{
  58. public:
  59. AllpassDelay()
  60. : _a1( 0.f )
  61. , _zm1( 0.f )
  62. {}
  63. void Delay( float delay ){ //sample delay time
  64. _a1 = (1.f - delay) / (1.f + delay);
  65. }
  66. float Update( float inSamp ){
  67. float y = inSamp * -_a1 + _zm1;
  68. _zm1 = y * _a1 + inSamp;
  69. return y;
  70. }
  71. private:
  72. float _a1, _zm1;
  73. };
  74. AllpassDelay _alps[6];
  75. float _dmin, _dmax; //range
  76. float _fb; //feedback
  77. float _lfoPhase;
  78. float _lfoInc;
  79. float _depth;
  80. float _zm1;
  81. };
  82. struct PhaserFx : Module{
  83. enum ParamIds {
  84. PARAM_RATE,
  85. PARAM_FEEDBACK,
  86. PARAM_DEPTH,
  87. NUM_PARAMS
  88. };
  89. enum InputIds {
  90. INPUT,
  91. NUM_INPUTS
  92. };
  93. enum OutputIds {
  94. OUT,
  95. NUM_OUTPUTS
  96. };
  97. PhaserFx();
  98. float rate ;
  99. float feedback;
  100. float depth;
  101. float input;
  102. float out;
  103. Phaser *pha;
  104. void step();
  105. };
  106. PhaserFx::PhaserFx() {
  107. params.resize(NUM_PARAMS);
  108. inputs.resize(NUM_INPUTS);
  109. outputs.resize(NUM_OUTPUTS);
  110. pha = new Phaser();
  111. }
  112. void PhaserFx::step() {
  113. rate = params[PARAM_RATE].value;
  114. feedback = params[PARAM_FEEDBACK].value;
  115. depth = params[PARAM_DEPTH].value;
  116. input = inputs[INPUT].value / 5.0f;
  117. pha->Rate(rate);
  118. pha->Feedback(feedback);
  119. pha->Depth (depth);
  120. out = pha->Update(input);
  121. outputs[OUT].value= out * 5.0f;
  122. }
  123. struct PhaserFxWidget : ModuleWidget{
  124. PhaserFxWidget(PhaserFx *module);
  125. };
  126. PhaserFxWidget::PhaserFxWidget(PhaserFx *module) : ModuleWidget(module) {
  127. box.size = Vec(15 * 6, 380);
  128. {
  129. SVGPanel *panel = new SVGPanel();
  130. panel->box.size = box.size;
  131. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Phaser.svg")));
  132. addChild(panel);
  133. }
  134. addChild(createScrew<ScrewSilver>(Vec(1, 0)));
  135. addChild(createScrew<ScrewSilver>(Vec(box.size.x - 20, 0)));
  136. addChild(createScrew<ScrewSilver>(Vec(1, 365)));
  137. addChild(createScrew<ScrewSilver>(Vec(box.size.x - 20, 365)));
  138. addParam(createParam<AutodafeKnobGreen>(Vec(25, 51), module, PhaserFx::PARAM_RATE, 0, 1, 0));
  139. //addParam(createParam<AutodafeKnob>(Vec(25, 51), module, PhaserFx::PARAM_RATE, 0, 1, 0));
  140. addParam(createParam<AutodafeKnobGreen>(Vec(25, 111), module, PhaserFx::PARAM_FEEDBACK, 0, 0.95, 0));
  141. //addParam(createParam<AutodafeKnob>(Vec(25, 111), module, PhaserFx::PARAM_FEEDBACK, 0, 0.95, 0));
  142. addParam(createParam<AutodafeKnobGreen>(Vec(25, 171), module, PhaserFx::PARAM_DEPTH, 0, 1, 0));
  143. //addParam(createParam<AutodafeKnob>(Vec(25, 171), module, PhaserFx::PARAM_DEPTH, 0, 1, 0));
  144. addInput(createInput<PJ301MPort>(Vec(10, 320), module, PhaserFx::INPUT));
  145. addOutput(createOutput<PJ301MPort>(Vec(48, 320), module, PhaserFx::OUT));
  146. }
  147. } // namespace rack_plugin_Autodafe
  148. using namespace rack_plugin_Autodafe;
  149. RACK_PLUGIN_MODEL_INIT(Autodafe, PhaserFx) {
  150. return Model::create<PhaserFx, PhaserFxWidget>("Autodafe", "Phaser", "Phaser", EFFECT_TAG);
  151. }