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.

129 lines
2.9KB

  1. /*
  2. TaHaSaHaN
  3. TrackAndHoldAndSampleAndHoldandNoise
  4. the mix knob blends SaH and TaH signals into one output.
  5. left side: SaH
  6. right side: TaH
  7. TODO: cv handling
  8. */////////////////////////////////////////////////////////////////////////////
  9. #include "pvc.hpp"
  10. #include "dsp/digital.hpp" // SchmittTrigger // PulseGenerator
  11. namespace rack_plugin_PvC {
  12. struct TaHaSaHaN : Module {
  13. enum ParamIds {
  14. BLEND,
  15. NUM_PARAMS
  16. };
  17. enum InputIds {
  18. SAMPLE,
  19. TRIGGER,
  20. BLEND_CV,
  21. NUM_INPUTS
  22. };
  23. enum OutputIds {
  24. MIX,
  25. SNH,
  26. TNH,
  27. NOISE,
  28. NUM_OUTPUTS
  29. };
  30. enum LightIds {
  31. NUM_LIGHTS
  32. };
  33. SchmittTrigger sampleTrigger;
  34. float input = 0.0f;
  35. float snhOut = 0.0f;
  36. float tnhOut = 0.0f;
  37. float noise = 0.0f;
  38. TaHaSaHaN() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  39. void step() override;
  40. void reset() override {
  41. input = snhOut = tnhOut = noise = 0.0f;
  42. }
  43. };
  44. void TaHaSaHaN::step() {
  45. noise = randomUniform()*10.0f - 5.0f;
  46. if (inputs[TRIGGER].active){
  47. input = inputs[SAMPLE].normalize(noise);
  48. if (sampleTrigger.process(inputs[TRIGGER].value)){
  49. snhOut = input;
  50. }
  51. if (inputs[TRIGGER].value > 0.01f){
  52. tnhOut = input;
  53. }
  54. }
  55. else snhOut = tnhOut = 0.0f;
  56. // TODO: better cv/knob interaction.
  57. float blend = params[BLEND].value;
  58. if (inputs[BLEND_CV].active)
  59. blend *= clamp(inputs[BLEND_CV].value * 0.1f, 0.0f, 1.0f);
  60. outputs[MIX].value = crossfade(snhOut,tnhOut,blend);
  61. outputs[SNH].value = snhOut;
  62. outputs[TNH].value = tnhOut;
  63. outputs[NOISE].value = noise;
  64. }
  65. struct TaHaSaHaNWidget : ModuleWidget {
  66. TaHaSaHaNWidget(TaHaSaHaN *module);
  67. };
  68. TaHaSaHaNWidget::TaHaSaHaNWidget(TaHaSaHaN *module) : ModuleWidget(module) {
  69. setPanel(SVG::load(assetPlugin(plugin, "res/panels/TaHaSaHaN.svg")));
  70. // screws
  71. addChild(Widget::create<ScrewHead4>(Vec(0, 0)));
  72. // addChild(Widget::create<ScrewHead1>(Vec(box.size.x - 15, 0)));
  73. // addChild(Widget::create<ScrewHead3>(Vec(0, 365)));
  74. addChild(Widget::create<ScrewHead2>(Vec(box.size.x - 15, 365)));
  75. addInput(Port::create<InPortAud>(Vec(4,22), Port::INPUT, module, TaHaSaHaN::SAMPLE));
  76. addInput(Port::create<InPortBin>(Vec(4,64), Port::INPUT, module, TaHaSaHaN::TRIGGER));
  77. addOutput(Port::create<OutPortVal>(Vec(4,132), Port::OUTPUT, module, TaHaSaHaN::TNH));
  78. addOutput(Port::create<OutPortVal>(Vec(4,176), Port::OUTPUT, module, TaHaSaHaN::SNH));
  79. addOutput(Port::create<OutPortVal>(Vec(4,220), Port::OUTPUT, module, TaHaSaHaN::NOISE));
  80. addParam(ParamWidget::create<PvCKnob>(Vec(4,258),module, TaHaSaHaN::BLEND, 0.0f, 1.0f, 0.5f));
  81. addInput(Port::create<InPortCtrl>(Vec(4,282), Port::INPUT, module, TaHaSaHaN::BLEND_CV));
  82. addOutput(Port::create<OutPortVal>(Vec(4,336), Port::OUTPUT, module, TaHaSaHaN::MIX));
  83. }
  84. } // namespace rack_plugin_PvC
  85. using namespace rack_plugin_PvC;
  86. RACK_PLUGIN_MODEL_INIT(PvC, TaHaSaHaN) {
  87. Model *modelTaHaSaHaN = Model::create<TaHaSaHaN, TaHaSaHaNWidget>(
  88. "PvC", "TaHaSaHaN", "TaHaSaHaN", SAMPLE_AND_HOLD_TAG, NOISE_TAG, RANDOM_TAG);
  89. return modelTaHaSaHaN;
  90. }