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.

635 lines
16KB

  1. #include "engine/Engine.hpp"
  2. #include "settings.hpp"
  3. #include "system.hpp"
  4. #include "random.hpp"
  5. #include <algorithm>
  6. #include <chrono>
  7. #include <thread>
  8. #include <condition_variable>
  9. #include <mutex>
  10. #include <atomic>
  11. #include <xmmintrin.h>
  12. #include <pmmintrin.h>
  13. namespace rack {
  14. namespace engine {
  15. /** Threads which obtain a VIPLock will cause wait() to block for other less important threads.
  16. This does not provide the VIPs with an exclusive lock. That should be left up to another mutex shared between the less important thread.
  17. */
  18. struct VIPMutex {
  19. int count = 0;
  20. std::condition_variable cv;
  21. std::mutex countMutex;
  22. /** Blocks until there are no remaining VIPLocks */
  23. void wait() {
  24. std::unique_lock<std::mutex> lock(countMutex);
  25. while (count > 0)
  26. cv.wait(lock);
  27. }
  28. };
  29. struct VIPLock {
  30. VIPMutex &m;
  31. VIPLock(VIPMutex &m) : m(m) {
  32. std::unique_lock<std::mutex> lock(m.countMutex);
  33. m.count++;
  34. }
  35. ~VIPLock() {
  36. std::unique_lock<std::mutex> lock(m.countMutex);
  37. m.count--;
  38. lock.unlock();
  39. m.cv.notify_all();
  40. }
  41. };
  42. struct Barrier {
  43. std::mutex mutex;
  44. std::condition_variable cv;
  45. int count = 0;
  46. int total = 0;
  47. void wait() {
  48. // Waiting on one thread is trivial.
  49. if (total <= 1)
  50. return;
  51. std::unique_lock<std::mutex> lock(mutex);
  52. count++;
  53. if (count < total) {
  54. cv.wait(lock);
  55. }
  56. else {
  57. count = 0;
  58. cv.notify_all();
  59. }
  60. }
  61. };
  62. struct SpinBarrier {
  63. std::atomic<int> count;
  64. int total = 0;
  65. SpinBarrier() {
  66. count = 0;
  67. }
  68. void wait() {
  69. count++;
  70. if (count < total) {
  71. while (count > 0) {}
  72. }
  73. else {
  74. count = 0;
  75. }
  76. }
  77. };
  78. struct EngineWorker {
  79. Engine *engine;
  80. int id;
  81. std::thread thread;
  82. bool running = true;
  83. void start() {
  84. thread = std::thread([&] {
  85. run();
  86. });
  87. }
  88. void stop() {
  89. running = false;
  90. }
  91. void join() {
  92. thread.join();
  93. }
  94. void run() {
  95. system::setThreadName("Engine worker");
  96. system::setThreadRealTime();
  97. while (running) {
  98. step();
  99. }
  100. }
  101. void step();
  102. };
  103. struct Engine::Internal {
  104. std::vector<Module*> modules;
  105. std::vector<Cable*> cables;
  106. std::vector<ModuleHandle*> moduleHandles;
  107. bool paused = false;
  108. bool running = false;
  109. float sampleRate;
  110. float sampleTime;
  111. int nextModuleId = 0;
  112. int nextCableId = 0;
  113. // Parameter smoothing
  114. Module *smoothModule = NULL;
  115. int smoothParamId;
  116. float smoothValue;
  117. std::recursive_mutex mutex;
  118. std::thread thread;
  119. VIPMutex vipMutex;
  120. int threadCount = 1;
  121. std::vector<EngineWorker> workers;
  122. SpinBarrier engineBarrier;
  123. SpinBarrier workerBarrier;
  124. Module *touchedModule = NULL;
  125. int touchedParamId = 0;
  126. };
  127. Engine::Engine() {
  128. internal = new Internal;
  129. internal->engineBarrier.total = 1;
  130. internal->workerBarrier.total = 1;
  131. setSampleRate(44100.f);
  132. setThreadCount(settings.threadCount);
  133. }
  134. Engine::~Engine() {
  135. settings.sampleRate = internal->sampleRate;
  136. settings.threadCount = internal->threadCount;
  137. // Stop worker threads
  138. setThreadCount(1);
  139. // Make sure there are no cables or modules in the rack on destruction.
  140. // If this happens, a module must have failed to remove itself before the RackWidget was destroyed.
  141. assert(internal->cables.empty());
  142. assert(internal->modules.empty());
  143. assert(internal->moduleHandles.empty());
  144. delete internal;
  145. }
  146. static void Engine_stepModules(Engine *engine, int threadId) {
  147. Engine::Internal *internal = engine->internal;
  148. int threadCount = internal->threadCount;
  149. int modulesLen = internal->modules.size();
  150. // TODO
  151. // There's room for optimization here by choosing modules intelligently rather than fixed strides.
  152. // See OpenMP's `guided` scheduling algorithm.
  153. // Step each module
  154. for (int i = threadId; i < modulesLen; i += threadCount) {
  155. Module *module = internal->modules[i];
  156. if (!module->bypass) {
  157. // Step module
  158. if (settings.cpuMeter) {
  159. auto startTime = std::chrono::high_resolution_clock::now();
  160. module->step();
  161. auto stopTime = std::chrono::high_resolution_clock::now();
  162. float cpuTime = std::chrono::duration<float>(stopTime - startTime).count();
  163. // Smooth CPU time
  164. const float cpuTau = 2.f /* seconds */;
  165. module->cpuTime += (cpuTime - module->cpuTime) * internal->sampleTime / cpuTau;
  166. }
  167. else {
  168. module->step();
  169. }
  170. }
  171. // Iterate ports to step plug lights
  172. for (Input &input : module->inputs) {
  173. input.step();
  174. }
  175. for (Output &output : module->outputs) {
  176. output.step();
  177. }
  178. }
  179. }
  180. static void Engine_step(Engine *engine) {
  181. Engine::Internal *internal = engine->internal;
  182. // Param smoothing
  183. Module *smoothModule = internal->smoothModule;
  184. int smoothParamId = internal->smoothParamId;
  185. float smoothValue = internal->smoothValue;
  186. if (smoothModule) {
  187. Param *param = &smoothModule->params[smoothParamId];
  188. float value = param->value;
  189. // decay rate is 1 graphics frame
  190. const float smoothLambda = 60.f;
  191. float newValue = value + (smoothValue - value) * smoothLambda * internal->sampleTime;
  192. if (value == newValue || !(param->minValue <= newValue && newValue <= param->maxValue)) {
  193. // Snap to actual smooth value if the value doesn't change enough (due to the granularity of floats), or if newValue is out of bounds
  194. param->setValue(smoothValue);
  195. internal->smoothModule = NULL;
  196. internal->smoothParamId = 0;
  197. }
  198. else {
  199. param->value = newValue;
  200. }
  201. }
  202. // Step modules along with workers
  203. internal->engineBarrier.wait();
  204. Engine_stepModules(engine, 0);
  205. internal->workerBarrier.wait();
  206. // Step cables
  207. for (Cable *cable : engine->internal->cables) {
  208. cable->step();
  209. }
  210. }
  211. static void Engine_run(Engine *engine) {
  212. // Set up thread
  213. system::setThreadName("Engine");
  214. system::setThreadRealTime();
  215. // Set CPU to flush-to-zero (FTZ) and denormals-are-zero (DAZ) mode
  216. // https://software.intel.com/en-us/node/682949
  217. _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
  218. _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
  219. // Every time the engine waits and locks a mutex, it steps this many frames
  220. const int mutexSteps = 64;
  221. // Time in seconds that the engine is rushing ahead of the estimated clock time
  222. double ahead = 0.0;
  223. auto lastTime = std::chrono::high_resolution_clock::now();
  224. while (engine->internal->running) {
  225. engine->internal->vipMutex.wait();
  226. if (!engine->internal->paused) {
  227. std::lock_guard<std::recursive_mutex> lock(engine->internal->mutex);
  228. // auto startTime = std::chrono::high_resolution_clock::now();
  229. for (int i = 0; i < mutexSteps; i++) {
  230. Engine_step(engine);
  231. }
  232. // auto stopTime = std::chrono::high_resolution_clock::now();
  233. // float cpuTime = std::chrono::duration<float>(stopTime - startTime).count();
  234. // DEBUG("%g", cpuTime / mutexSteps * 44100);
  235. }
  236. double stepTime = mutexSteps * engine->internal->sampleTime;
  237. ahead += stepTime;
  238. auto currTime = std::chrono::high_resolution_clock::now();
  239. const double aheadFactor = 2.0;
  240. ahead -= aheadFactor * std::chrono::duration<double>(currTime - lastTime).count();
  241. lastTime = currTime;
  242. ahead = std::fmax(ahead, 0.0);
  243. // Avoid pegging the CPU at 100% when there are no "blocking" modules like AudioInterface, but still step audio at a reasonable rate
  244. // The number of steps to wait before possibly sleeping
  245. const double aheadMax = 1.0; // seconds
  246. if (ahead > aheadMax) {
  247. std::this_thread::sleep_for(std::chrono::duration<double>(stepTime));
  248. }
  249. }
  250. }
  251. void Engine::start() {
  252. internal->running = true;
  253. internal->thread = std::thread(Engine_run, this);
  254. }
  255. void Engine::stop() {
  256. internal->running = false;
  257. internal->thread.join();
  258. }
  259. void Engine::setThreadCount(int threadCount) {
  260. assert(1 <= threadCount);
  261. VIPLock vipLock(internal->vipMutex);
  262. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  263. // Stop all workers
  264. for (EngineWorker &worker : internal->workers) {
  265. worker.stop();
  266. }
  267. internal->engineBarrier.wait();
  268. // Destroy all workers
  269. for (EngineWorker &worker : internal->workers) {
  270. worker.join();
  271. }
  272. internal->workers.resize(0);
  273. // Set barrier counts
  274. internal->threadCount = threadCount;
  275. internal->engineBarrier.total = threadCount;
  276. internal->workerBarrier.total = threadCount;
  277. // Create workers
  278. internal->workers.resize(threadCount - 1);
  279. for (int id = 1; id < threadCount; id++) {
  280. EngineWorker &worker = internal->workers[id - 1];
  281. worker.id = id;
  282. worker.engine = this;
  283. worker.start();
  284. }
  285. }
  286. int Engine::getThreadCount() {
  287. // No lock
  288. return internal->threadCount;
  289. }
  290. void Engine::setPaused(bool paused) {
  291. VIPLock vipLock(internal->vipMutex);
  292. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  293. internal->paused = paused;
  294. }
  295. bool Engine::isPaused() {
  296. // No lock
  297. return internal->paused;
  298. }
  299. void Engine::setSampleRate(float sampleRate) {
  300. VIPLock vipLock(internal->vipMutex);
  301. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  302. internal->sampleRate = sampleRate;
  303. internal->sampleTime = 1 / sampleRate;
  304. for (Module *module : internal->modules) {
  305. module->onSampleRateChange();
  306. }
  307. }
  308. float Engine::getSampleRate() {
  309. return internal->sampleRate;
  310. }
  311. float Engine::getSampleTime() {
  312. return internal->sampleTime;
  313. }
  314. void Engine::addModule(Module *module) {
  315. assert(module);
  316. VIPLock vipLock(internal->vipMutex);
  317. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  318. // Check that the module is not already added
  319. auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
  320. assert(it == internal->modules.end());
  321. // Set ID
  322. if (module->id < 0) {
  323. // Automatically assign ID
  324. module->id = internal->nextModuleId++;
  325. }
  326. else {
  327. // Manual ID
  328. // Check that the ID is not already taken
  329. for (Module *m : internal->modules) {
  330. assert(module->id != m->id);
  331. }
  332. if (module->id >= internal->nextModuleId) {
  333. internal->nextModuleId = module->id + 1;
  334. }
  335. }
  336. // Update ModuleHandle
  337. for (ModuleHandle *moduleHandle : internal->moduleHandles) {
  338. if (moduleHandle->id == module->id)
  339. moduleHandle->module = module;
  340. }
  341. // Add module
  342. internal->modules.push_back(module);
  343. }
  344. void Engine::removeModule(Module *module) {
  345. assert(module);
  346. VIPLock vipLock(internal->vipMutex);
  347. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  348. // If a param is being smoothed on this module, stop smoothing it immediately
  349. if (module == internal->smoothModule) {
  350. internal->smoothModule = NULL;
  351. }
  352. // Check that all cables are disconnected
  353. for (Cable *cable : internal->cables) {
  354. assert(cable->outputModule != module);
  355. assert(cable->inputModule != module);
  356. }
  357. // Remove touched param
  358. if (internal->touchedModule == module) {
  359. internal->touchedModule = NULL;
  360. internal->touchedParamId = 0;
  361. }
  362. // Update ModuleHandle
  363. for (ModuleHandle *moduleHandle : internal->moduleHandles) {
  364. if (moduleHandle->id == module->id)
  365. moduleHandle->module = NULL;
  366. }
  367. // Check that the module actually exists
  368. auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
  369. assert(it != internal->modules.end());
  370. // Remove the module
  371. internal->modules.erase(it);
  372. }
  373. Module *Engine::getModule(int moduleId) {
  374. VIPLock vipLock(internal->vipMutex);
  375. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  376. // Find module
  377. for (Module *module : internal->modules) {
  378. if (module->id == moduleId)
  379. return module;
  380. }
  381. return NULL;
  382. }
  383. void Engine::resetModule(Module *module) {
  384. assert(module);
  385. VIPLock vipLock(internal->vipMutex);
  386. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  387. module->reset();
  388. }
  389. void Engine::randomizeModule(Module *module) {
  390. assert(module);
  391. VIPLock vipLock(internal->vipMutex);
  392. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  393. module->randomize();
  394. }
  395. void Engine::bypassModule(Module *module, bool bypass) {
  396. assert(module);
  397. VIPLock vipLock(internal->vipMutex);
  398. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  399. if (bypass) {
  400. for (Output &output : module->outputs) {
  401. // This also zeros all voltages
  402. output.setChannels(0);
  403. }
  404. module->cpuTime = 0.f;
  405. }
  406. else {
  407. // Set all outputs to 1 channel
  408. for (Output &output : module->outputs) {
  409. output.setChannels(1);
  410. }
  411. }
  412. module->bypass = bypass;
  413. }
  414. static void Engine_updateConnected(Engine *engine) {
  415. // Set everything to unconnected
  416. for (Module *module : engine->internal->modules) {
  417. for (Input &input : module->inputs) {
  418. input.active = false;
  419. }
  420. for (Output &output : module->outputs) {
  421. output.active = false;
  422. }
  423. }
  424. // Set inputs/outputs to active
  425. for (Cable *cable : engine->internal->cables) {
  426. cable->outputModule->outputs[cable->outputId].active = true;
  427. cable->inputModule->inputs[cable->inputId].active = true;
  428. }
  429. }
  430. void Engine::addCable(Cable *cable) {
  431. assert(cable);
  432. VIPLock vipLock(internal->vipMutex);
  433. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  434. // Check cable properties
  435. assert(cable->outputModule);
  436. assert(cable->inputModule);
  437. // Check that the cable is not already added, and that the input is not already used by another cable
  438. for (Cable *cable2 : internal->cables) {
  439. assert(cable2 != cable);
  440. assert(!(cable2->inputModule == cable->inputModule && cable2->inputId == cable->inputId));
  441. }
  442. // Set ID
  443. if (cable->id < 0) {
  444. // Automatically assign ID
  445. cable->id = internal->nextCableId++;
  446. }
  447. else {
  448. // Manual ID
  449. // Check that the ID is not already taken
  450. for (Cable *w : internal->cables) {
  451. assert(cable->id != w->id);
  452. }
  453. if (cable->id >= internal->nextCableId) {
  454. internal->nextCableId = cable->id + 1;
  455. }
  456. }
  457. // Add the cable
  458. internal->cables.push_back(cable);
  459. Engine_updateConnected(this);
  460. }
  461. void Engine::removeCable(Cable *cable) {
  462. assert(cable);
  463. VIPLock vipLock(internal->vipMutex);
  464. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  465. // Check that the cable is already added
  466. auto it = std::find(internal->cables.begin(), internal->cables.end(), cable);
  467. assert(it != internal->cables.end());
  468. // Set input to inactive
  469. Input &input = cable->inputModule->inputs[cable->inputId];
  470. input.setChannels(0);
  471. // Remove the cable
  472. internal->cables.erase(it);
  473. Engine_updateConnected(this);
  474. }
  475. void Engine::setParam(Module *module, int paramId, float value) {
  476. // TODO Does this need to be thread-safe?
  477. // If being smoothed, cancel smoothing
  478. if (internal->smoothModule == module && internal->smoothParamId == paramId) {
  479. internal->smoothModule = NULL;
  480. internal->smoothParamId = 0;
  481. }
  482. module->params[paramId].value = value;
  483. }
  484. float Engine::getParam(Module *module, int paramId) {
  485. return module->params[paramId].value;
  486. }
  487. void Engine::setSmoothParam(Module *module, int paramId, float value) {
  488. // If another param is being smoothed, jump value
  489. if (internal->smoothModule && !(internal->smoothModule == module && internal->smoothParamId == paramId)) {
  490. internal->smoothModule->params[internal->smoothParamId].value = internal->smoothValue;
  491. }
  492. internal->smoothParamId = paramId;
  493. internal->smoothValue = value;
  494. // Set this last so the above values are valid as soon as it is set
  495. internal->smoothModule = module;
  496. }
  497. float Engine::getSmoothParam(Module *module, int paramId) {
  498. if (internal->smoothModule == module && internal->smoothParamId == paramId)
  499. return internal->smoothValue;
  500. return getParam(module, paramId);
  501. }
  502. void Engine::setTouchedParam(Module *module, int paramId) {
  503. internal->touchedModule = module;
  504. internal->touchedParamId = paramId;
  505. }
  506. void Engine::getTouchedParam(Module *&module, int &paramId) {
  507. module = internal->touchedModule;
  508. paramId = internal->touchedParamId;
  509. }
  510. void Engine::addModuleHandle(ModuleHandle *moduleHandle) {
  511. VIPLock vipLock(internal->vipMutex);
  512. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  513. // Check that the ModuleHandle is not already added
  514. auto it = std::find(internal->moduleHandles.begin(), internal->moduleHandles.end(), moduleHandle);
  515. assert(it == internal->moduleHandles.end());
  516. moduleHandle->module = getModule(moduleHandle->id);
  517. internal->moduleHandles.push_back(moduleHandle);
  518. }
  519. void Engine::removeModuleHandle(ModuleHandle *moduleHandle) {
  520. VIPLock vipLock(internal->vipMutex);
  521. std::lock_guard<std::recursive_mutex> lock(internal->mutex);
  522. moduleHandle->module = NULL;
  523. // Check that the ModuleHandle is already added
  524. auto it = std::find(internal->moduleHandles.begin(), internal->moduleHandles.end(), moduleHandle);
  525. assert(it != internal->moduleHandles.end());
  526. internal->moduleHandles.erase(it);
  527. }
  528. void EngineWorker::step() {
  529. engine->internal->engineBarrier.wait();
  530. if (!running)
  531. return;
  532. Engine_stepModules(engine, id);
  533. engine->internal->workerBarrier.wait();
  534. }
  535. } // namespace engine
  536. } // namespace rack