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.

183 lines
5.3KB

  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <random>
  4. #include <cmath>
  5. #include "dsp/digital.hpp"
  6. #include "RJModules.hpp"
  7. #include "VAStateVariableFilter.h"
  8. /*
  9. Voss pink noise algorithm from: http://www.firstpr.com.au/dsp/pink-noise/#Voss
  10. */
  11. namespace rack_plugin_RJModules {
  12. class PinkNumber
  13. {
  14. // goes from 0 to 118;
  15. private:
  16. int max_key;
  17. int key;
  18. unsigned int white_values[5];
  19. unsigned int range;
  20. public:
  21. PinkNumber(unsigned int range = 128)
  22. {
  23. max_key = 0x1f; // Five bits set
  24. this->range = range;
  25. key = 0;
  26. for (int i = 0; i < 5; i++){
  27. white_values[i] = rand() % (range/5);
  28. }
  29. }
  30. float GetNextValue()
  31. {
  32. int last_key = key;
  33. unsigned int sum;
  34. key++;
  35. if (key > max_key){
  36. key = 0;
  37. }
  38. // Exclusive-Or previous value with current value. This gives
  39. // a list of bits that have changed.
  40. int diff = last_key ^ key;
  41. sum = 0;
  42. for (int i = 0; i < 5; i++)
  43. {
  44. // If bit changed get new random number for corresponding
  45. // white_value
  46. if (diff & (1 << i))
  47. white_values[i] = rand() % (range/5);
  48. sum += white_values[i];
  49. }
  50. return 1.0 * (float)sum;
  51. }
  52. };
  53. struct Noise : Module {
  54. enum ParamIds {
  55. COLOR_PARAM,
  56. LPF_PARAM,
  57. HPF_PARAM,
  58. VOL_PARAM,
  59. NUM_PARAMS
  60. };
  61. enum InputIds {
  62. COLOR_CV_INPUT,
  63. LPF_CV_INPUT,
  64. HPF_CV_INPUT,
  65. NUM_INPUTS
  66. };
  67. enum OutputIds {
  68. NOISE_OUTPUT,
  69. NUM_OUTPUTS
  70. };
  71. enum LightIds {
  72. NUM_LIGHTS
  73. };
  74. PinkNumber pink = PinkNumber();
  75. float low = 99;
  76. float high = 0;
  77. float next;
  78. float mapped_pink = 0.0;
  79. float white = 0.0;
  80. float mixed = 0.0;
  81. float mix_value = 1.0;
  82. std::random_device rd; // obtain a random number from hardware
  83. float outLP;
  84. float outHP;
  85. VAStateVariableFilter *lpFilter = new VAStateVariableFilter() ; // create a lpFilter;
  86. VAStateVariableFilter *hpFilter = new VAStateVariableFilter() ; // create a hpFilter;
  87. Noise() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  88. void step() override;
  89. };
  90. void Noise::step(){
  91. next = pink.GetNextValue();
  92. mapped_pink = (next - 0) / (118 ) * 10 - 5;
  93. std::mt19937 eng(rd()); // seed the generator
  94. std::uniform_real_distribution<> distr1(-5, 5); // define the range
  95. white = distr1(eng);
  96. mix_value = params[COLOR_PARAM].value * clamp(inputs[COLOR_CV_INPUT].normalize(10.0f) / 10.0f, 0.0f, 1.0f);
  97. mixed = ( (mapped_pink * mix_value) + (white * (1.0 - mix_value)) )/ 2;
  98. // filtration
  99. mixed += 1.0e-6 * (2.0*randomUniform() - 1.0)*1000;
  100. //float cutoffcv = 400;//*params[LPF_PARAM].value * inputs[FREQ_INPUT].value+ 400*inputs[FREQ_INPUT2].value *params[FREQ_CV_PARAM2].value ;
  101. float lp_cutoff = params[LPF_PARAM].value * clamp(inputs[LPF_CV_INPUT].normalize(10.0f) / 10.0f, 0.0f, 1.0f);;
  102. float hp_cutoff = params[HPF_PARAM].value * clamp(inputs[HPF_CV_INPUT].normalize(10.0f) / 10.0f, 0.0f, 1.0f);; // + cutoffcv;
  103. lpFilter->setFilterType(0);
  104. hpFilter->setFilterType(2);
  105. lpFilter->setCutoffFreq(lp_cutoff);
  106. hpFilter->setCutoffFreq(hp_cutoff);
  107. lpFilter->setResonance(.6);
  108. hpFilter->setResonance(.6);
  109. lpFilter->setSampleRate(engineGetSampleRate());
  110. hpFilter->setSampleRate(engineGetSampleRate());
  111. mixed = lpFilter->processAudioSample(mixed, 1);
  112. mixed = hpFilter->processAudioSample(mixed, 1);
  113. // if you don't map to whatever, it just sounds like weird kinda cool crackles
  114. //outputs[NOISE_OUTPUT].value = pink.GetNextValue();
  115. outputs[NOISE_OUTPUT].value = mixed*2*params[VOL_PARAM].value;
  116. }
  117. struct NoiseWidget: ModuleWidget {
  118. NoiseWidget(Noise *module);
  119. };
  120. NoiseWidget::NoiseWidget(Noise *module) : ModuleWidget(module) {
  121. box.size = Vec(15*10, 380);
  122. {
  123. SVGPanel *panel = new SVGPanel();
  124. panel->box.size = box.size;
  125. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Noise.svg")));
  126. addChild(panel);
  127. }
  128. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  129. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  130. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  131. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  132. addParam(ParamWidget::create<RoundHugeBlackKnob>(Vec(47, 61), module, Noise::COLOR_PARAM, 0.0, 1.0, 1.0));
  133. addParam(ParamWidget::create<RoundHugeBlackKnob>(Vec(47, 143), module, Noise::LPF_PARAM, 0.0, 8000.0, 8000.0));
  134. addParam(ParamWidget::create<RoundHugeBlackKnob>(Vec(47, 228), module, Noise::HPF_PARAM, 30.0, 8000.0, 30.0));
  135. addInput(Port::create<PJ301MPort>(Vec(22, 100), Port::INPUT, module, Noise::COLOR_CV_INPUT));
  136. addInput(Port::create<PJ301MPort>(Vec(22, 190), Port::INPUT, module, Noise::LPF_CV_INPUT));
  137. addInput(Port::create<PJ301MPort>(Vec(22, 270), Port::INPUT, module, Noise::HPF_CV_INPUT));
  138. addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(20, 310), module, Noise::VOL_PARAM, 0.0, 2.0, 1.0));
  139. addOutput(Port::create<PJ301MPort>(Vec(100, 310), Port::OUTPUT, module, Noise::NOISE_OUTPUT));
  140. }
  141. } // namespace rack_plugin_RJModules
  142. using namespace rack_plugin_RJModules;
  143. RACK_PLUGIN_MODEL_INIT(RJModules, Noise) {
  144. Model *modelNoise = Model::create<Noise, NoiseWidget>("RJModules", "Noise", "[GEN] Noise", NOISE_TAG, RANDOM_TAG);
  145. return modelNoise;
  146. }