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.

165 lines
4.8KB

  1. //**************************************************************************************
  2. //WaveSahper module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
  3. //
  4. //Code taken from HetrickCV plugins by Michael Hetrick https://github.com/mhetrick/hetrickcv
  5. //**************************************************************************************
  6. #include "AS.hpp"
  7. #include "dsp/digital.hpp"
  8. struct WaveShaper : Module {
  9. enum ParamIds {
  10. AMOUNT_PARAM,
  11. SCALE_PARAM,
  12. RANGE_PARAM,
  13. BYPASS_SWITCH,
  14. NUM_PARAMS
  15. };
  16. enum InputIds {
  17. INPUT,
  18. AMOUNT_INPUT,
  19. BYPASS_CV_INPUT,
  20. NUM_INPUTS
  21. };
  22. enum OutputIds {
  23. OUTPUT,
  24. NUM_OUTPUTS
  25. };
  26. enum LightIds {
  27. BYPASS_LED,
  28. NUM_LIGHTS
  29. };
  30. SchmittTrigger bypass_button_trig;
  31. SchmittTrigger bypass_cv_trig;
  32. bool fx_bypass = false;
  33. float fade_in_fx = 0.0f;
  34. float fade_in_dry = 0.0f;
  35. float fade_out_fx = 1.0f;
  36. float fade_out_dry = 1.0f;
  37. const float fade_speed = 0.001f;
  38. WaveShaper() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  39. void step() override;
  40. json_t *toJson()override {
  41. json_t *rootJm = json_object();
  42. json_t *statesJ = json_array();
  43. json_t *bypassJ = json_boolean(fx_bypass);
  44. json_array_append_new(statesJ, bypassJ);
  45. json_object_set_new(rootJm, "as_FxBypass", statesJ);
  46. return rootJm;
  47. }
  48. void fromJson(json_t *rootJm)override {
  49. json_t *statesJ = json_object_get(rootJm, "as_FxBypass");
  50. json_t *bypassJ = json_array_get(statesJ, 0);
  51. fx_bypass = !!json_boolean_value(bypassJ);
  52. }
  53. void resetFades(){
  54. fade_in_fx = 0.0f;
  55. fade_in_dry = 0.0f;
  56. fade_out_fx = 1.0f;
  57. fade_out_dry = 1.0f;
  58. }
  59. };
  60. void WaveShaper::step() {
  61. if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) ){
  62. fx_bypass = !fx_bypass;
  63. resetFades();
  64. }
  65. lights[BYPASS_LED].value = fx_bypass ? 1.0f : 0.0f;
  66. float input = inputs[INPUT].value;
  67. bool mode5V = (params[RANGE_PARAM].value == 0.0f);
  68. if(mode5V) input = clamp(input, -5.0f, 5.0f) * 0.2f;
  69. else input = clamp(input, -10.0f, 10.0f) * 0.1f;
  70. float shape = params[AMOUNT_PARAM].value + (inputs[AMOUNT_INPUT].value * params[SCALE_PARAM].value);
  71. shape = clamp(shape, -5.0f, 5.0f) * 0.2f;
  72. shape *= 0.99f;
  73. const float shapeB = (1.0f - shape) / (1.0f + shape);
  74. const float shapeA = (4.0f * shape) / ((1.0f - shape) * (1.0f + shape));
  75. float output = input * (shapeA + shapeB);
  76. output = output / ((std::abs(input) * shapeA) + shapeB);
  77. output *= 10.0f;
  78. //check for bypass switch status
  79. if (fx_bypass){
  80. fade_in_dry += fade_speed;
  81. if ( fade_in_dry > 1.0f ) {
  82. fade_in_dry = 1.0f;
  83. }
  84. fade_out_fx -= fade_speed;
  85. if ( fade_out_fx < 0.0f ) {
  86. fade_out_fx = 0.0f;
  87. }
  88. outputs[OUTPUT].value = ( input * fade_in_dry ) + ( output * fade_out_fx );
  89. }else{
  90. fade_in_fx += fade_speed;
  91. if ( fade_in_fx > 1.0f ) {
  92. fade_in_fx = 1.0f;
  93. }
  94. fade_out_dry -= fade_speed;
  95. if ( fade_out_dry < 0.0f ) {
  96. fade_out_dry = 0.0f;
  97. }
  98. outputs[OUTPUT].value = ( input * fade_out_dry ) + ( output * fade_in_fx );
  99. }
  100. }
  101. struct WaveShaperWidget : ModuleWidget
  102. {
  103. WaveShaperWidget(WaveShaper *module);
  104. };
  105. WaveShaperWidget::WaveShaperWidget(WaveShaper *module) : ModuleWidget(module) {
  106. setPanel(SVG::load(assetPlugin(plugin, "res/WaveShaper.svg")));
  107. //SCREWS
  108. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, 0)));
  109. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  110. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  111. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  112. //PARAMS
  113. addParam(ParamWidget::create<as_KnobBlack>(Vec(26, 60), module, WaveShaper::AMOUNT_PARAM, -5.0f, 5.0f, 0.0f));
  114. addParam(ParamWidget::create<as_KnobBlack>(Vec(26, 125), module, WaveShaper::SCALE_PARAM, -1.0f, 1.0f, 1.0f));
  115. //INPUTS
  116. addInput(Port::create<as_PJ301MPort>(Vec(33, 180), Port::INPUT, module, WaveShaper::AMOUNT_INPUT));
  117. //RANGE SWITCH
  118. addParam(ParamWidget::create<as_CKSSH>(Vec(33, 220), module, WaveShaper::RANGE_PARAM, 0.0f, 1.0f, 0.0f));
  119. //BYPASS SWITCH
  120. addParam(ParamWidget::create<LEDBezel>(Vec(55, 260), module, WaveShaper::BYPASS_SWITCH , 0.0f, 1.0f, 0.0f));
  121. addChild(ModuleLightWidget::create<LedLight<RedLight>>(Vec(57.2, 262), module, WaveShaper::BYPASS_LED));
  122. //INS/OUTS
  123. addInput(Port::create<as_PJ301MPort>(Vec(10, 310), Port::INPUT, module, WaveShaper::INPUT));
  124. addOutput(Port::create<as_PJ301MPort>(Vec(55, 310), Port::OUTPUT, module, WaveShaper::OUTPUT));
  125. //BYPASS CV INPUT
  126. addInput(Port::create<as_PJ301MPort>(Vec(10, 259), Port::INPUT, module, WaveShaper::BYPASS_CV_INPUT));
  127. }
  128. RACK_PLUGIN_MODEL_INIT(AS, WaveShaper) {
  129. Model *modelWaveShaper = Model::create<WaveShaper, WaveShaperWidget>("AS", "WaveShaper", "Wave Shaper", WAVESHAPER_TAG);
  130. return modelWaveShaper;
  131. }