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.

136 lines
3.2KB

  1. #include "FrozenWasteland.hpp"
  2. #include "dsp/decimator.hpp"
  3. #include "dsp/digital.hpp"
  4. #include <complex>
  5. using namespace std;
  6. #define BUFFER_SIZE 32000
  7. #define FRAME_COUNT 10
  8. #define FREQUENCY_BANDS 6
  9. #ifndef FCOMPLEX_H_
  10. #define FCOMPLEX_H_
  11. #define J fcomplex(0.0,1.0)
  12. typedef std::complex<float> fcomplex;
  13. #endif /* FCOMPLEX_H_ */
  14. namespace rack_plugin_FrozenWasteland {
  15. struct Sabonis : Module {
  16. enum ParamIds {
  17. SMOOTHENESS_PARAM,
  18. NUM_PARAMS
  19. };
  20. enum InputIds {
  21. SIGNAL_IN,
  22. NUM_INPUTS
  23. };
  24. enum OutputIds {
  25. TRANSIENT_OUTPUT,
  26. TONAL_OUTPUT,
  27. NUM_OUTPUTS
  28. };
  29. int defaultWindowSize = 2048; //11ms window. NOTE add detection for sample rate change
  30. int halfWindowSize = defaultWindowSize / 2;
  31. int hopSize = 512; //30ms overlap. NOTE add detection for sample rate change
  32. float windowFunction[BUFFER_SIZE] = {};
  33. float signalBuffer[BUFFER_SIZE] = {};
  34. float X[BUFFER_SIZE][FREQUENCY_BANDS] = {};
  35. void CreateBlackmanHarrisWindow(int windowSize)
  36. {
  37. float a0 = 0.35875;
  38. float a1 = 0.48829;
  39. float a2 = 0.14128;
  40. float a3 = 0.01168;
  41. for(int n=0;n<halfWindowSize;n++)
  42. {
  43. windowFunction[n] = a0 - a1*cosf(2*M_PI*n/(halfWindowSize-1)) + a2*cosf(4*M_PI*n/(halfWindowSize-1)) - a3*cosf(6*M_PI*n/(halfWindowSize-1));
  44. }
  45. }
  46. void stft(int n) {
  47. float total;
  48. for(int k=0;k<FREQUENCY_BANDS;k++) {
  49. total = 0.0f;
  50. for(int m=-halfWindowSize; m<halfWindowSize-1;m++) {
  51. total += signalBuffer[n*hopSize + m] * windowFunction[m] * std::real(exp((-J) * 2.0f * (float)M_PI * (float)m * (float)k / (float)defaultWindowSize));
  52. }
  53. X[n][k] = total;
  54. }
  55. }
  56. void transientDetection(int n) {
  57. float energy;
  58. for(int k=0;k<FREQUENCY_BANDS;k++) {
  59. }
  60. }
  61. Sabonis() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {
  62. CreateBlackmanHarrisWindow(defaultWindowSize);
  63. }
  64. void step() override;
  65. };
  66. void Sabonis::step() {
  67. float signalIn = inputs[SIGNAL_IN].value/5;
  68. float out = 0.0;
  69. outputs[TONAL_OUTPUT].value = out / 4.0;
  70. }
  71. struct SabonisWidget : ModuleWidget {
  72. SabonisWidget(Sabonis *module);
  73. };
  74. SabonisWidget::SabonisWidget(Sabonis *module) : ModuleWidget(module) {
  75. box.size = Vec(15*9, 380);
  76. {
  77. SVGPanel *panel = new SVGPanel();
  78. panel->box.size = box.size;
  79. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Sabonis.svg")));
  80. addChild(panel);
  81. }
  82. addParam(ParamWidget::create<RoundBlackKnob>(Vec(14, 84), module, Sabonis::SMOOTHENESS_PARAM, 0, 1.0, .25));
  83. addInput(Port::create<PJ301MPort>(Vec(10, 170), Port::INPUT, module, Sabonis::SIGNAL_IN));
  84. addOutput(Port::create<PJ301MPort>(Vec(10, 255), Port::OUTPUT, module, Sabonis::TRANSIENT_OUTPUT));
  85. addOutput(Port::create<PJ301MPort>(Vec(10, 305), Port::OUTPUT, module, Sabonis::TONAL_OUTPUT));
  86. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  87. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  88. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  89. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  90. }
  91. } // namespace rack_plugin_FrozenWasteland
  92. using namespace rack_plugin_FrozenWasteland;
  93. RACK_PLUGIN_MODEL_INIT(FrozenWasteland, Sabonis) {
  94. Model *modelSabonis = Model::create<Sabonis, SabonisWidget>("Frozen Wasteland", "Sabonis", "Sabonis", FILTER_TAG);
  95. return modelSabonis;
  96. }