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.

473 lines
15KB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include <math.h>
  5. #include <vector>
  6. #include <algorithm>
  7. #include <chrono>
  8. #include <thread>
  9. #include <xmmintrin.h>
  10. #include <pmmintrin.h>
  11. #include "global_pre.hpp"
  12. #include "app.hpp"
  13. #include "engine.hpp"
  14. #include "plugin.hpp"
  15. #include "window.hpp"
  16. #include "global.hpp"
  17. #include "global_ui.hpp"
  18. namespace rack {
  19. float Light::getBrightness() {
  20. // LEDs are diodes, so don't allow reverse current.
  21. // For some reason, instead of the RMS, the sqrt of RMS looks better
  22. return powf(fmaxf(0.f, value), 0.25f);
  23. }
  24. void Light::setBrightnessSmooth(float brightness, float frames) {
  25. float v = (brightness > 0.f) ? brightness * brightness : 0.f;
  26. if (v < value) {
  27. // Fade out light with lambda = framerate
  28. value += (v - value) * global->engine.sampleTime * frames * 60.f;
  29. }
  30. else {
  31. // Immediately illuminate light
  32. value = v;
  33. }
  34. }
  35. void Wire::step() {
  36. float value = outputModule->outputs[outputId].value;
  37. inputModule->inputs[inputId].value = value;
  38. }
  39. void engineInit() {
  40. engineSetSampleRate(44100.0);
  41. }
  42. void engineDestroy() {
  43. // Make sure there are no wires or modules in the rack on destruction. This suggests that a module failed to remove itself before the WINDOW was destroyed.
  44. assert(global->gWires.empty());
  45. assert(global->gModules.empty());
  46. }
  47. static void engineStep() {
  48. // Param interpolation
  49. if (global->engine.smoothModule) {
  50. float value = global->engine.smoothModule->params[global->engine.smoothParamId].value;
  51. const float lambda = 60.0; // decay rate is 1 graphics frame
  52. float delta = global->engine.smoothValue - value;
  53. float newValue = value + delta * lambda * global->engine.sampleTime;
  54. if (value == newValue) {
  55. // Snap to actual smooth value if the value doesn't change enough (due to the granularity of floats)
  56. global->engine.smoothModule->params[global->engine.smoothParamId].value = global->engine.smoothValue;
  57. global->engine.smoothModule = NULL;
  58. }
  59. else {
  60. global->engine.smoothModule->params[global->engine.smoothParamId].value = newValue;
  61. }
  62. }
  63. // Step modules
  64. for (Module *module : global->gModules) {
  65. std::chrono::high_resolution_clock::time_point startTime;
  66. if (global->gPowerMeter) {
  67. startTime = std::chrono::high_resolution_clock::now();
  68. module->step();
  69. auto stopTime = std::chrono::high_resolution_clock::now();
  70. float cpuTime = std::chrono::duration<float>(stopTime - startTime).count() * global->engine.sampleRate;
  71. module->cpuTime += (cpuTime - module->cpuTime) * global->engine.sampleTime / 0.5f;
  72. }
  73. else {
  74. module->step();
  75. }
  76. // Step ports
  77. for (Input &input : module->inputs) {
  78. if (input.active) {
  79. float value = input.value / 5.f;
  80. input.plugLights[0].setBrightnessSmooth(value);
  81. input.plugLights[1].setBrightnessSmooth(-value);
  82. }
  83. }
  84. for (Output &output : module->outputs) {
  85. if (output.active) {
  86. float value = output.value / 5.f;
  87. output.plugLights[0].setBrightnessSmooth(value);
  88. output.plugLights[1].setBrightnessSmooth(-value);
  89. }
  90. }
  91. }
  92. // Step cables by moving their output values to inputs
  93. for (Wire *wire : global->gWires) {
  94. wire->step();
  95. }
  96. }
  97. static void engineRun() {
  98. #ifdef _MSC_VER
  99. // Set CPU to flush-to-zero (FTZ) and denormals-are-zero (DAZ) mode
  100. // https://software.intel.com/en-us/node/682949
  101. _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
  102. _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
  103. #endif // _MSC_VER
  104. // Every time the engine waits and locks a mutex, it steps this many frames
  105. const int mutexSteps = 64;
  106. // Time in seconds that the engine is rushing ahead of the estimated clock time
  107. double ahead = 0.0;
  108. auto lastTime = std::chrono::high_resolution_clock::now();
  109. while (global->engine.running) {
  110. global->engine.vipMutex.wait();
  111. if (!global->gPaused) {
  112. std::lock_guard<std::mutex> lock(global->engine.mutex);
  113. for (int i = 0; i < mutexSteps; i++) {
  114. engineStep();
  115. }
  116. }
  117. double stepTime = mutexSteps * global->engine.sampleTime;
  118. ahead += stepTime;
  119. auto currTime = std::chrono::high_resolution_clock::now();
  120. const double aheadFactor = 2.0;
  121. ahead -= aheadFactor * std::chrono::duration<double>(currTime - lastTime).count();
  122. lastTime = currTime;
  123. ahead = fmaxf(ahead, 0.0);
  124. // Avoid pegging the CPU at 100% when there are no "blocking" modules like AudioInterface, but still step audio at a reasonable rate
  125. // The number of steps to wait before possibly sleeping
  126. const double aheadMax = 1.0; // seconds
  127. if (ahead > aheadMax) {
  128. std::this_thread::sleep_for(std::chrono::duration<double>(stepTime));
  129. }
  130. }
  131. }
  132. void engineStart() {
  133. global->engine.running = true;
  134. global->engine.thread = std::thread(engineRun);
  135. }
  136. void engineStop() {
  137. global->engine.running = false;
  138. global->engine.thread.join();
  139. }
  140. void engineAddModule(Module *module) {
  141. assert(module);
  142. VIPLock vipLock(global->engine.vipMutex);
  143. std::lock_guard<std::mutex> lock(global->engine.mutex);
  144. // Check that the module is not already added
  145. auto it = std::find(global->gModules.begin(), global->gModules.end(), module);
  146. assert(it == global->gModules.end());
  147. global->gModules.push_back(module);
  148. #ifdef USE_VST2
  149. module->vst2_unique_param_base_id = global->vst2.next_unique_param_base_id;
  150. global->vst2.next_unique_param_base_id += module->params.size() + 1;
  151. #endif // USE_VST2
  152. }
  153. void engineRemoveModule(Module *module) {
  154. assert(module);
  155. VIPLock vipLock(global->engine.vipMutex);
  156. std::lock_guard<std::mutex> lock(global->engine.mutex);
  157. // If a param is being smoothed on this module, stop smoothing it immediately
  158. if (module == global->engine.smoothModule) {
  159. global->engine.smoothModule = NULL;
  160. }
  161. // Check that all wires are disconnected
  162. for (Wire *wire : global->gWires) {
  163. assert(wire->outputModule != module);
  164. assert(wire->inputModule != module);
  165. }
  166. // Check that the module actually exists
  167. auto it = std::find(global->gModules.begin(), global->gModules.end(), module);
  168. assert(it != global->gModules.end());
  169. // Remove it
  170. global->gModules.erase(it);
  171. }
  172. static void updateActive() {
  173. // Set everything to inactive
  174. for (Module *module : global->gModules) {
  175. for (Input &input : module->inputs) {
  176. input.active = false;
  177. }
  178. for (Output &output : module->outputs) {
  179. output.active = false;
  180. }
  181. }
  182. // Set inputs/outputs to active
  183. for (Wire *wire : global->gWires) {
  184. wire->outputModule->outputs[wire->outputId].active = true;
  185. wire->inputModule->inputs[wire->inputId].active = true;
  186. }
  187. }
  188. void engineAddWire(Wire *wire) {
  189. assert(wire);
  190. VIPLock vipLock(global->engine.vipMutex);
  191. std::lock_guard<std::mutex> lock(global->engine.mutex);
  192. // Check wire properties
  193. assert(wire->outputModule);
  194. assert(wire->inputModule);
  195. // Check that the wire is not already added, and that the input is not already used by another cable
  196. for (Wire *wire2 : global->gWires) {
  197. assert(wire2 != wire);
  198. assert(!(wire2->inputModule == wire->inputModule && wire2->inputId == wire->inputId));
  199. }
  200. // Add the wire
  201. global->gWires.push_back(wire);
  202. updateActive();
  203. }
  204. void engineRemoveWire(Wire *wire) {
  205. assert(wire);
  206. VIPLock vipLock(global->engine.vipMutex);
  207. std::lock_guard<std::mutex> lock(global->engine.mutex);
  208. // Check that the wire is already added
  209. auto it = std::find(global->gWires.begin(), global->gWires.end(), wire);
  210. assert(it != global->gWires.end());
  211. // Set input to 0V
  212. wire->inputModule->inputs[wire->inputId].value = 0.0;
  213. // Remove the wire
  214. global->gWires.erase(it);
  215. updateActive();
  216. }
  217. #ifdef USE_VST2
  218. static int loc_vst2_find_unique_param_by_module_and_paramid(Module *module, int paramId) {
  219. return module->vst2_unique_param_base_id + paramId;
  220. }
  221. static bool loc_vst2_find_module_and_paramid_by_unique_paramid(int uniqueParamId, Module**retModule, int *retParamId) {
  222. if(uniqueParamId >= 0)
  223. {
  224. if(uniqueParamId < VST2_MAX_UNIQUE_PARAM_IDS)
  225. {
  226. // (todo) speed this up with a hashtable
  227. for(Module *module : global->gModules) {
  228. if( (uniqueParamId >= module->vst2_unique_param_base_id) &&
  229. (uniqueParamId < (module->vst2_unique_param_base_id + module->params.size()))
  230. )
  231. {
  232. *retParamId = (uniqueParamId - module->vst2_unique_param_base_id);
  233. *retModule = module;
  234. return true;
  235. }
  236. }
  237. }
  238. }
  239. return false;
  240. }
  241. #endif // USE_VST2
  242. #ifdef USE_VST2
  243. void engineSetParam(Module *module, int paramId, float value, bool bVSTAutomate) {
  244. #else
  245. void engineSetParam(Module *module, int paramId, float value) {
  246. #endif
  247. if(module->params[paramId].value == value)
  248. return;
  249. module->params[paramId].value = value;
  250. #ifdef USE_VST2
  251. if(bVSTAutomate && !global->vst2.b_patch_loading)
  252. {
  253. // (note) [bsp] this is usually called from the UI thread (see ParamWidget.cpp)
  254. // (note) [bsp] VST requires all parameters to be in the normalized 0..1 range
  255. // (note) [bsp] VCV Rack parameters however are arbitrary floats
  256. // printf("xxx vcvrack: paramId=%d value=%f (=> %f)\n", paramId, value, normValue);
  257. int uniqueParamId = loc_vst2_find_unique_param_by_module_and_paramid(module, paramId);
  258. if(-1 != uniqueParamId)
  259. {
  260. ModuleWidget *moduleWidget = global_ui->app.gRackWidget->findModuleWidgetByModule(module);
  261. if(NULL != moduleWidget)
  262. {
  263. // Find
  264. ParamWidget *paramWidget = moduleWidget->findParamWidgetByParamId(paramId);
  265. if(NULL != paramWidget)
  266. {
  267. if(isfinite(paramWidget->minValue) && isfinite(paramWidget->maxValue))
  268. {
  269. // Normalize parameter
  270. float paramRange = (paramWidget->maxValue - paramWidget->minValue);
  271. if(paramRange > 0.0f)
  272. {
  273. float normValue = (value - paramWidget->minValue) / paramRange;
  274. // printf("xxx paramId=%d normValue=%f\n", paramId, normValue);
  275. // Call host audioMasterAutomate
  276. vst2_handle_ui_param(uniqueParamId, normValue);
  277. }
  278. }
  279. }
  280. }
  281. }
  282. }
  283. #endif // USE_VST2
  284. }
  285. #ifdef USE_VST2
  286. }
  287. using namespace rack;
  288. void vst2_queue_param(int uniqueParamId, float value, bool bNormalized) {
  289. // Called from any thread via setParameter()
  290. // (note) protected by caller mutex
  291. VST2QueuedParam qp;
  292. qp.unique_id = uniqueParamId;
  293. qp.value = value;
  294. qp.b_normalized = bNormalized;
  295. global->vst2.queued_params.push_back(qp);
  296. }
  297. void vst2_handle_queued_params(void) {
  298. // Called in processReplacing()
  299. // (note) protected by caller mutex
  300. if(global->vst2.queued_params.size() > 0)
  301. {
  302. global_ui->app.mtx_param.lock();
  303. for(VST2QueuedParam qp : global->vst2.queued_params)
  304. {
  305. Module *module;
  306. int paramId;
  307. if(loc_vst2_find_module_and_paramid_by_unique_paramid(qp.unique_id, &module, &paramId))
  308. {
  309. ModuleWidget *moduleWidget = global_ui->app.gRackWidget->findModuleWidgetByModule(module);
  310. if(NULL != moduleWidget)
  311. {
  312. // Find
  313. ParamWidget *paramWidget = moduleWidget->findParamWidgetByParamId(paramId);
  314. if(NULL != paramWidget)
  315. {
  316. if(isfinite(paramWidget->minValue) && isfinite(paramWidget->maxValue))
  317. {
  318. if(qp.b_normalized)
  319. {
  320. // De-Normalize parameter
  321. global_ui->param_info.b_lock = true;
  322. float paramRange = (paramWidget->maxValue - paramWidget->minValue);
  323. if(paramRange > 0.0f)
  324. {
  325. float value = (qp.value * paramRange) + paramWidget->minValue;
  326. engineSetParam(module, paramId, value, false/*bVSTAutomate*/);
  327. // Update UI widget
  328. paramWidget->setValue(value);
  329. }
  330. global_ui->param_info.b_lock = false;
  331. }
  332. else
  333. {
  334. float value = qp.value;
  335. if(value < paramWidget->minValue)
  336. value = paramWidget->minValue;
  337. else if(value > paramWidget->maxValue)
  338. value = paramWidget->maxValue;
  339. engineSetParam(module, paramId, value, false/*bVSTAutomate*/);
  340. // Update UI widget
  341. paramWidget->setValue(qp.value);
  342. }
  343. }
  344. }
  345. }
  346. }
  347. }
  348. global->vst2.queued_params.clear();
  349. global_ui->app.mtx_param.unlock();
  350. }
  351. }
  352. float vst2_get_param(int uniqueParamId) {
  353. Module *module;
  354. int paramId;
  355. if(loc_vst2_find_module_and_paramid_by_unique_paramid(uniqueParamId, &module, &paramId))
  356. {
  357. if(sUI(paramId) < sUI(module->params.size())) // paranoia
  358. {
  359. return module->params[paramId].value;
  360. }
  361. }
  362. return 0.0f;
  363. }
  364. void vst2_get_param_name (int uniqueParamId, char *s, int sMaxLen) {
  365. Module *module;
  366. int paramId;
  367. if(loc_vst2_find_module_and_paramid_by_unique_paramid(uniqueParamId, &module, &paramId))
  368. {
  369. if(sUI(paramId) < sUI(module->params.size())) // paranoia
  370. {
  371. // (note) VCV params do not have names
  372. ::snprintf(s, sMaxLen, "%4d: <param>", uniqueParamId);
  373. return;
  374. }
  375. }
  376. ::snprintf(s, sMaxLen, "%4d: -", uniqueParamId);
  377. }
  378. namespace rack {
  379. #endif // USE_VST2
  380. void engineSetParamSmooth(Module *module, int paramId, float value) {
  381. VIPLock vipLock(global->engine.vipMutex);
  382. std::lock_guard<std::mutex> lock(global->engine.mutex);
  383. // Since only one param can be smoothed at a time, if another param is currently being smoothed, skip to its final state
  384. if (global->engine.smoothModule && !(global->engine.smoothModule == module && global->engine.smoothParamId == paramId)) {
  385. global->engine.smoothModule->params[global->engine.smoothParamId].value = global->engine.smoothValue;
  386. }
  387. global->engine.smoothModule = module;
  388. global->engine.smoothParamId = paramId;
  389. global->engine.smoothValue = value;
  390. }
  391. void engineSetSampleRate(float newSampleRate) {
  392. VIPLock vipLock(global->engine.vipMutex);
  393. std::lock_guard<std::mutex> lock(global->engine.mutex);
  394. global->engine.sampleRate = newSampleRate;
  395. global->engine.sampleTime = 1.0 / global->engine.sampleRate;
  396. // onSampleRateChange
  397. for (Module *module : global->gModules) {
  398. module->onSampleRateChange();
  399. }
  400. }
  401. float engineGetSampleRate() {
  402. return global->engine.sampleRate;
  403. }
  404. float engineGetSampleTime() {
  405. return global->engine.sampleTime;
  406. }
  407. } // namespace rack
  408. #ifdef USE_VST2
  409. using namespace rack;
  410. void vst2_set_samplerate(sF32 _rate) {
  411. rack::engineSetSampleRate(_rate);
  412. }
  413. void vst2_engine_process(float *const*_in, float **_out, unsigned int _numFrames) {
  414. global->vst2.inputs = _in;
  415. global->vst2.outputs = _out;
  416. for(global->vst2.frame_idx = 0u; global->vst2.frame_idx < _numFrames; global->vst2.frame_idx++)
  417. {
  418. engineStep();
  419. }
  420. }
  421. #endif // USE_VST2