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.

249 lines
8.6KB

  1. #include "NauModular.hpp"
  2. #define DEBUG_PERLIN
  3. #ifdef DEBUG_PERLIN
  4. #include <iostream>
  5. #include <limits.h>
  6. #endif
  7. #include <float.h>
  8. #define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : (((int)x)-1) )
  9. namespace rack_plugin_NauModular {
  10. struct Perlin : Module{
  11. enum ParamIds {
  12. SPEED_PARAM,
  13. SPEED_PCT_PARAM,
  14. MULT_PARAM,
  15. MULT_PCT_PARAM,
  16. WGT0_PARAM,
  17. WGT1_PARAM,
  18. WGT2_PARAM,
  19. WGT3_PARAM,
  20. NUM_PARAMS
  21. };
  22. enum InputIds {
  23. SPEED_INPUT,
  24. MULT_INPUT,
  25. NUM_INPUTS
  26. };
  27. enum OutputIds {
  28. NOISE_OUTPUT,
  29. NOISE0_OUTPUT,
  30. NOISE1_OUTPUT,
  31. NOISE2_OUTPUT,
  32. NOISE3_OUTPUT,
  33. NUM_OUTPUTS
  34. };
  35. enum LightIds {
  36. NUM_LIGHTS
  37. };
  38. Perlin() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS){
  39. noise = new float[nOctaves];
  40. }
  41. ~Perlin(){
  42. delete [] noise;
  43. }
  44. void step() override;
  45. float grad(int hash, float x);
  46. float getNoise(float x);
  47. void mixOctaves(float * nn);
  48. float getMixed(float & _val0, float & _val1, float & _mix);
  49. OutputIds octaveIndex2outputIndex(int octIdx){return OutputIds(octIdx+1);}
  50. ParamIds octaveIndex2paramIndex(int octIdx){return ParamIds(octIdx+4);}
  51. Output * getOctaveOutput(int octIdx);
  52. Param * getOctaveWeight(int octIdx);
  53. bool hasWire(InputIds _inIdx);
  54. const int nOctaves = 4;
  55. float curTime = 0.0;
  56. float minSpd = 1;
  57. float maxSpd = 500;
  58. float oldSpeedVal;
  59. float oldSpeedPctVal;
  60. float noiseOutMix;
  61. float * noise;
  62. #ifdef debug_perlin
  63. int cursmp = 0;
  64. #endif
  65. unsigned char perm[512] = {151,160,137,91,90,15,
  66. 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
  67. 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
  68. 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
  69. 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
  70. 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
  71. 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
  72. 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
  73. 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
  74. 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
  75. 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
  76. 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
  77. 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
  78. 151,160,137,91,90,15,
  79. 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
  80. 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
  81. 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
  82. 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
  83. 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
  84. 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
  85. 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
  86. 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
  87. 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
  88. 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
  89. 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
  90. 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
  91. };
  92. };
  93. Output * Perlin::getOctaveOutput(int octIdx){
  94. return &outputs[octaveIndex2outputIndex(octIdx)];
  95. }
  96. Param * Perlin::getOctaveWeight(int octIdx){
  97. return &params[octaveIndex2paramIndex(octIdx)];
  98. }
  99. bool Perlin::hasWire(InputIds _inIdx){
  100. return (inputs[_inIdx].plugLights[0].getBrightness()>0 ||
  101. inputs[_inIdx].plugLights[1].getBrightness()>0);
  102. }
  103. float Perlin::grad(int hash, float x){
  104. int h = hash & 15;
  105. float grad =1.0+(h&7);
  106. if(h&8)grad=-grad;
  107. return (grad*x);
  108. }
  109. float Perlin::getNoise(float x){
  110. int i0 = FASTFLOOR(x);
  111. int i1 = i0+1;
  112. float x0 = x-i0;
  113. float x1 = x0-1.0;
  114. float t1 = 1.0 - x1*x1;
  115. float n0;
  116. float n1;
  117. float t0 = 1.0 - x0*x0;
  118. t0 *= t0;
  119. n0 = t0*t0*grad(perm[i0 & 0xff], x0);
  120. t1 *= t1;
  121. n1 = t1*t1*grad(perm[i1 & 0xff], x1);
  122. return (0.25 * (n0+n1));
  123. }
  124. void Perlin::mixOctaves(float * nn){
  125. float totW = 0;
  126. noiseOutMix = 0;
  127. for(int i=0;i<nOctaves;i++){
  128. float nw = getOctaveWeight(i)->value;
  129. noiseOutMix += nn[i]*nw;
  130. totW += nw;
  131. }
  132. if(totW==0)totW=1.0;
  133. noiseOutMix /= totW;
  134. outputs[NOISE_OUTPUT].value = noiseOutMix;
  135. }
  136. float Perlin::getMixed(float & _val0, float & _val1, float & _mix){
  137. return ((_val0 * _mix)+(_val1 * (1.0-_mix)));
  138. }
  139. void Perlin::step(){
  140. const float maxTime = 511;//FLT_MAX-1000; <-- this needs some more love
  141. if(curTime>maxTime)curTime=0;
  142. float deltaTime = 1.0/engineGetSampleRate();
  143. curTime += deltaTime;
  144. /*
  145. auto now = std::chrono::system_clock::now();
  146. time_t t = std::chrono::system_clock::to_time_t(now);
  147. std::chrono::duration<double> s = now - std::chrono::system_clock::from_time_t(t);
  148. auto ms = s.count();
  149. auto tm = *std::localtime(&t);
  150. float timef = 60*tm.tm_min;
  151. timef += tm.tm_sec;
  152. timef += ms;
  153. curTime = timef;
  154. */
  155. float noiseSpd = params[SPEED_INPUT].value;
  156. if(inputs[SPEED_INPUT].active){
  157. float spdIn = inputs[SPEED_INPUT].value/5.0;
  158. noiseSpd = getMixed(spdIn, noiseSpd, params[SPEED_PCT_PARAM].value);
  159. }
  160. float noiseAmp = params[MULT_PARAM].value;
  161. if(inputs[MULT_INPUT].active){
  162. float ampIn = inputs[MULT_INPUT].value;
  163. noiseAmp = getMixed(ampIn, noiseAmp, params[MULT_PCT_PARAM].value);
  164. }
  165. float octMult = 1.0;
  166. for(int i=0;i<nOctaves;i++){
  167. noise[i] = noiseAmp * getNoise(curTime * noiseSpd * octMult);
  168. getOctaveOutput(i)->value = noise[i];
  169. octMult *= 2;
  170. }
  171. mixOctaves(noise);
  172. //std::cout<<"curTime: "<<curTime<<std::endl;
  173. }
  174. struct PerlinWidget : ModuleWidget{
  175. PerlinWidget(Perlin *module);
  176. };
  177. PerlinWidget::PerlinWidget(Perlin *module) : ModuleWidget(module){
  178. box.size = Vec(6 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
  179. {
  180. SVGPanel *panel = new SVGPanel();
  181. panel->box.size = box.size;
  182. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Perlin.svg")));
  183. addChild(panel);
  184. }
  185. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  186. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)));
  187. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  188. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)));
  189. float startSpd = (module->maxSpd-module->minSpd)/2 + module->minSpd;
  190. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(10, 83), module, Perlin::SPEED_PARAM, module->minSpd, module->maxSpd, startSpd));
  191. addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(55, 100), module, Perlin::SPEED_PCT_PARAM, 0.0, 1.0, 0.5));
  192. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(10, 150), module, Perlin::MULT_PARAM, 1.0, 10.0, 1.0));
  193. addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(55, 167), module, Perlin::MULT_PCT_PARAM, 0.0, 1.0, 0.5));
  194. addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(15, 205), module, Perlin::WGT0_PARAM, 0.0,1.0,0.25));
  195. addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(50, 205), module, Perlin::WGT1_PARAM, 0.0,1.0,0.25));
  196. addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(15, 235), module, Perlin::WGT2_PARAM, 0.0,1.0,0.25));
  197. addParam(ParamWidget::create<RoundSmallBlackKnob>(Vec(50, 235), module, Perlin::WGT3_PARAM, 0.0,1.0,0.25));
  198. addInput(Port::create<PJ301MPort>(Vec(55, 75), Port::INPUT, module, Perlin::SPEED_INPUT));
  199. addInput(Port::create<PJ301MPort>(Vec(55, 140), Port::INPUT, module, Perlin::MULT_INPUT));
  200. addOutput(Port::create<PJ301MPort>(Vec(17, 270), Port::OUTPUT, module, Perlin::NOISE0_OUTPUT));
  201. addOutput(Port::create<PJ301MPort>(Vec(45, 270), Port::OUTPUT, module, Perlin::NOISE1_OUTPUT));
  202. addOutput(Port::create<PJ301MPort>(Vec(17, 295), Port::OUTPUT, module, Perlin::NOISE2_OUTPUT));
  203. addOutput(Port::create<PJ301MPort>(Vec(45, 295), Port::OUTPUT, module, Perlin::NOISE3_OUTPUT));
  204. addOutput(Port::create<PJ301MPort>(Vec(33, 320), Port::OUTPUT, module, Perlin::NOISE_OUTPUT));
  205. }
  206. } // namespace rack_plugin_NauModular
  207. using namespace rack_plugin_NauModular;
  208. RACK_PLUGIN_MODEL_INIT(NauModular, Perlin) {
  209. Model *modelPerlin = Model::create<Perlin, PerlinWidget>("NauModular", "Perlin", "Perlin", NOISE_TAG);
  210. return modelPerlin;
  211. }