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.

248 lines
8.5KB

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