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.

209 lines
6.3KB

  1. //***********************************************************************************************
  2. //
  3. //Reverb module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
  4. //
  5. //Based on code from ML_Modules by martin-lueders https://github.com/martin-lueders/ML_modules
  6. //And code from Freeverb by Jezar at Dreampoint - http://www.dreampoint.co.uk
  7. //
  8. //***********************************************************************************************
  9. #include "AS.hpp"
  10. #include "dsp/digital.hpp"
  11. #include "../freeverb/revmodel.hpp"
  12. struct ReverbFx : Module{
  13. enum ParamIds {
  14. DECAY_PARAM,
  15. DAMP_PARAM,
  16. BLEND_PARAM,
  17. BYPASS_SWITCH,
  18. NUM_PARAMS
  19. };
  20. enum InputIds {
  21. SIGNAL_INPUT,
  22. DECAY_CV_INPUT,
  23. DAMP_CV_INPUT,
  24. BLEND_CV_INPUT,
  25. BYPASS_CV_INPUT,
  26. NUM_INPUTS
  27. };
  28. enum OutputIds {
  29. SIGNAL_OUTPUT,
  30. NUM_OUTPUTS
  31. };
  32. enum LightIds {
  33. DECAY_LIGHT,
  34. DAMP_LIGHT,
  35. BLEND_LIGHT,
  36. BYPASS_LED,
  37. NUM_LIGHTS
  38. };
  39. revmodel reverb;
  40. float roomsize, damp;
  41. SchmittTrigger bypass_button_trig;
  42. SchmittTrigger bypass_cv_trig;
  43. bool fx_bypass = false;
  44. float fade_in_fx = 0.0f;
  45. float fade_in_dry = 0.0f;
  46. float fade_out_fx = 1.0f;
  47. float fade_out_dry = 1.0f;
  48. const float fade_speed = 0.001f;
  49. ReverbFx() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  50. float gSampleRate = engineGetSampleRate();
  51. reverb.init(gSampleRate);
  52. }
  53. void step() override;
  54. void onSampleRateChange() override;
  55. json_t *toJson()override {
  56. json_t *rootJm = json_object();
  57. json_t *statesJ = json_array();
  58. json_t *bypassJ = json_boolean(fx_bypass);
  59. json_array_append_new(statesJ, bypassJ);
  60. json_object_set_new(rootJm, "as_FxBypass", statesJ);
  61. return rootJm;
  62. }
  63. void fromJson(json_t *rootJm)override {
  64. json_t *statesJ = json_object_get(rootJm, "as_FxBypass");
  65. json_t *bypassJ = json_array_get(statesJ, 0);
  66. fx_bypass = !!json_boolean_value(bypassJ);
  67. }
  68. void resetFades(){
  69. fade_in_fx = 0.0f;
  70. fade_in_dry = 0.0f;
  71. fade_out_fx = 1.0f;
  72. fade_out_dry = 1.0f;
  73. }
  74. };
  75. void ReverbFx::onSampleRateChange() {
  76. float gSampleRate = engineGetSampleRate();
  77. reverb.init(gSampleRate);
  78. reverb.setdamp(damp);
  79. reverb.setroomsize(roomsize);
  80. };
  81. void ReverbFx::step() {
  82. if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) ){
  83. fx_bypass = !fx_bypass;
  84. resetFades();
  85. }
  86. lights[BYPASS_LED].value = fx_bypass ? 1.0f : 0.0f;
  87. float out1, out2;
  88. out1 = out2 = 0.0f;
  89. float old_roomsize = roomsize;
  90. float old_damp = damp;
  91. float input_signal = clamp(inputs[SIGNAL_INPUT].value,-10.0f,10.0f);
  92. //float input_signal = inputs[SIGNAL_INPUT].value;
  93. roomsize = clamp(params[DECAY_PARAM].value + inputs[DECAY_CV_INPUT].value / 10.0f, 0.0f, 0.88f);
  94. damp = clamp(params[DAMP_PARAM].value + inputs[DAMP_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
  95. if( old_damp != damp ) reverb.setdamp(damp);
  96. if( old_roomsize != roomsize) reverb.setroomsize(roomsize);
  97. reverb.process(input_signal+ input_signal, out1, out2);
  98. float out = input_signal + out1 * clamp(params[BLEND_PARAM].value + inputs[BLEND_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
  99. //check bypass switch status
  100. if (fx_bypass){
  101. fade_in_dry += fade_speed;
  102. if ( fade_in_dry > 1.0f ) {
  103. fade_in_dry = 1.0f;
  104. }
  105. fade_out_fx -= fade_speed;
  106. if ( fade_out_fx < 0.0f ) {
  107. fade_out_fx = 0.0f;
  108. }
  109. outputs[SIGNAL_OUTPUT].value = ( input_signal * fade_in_dry ) + ( out * fade_out_fx );
  110. }else{
  111. fade_in_fx += fade_speed;
  112. if ( fade_in_fx > 1.0f ) {
  113. fade_in_fx = 1.0f;
  114. }
  115. fade_out_dry -= fade_speed;
  116. if ( fade_out_dry < 0.0f ) {
  117. fade_out_dry = 0.0f;
  118. }
  119. outputs[SIGNAL_OUTPUT].value = ( input_signal * fade_out_dry ) + ( out * fade_in_fx );
  120. }
  121. lights[DECAY_LIGHT].value = clamp(params[DECAY_PARAM].value + inputs[DECAY_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
  122. lights[DAMP_LIGHT].value = clamp(params[DAMP_PARAM].value + inputs[DAMP_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
  123. lights[BLEND_LIGHT].value = clamp(params[BLEND_PARAM].value + inputs[BLEND_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
  124. }
  125. struct ReverbFxWidget : ModuleWidget
  126. {
  127. ReverbFxWidget(ReverbFx *module);
  128. };
  129. ReverbFxWidget::ReverbFxWidget(ReverbFx *module) : ModuleWidget(module) {
  130. setPanel(SVG::load(assetPlugin(plugin, "res/Reverb.svg")));
  131. //SCREWS
  132. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, 0)));
  133. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  134. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  135. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  136. //KNOBS
  137. addParam(ParamWidget::create<as_FxKnobWhite>(Vec(43, 60), module, ReverbFx::DECAY_PARAM, 0.0f, 0.9f, 0.5f));
  138. addParam(ParamWidget::create<as_FxKnobWhite>(Vec(43, 125), module, ReverbFx::DAMP_PARAM, 0.0f, 1.0f, 0.0f));
  139. addParam(ParamWidget::create<as_FxKnobWhite>(Vec(43, 190), module, ReverbFx::BLEND_PARAM, 0.0f, 1.0f, 0.5f));
  140. //LIGHTS
  141. addChild(ModuleLightWidget::create<SmallLight<YellowLight>>(Vec(39, 57), module, ReverbFx::DECAY_LIGHT));
  142. addChild(ModuleLightWidget::create<SmallLight<YellowLight>>(Vec(39, 122), module, ReverbFx::DAMP_LIGHT));
  143. addChild(ModuleLightWidget::create<SmallLight<YellowLight>>(Vec(39, 187), module, ReverbFx::BLEND_LIGHT));
  144. //BYPASS SWITCH
  145. addParam(ParamWidget::create<LEDBezel>(Vec(55, 260), module, ReverbFx::BYPASS_SWITCH , 0.0f, 1.0f, 0.0f));
  146. addChild(ModuleLightWidget::create<LedLight<RedLight>>(Vec(57.2, 262), module, ReverbFx::BYPASS_LED));
  147. //INS/OUTS
  148. addInput(Port::create<as_PJ301MPort>(Vec(10, 310), Port::INPUT, module, ReverbFx::SIGNAL_INPUT));
  149. addOutput(Port::create<as_PJ301MPort>(Vec(55, 310), Port::OUTPUT, module, ReverbFx::SIGNAL_OUTPUT));
  150. //CV INPUTS
  151. addInput(Port::create<as_PJ301MPort>(Vec(10, 67), Port::INPUT, module, ReverbFx::DECAY_CV_INPUT));
  152. addInput(Port::create<as_PJ301MPort>(Vec(10, 132), Port::INPUT, module, ReverbFx::DAMP_CV_INPUT));
  153. addInput(Port::create<as_PJ301MPort>(Vec(10, 197), Port::INPUT, module, ReverbFx::BLEND_CV_INPUT));
  154. //BYPASS CV INPUT
  155. addInput(Port::create<as_PJ301MPort>(Vec(10, 259), Port::INPUT, module, ReverbFx::BYPASS_CV_INPUT));
  156. }
  157. RACK_PLUGIN_MODEL_INIT(AS, ReverbFx) {
  158. Model *modelReverbFx = Model::create<ReverbFx, ReverbFxWidget>("AS", "ReverbFx", "Reverb FX", REVERB_TAG, EFFECT_TAG);
  159. return modelReverbFx;
  160. }