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.

506 lines
16KB

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