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.

365 lines
9.2KB

  1. #include <vector>
  2. #include <algorithm>
  3. #include <chrono>
  4. #include <thread>
  5. #include <condition_variable>
  6. #include <mutex>
  7. #include <xmmintrin.h>
  8. #include <pmmintrin.h>
  9. #include "rack.hpp"
  10. #include "engine.hpp"
  11. namespace rack {
  12. bool gPaused = false;
  13. std::vector<Module*> gModules;
  14. std::vector<Wire*> gWires;
  15. bool gPowerMeter = false;
  16. static bool running = false;
  17. static float sampleRate = 44100.f;
  18. static float sampleTime = 1.f / sampleRate;
  19. static float sampleRateRequested = sampleRate;
  20. static Module *resetModule = NULL;
  21. static Module *randomizeModule = NULL;
  22. /** Threads which obtain a VIPLock will cause wait() to block for other less important threads.
  23. This does not provide the VIPs with an exclusive lock. That should be left up to another mutex shared between the less important thread.
  24. */
  25. struct VIPMutex {
  26. int count = 0;
  27. std::condition_variable cv;
  28. std::mutex countMutex;
  29. /** Blocks until there are no remaining VIPLocks */
  30. void wait() {
  31. std::unique_lock<std::mutex> lock(countMutex);
  32. while (count > 0)
  33. cv.wait(lock);
  34. }
  35. };
  36. struct VIPLock {
  37. VIPMutex &m;
  38. VIPLock(VIPMutex &m) : m(m) {
  39. std::unique_lock<std::mutex> lock(m.countMutex);
  40. m.count++;
  41. }
  42. ~VIPLock() {
  43. std::unique_lock<std::mutex> lock(m.countMutex);
  44. m.count--;
  45. lock.unlock();
  46. m.cv.notify_all();
  47. }
  48. };
  49. static std::mutex mutex;
  50. static std::thread thread;
  51. static VIPMutex vipMutex;
  52. // Parameter interpolation
  53. static Module *smoothModule = NULL;
  54. static int smoothParamId;
  55. static float smoothValue;
  56. json_t *Param::toJson() {
  57. json_t *rootJ = json_object();
  58. // Infinite params should serialize to 0
  59. float v = (std::isfinite(minValue) && std::isfinite(maxValue)) ? value : 0.f;
  60. json_object_set_new(rootJ, "value", json_real(v));
  61. return rootJ;
  62. }
  63. void Param::fromJson(json_t *rootJ) {
  64. json_t *valueJ = json_object_get(rootJ, "value");
  65. if (valueJ)
  66. value = json_number_value(valueJ);
  67. }
  68. float Light::getBrightness() {
  69. // LEDs are diodes, so don't allow reverse current.
  70. // For some reason, instead of the RMS, the sqrt of RMS looks better
  71. return std::pow(std::fmaxf(0.f, value), 0.25f);
  72. }
  73. void Light::setBrightnessSmooth(float brightness, float frames) {
  74. float v = (brightness > 0.f) ? brightness * brightness : 0.f;
  75. if (v < value) {
  76. // Fade out light with lambda = framerate
  77. value += (v - value) * sampleTime * frames * 60.f;
  78. }
  79. else {
  80. // Immediately illuminate light
  81. value = v;
  82. }
  83. }
  84. void Wire::step() {
  85. float value = outputModule->outputs[outputId].value;
  86. inputModule->inputs[inputId].value = value;
  87. }
  88. void engineInit() {
  89. }
  90. void engineDestroy() {
  91. // Make sure there are no wires or modules in the rack on destruction. This suggests that a module failed to remove itself before the RackWidget was destroyed.
  92. assert(gWires.empty());
  93. assert(gModules.empty());
  94. }
  95. static void engineStep() {
  96. // Sample rate
  97. if (sampleRateRequested != sampleRate) {
  98. sampleRate = sampleRateRequested;
  99. sampleTime = 1.f / sampleRate;
  100. for (Module *module : gModules) {
  101. module->onSampleRateChange();
  102. }
  103. }
  104. // Events
  105. if (resetModule) {
  106. resetModule->onReset();
  107. resetModule = NULL;
  108. }
  109. if (randomizeModule) {
  110. randomizeModule->onRandomize();
  111. randomizeModule = NULL;
  112. }
  113. // Param smoothing
  114. {
  115. Module *localSmoothModule = smoothModule;
  116. int localSmoothParamId = smoothParamId;
  117. float localSmoothValue = smoothValue;
  118. if (localSmoothModule) {
  119. float value = localSmoothModule->params[localSmoothParamId].value;
  120. const float lambda = 60.0; // decay rate is 1 graphics frame
  121. float delta = localSmoothValue - value;
  122. float newValue = value + delta * lambda * sampleTime;
  123. if (value == newValue) {
  124. // Snap to actual smooth value if the value doesn't change enough (due to the granularity of floats)
  125. localSmoothModule->params[localSmoothParamId].value = localSmoothValue;
  126. smoothModule = NULL;
  127. }
  128. else {
  129. localSmoothModule->params[localSmoothParamId].value = newValue;
  130. }
  131. }
  132. }
  133. // Step modules
  134. for (Module *module : gModules) {
  135. std::chrono::high_resolution_clock::time_point startTime;
  136. if (gPowerMeter) {
  137. startTime = std::chrono::high_resolution_clock::now();
  138. module->step();
  139. auto stopTime = std::chrono::high_resolution_clock::now();
  140. float cpuTime = std::chrono::duration<float>(stopTime - startTime).count() * sampleRate;
  141. module->cpuTime += (cpuTime - module->cpuTime) * sampleTime / 0.5f;
  142. }
  143. else {
  144. module->step();
  145. }
  146. // Step ports
  147. for (Input &input : module->inputs) {
  148. if (input.active) {
  149. float value = input.value / 5.f;
  150. input.plugLights[0].setBrightnessSmooth(value);
  151. input.plugLights[1].setBrightnessSmooth(-value);
  152. }
  153. }
  154. for (Output &output : module->outputs) {
  155. if (output.active) {
  156. float value = output.value / 5.f;
  157. output.plugLights[0].setBrightnessSmooth(value);
  158. output.plugLights[1].setBrightnessSmooth(-value);
  159. }
  160. }
  161. }
  162. // Step cables by moving their output values to inputs
  163. for (Wire *wire : gWires) {
  164. wire->step();
  165. }
  166. }
  167. static void engineRun() {
  168. // Set CPU to flush-to-zero (FTZ) and denormals-are-zero (DAZ) mode
  169. // https://software.intel.com/en-us/node/682949
  170. _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
  171. _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
  172. // Every time the engine waits and locks a mutex, it steps this many frames
  173. const int mutexSteps = 64;
  174. // Time in seconds that the engine is rushing ahead of the estimated clock time
  175. double ahead = 0.0;
  176. auto lastTime = std::chrono::high_resolution_clock::now();
  177. while (running) {
  178. vipMutex.wait();
  179. if (!gPaused) {
  180. std::lock_guard<std::mutex> lock(mutex);
  181. for (int i = 0; i < mutexSteps; i++) {
  182. engineStep();
  183. }
  184. }
  185. double stepTime = mutexSteps * sampleTime;
  186. ahead += stepTime;
  187. auto currTime = std::chrono::high_resolution_clock::now();
  188. const double aheadFactor = 2.0;
  189. ahead -= aheadFactor * std::chrono::duration<double>(currTime - lastTime).count();
  190. lastTime = currTime;
  191. ahead = fmaxf(ahead, 0.0);
  192. // Avoid pegging the CPU at 100% when there are no "blocking" modules like AudioInterface, but still step audio at a reasonable rate
  193. // The number of steps to wait before possibly sleeping
  194. const double aheadMax = 1.0; // seconds
  195. if (ahead > aheadMax) {
  196. std::this_thread::sleep_for(std::chrono::duration<double>(stepTime));
  197. }
  198. }
  199. }
  200. void engineStart() {
  201. running = true;
  202. thread = std::thread(engineRun);
  203. }
  204. void engineStop() {
  205. running = false;
  206. thread.join();
  207. }
  208. void engineAddModule(Module *module) {
  209. assert(module);
  210. VIPLock vipLock(vipMutex);
  211. std::lock_guard<std::mutex> lock(mutex);
  212. // Check that the module is not already added
  213. auto it = std::find(gModules.begin(), gModules.end(), module);
  214. assert(it == gModules.end());
  215. gModules.push_back(module);
  216. }
  217. void engineRemoveModule(Module *module) {
  218. assert(module);
  219. VIPLock vipLock(vipMutex);
  220. std::lock_guard<std::mutex> lock(mutex);
  221. // If a param is being smoothed on this module, stop smoothing it immediately
  222. if (module == smoothModule) {
  223. smoothModule = NULL;
  224. }
  225. // Check that all wires are disconnected
  226. for (Wire *wire : gWires) {
  227. assert(wire->outputModule != module);
  228. assert(wire->inputModule != module);
  229. }
  230. // Check that the module actually exists
  231. auto it = std::find(gModules.begin(), gModules.end(), module);
  232. assert(it != gModules.end());
  233. // Remove it
  234. gModules.erase(it);
  235. }
  236. void engineResetModule(Module *module) {
  237. resetModule = module;
  238. }
  239. void engineRandomizeModule(Module *module) {
  240. randomizeModule = module;
  241. }
  242. static void updateActive() {
  243. // Set everything to inactive
  244. for (Module *module : gModules) {
  245. for (Input &input : module->inputs) {
  246. input.active = false;
  247. }
  248. for (Output &output : module->outputs) {
  249. output.active = false;
  250. }
  251. }
  252. // Set inputs/outputs to active
  253. for (Wire *wire : gWires) {
  254. wire->outputModule->outputs[wire->outputId].active = true;
  255. wire->inputModule->inputs[wire->inputId].active = true;
  256. }
  257. }
  258. void engineAddWire(Wire *wire) {
  259. assert(wire);
  260. VIPLock vipLock(vipMutex);
  261. std::lock_guard<std::mutex> lock(mutex);
  262. // Check wire properties
  263. assert(wire->outputModule);
  264. assert(wire->inputModule);
  265. // Check that the wire is not already added, and that the input is not already used by another cable
  266. for (Wire *wire2 : gWires) {
  267. assert(wire2 != wire);
  268. assert(!(wire2->inputModule == wire->inputModule && wire2->inputId == wire->inputId));
  269. }
  270. // Add the wire
  271. gWires.push_back(wire);
  272. updateActive();
  273. }
  274. void engineRemoveWire(Wire *wire) {
  275. assert(wire);
  276. VIPLock vipLock(vipMutex);
  277. std::lock_guard<std::mutex> lock(mutex);
  278. // Check that the wire is already added
  279. auto it = std::find(gWires.begin(), gWires.end(), wire);
  280. assert(it != gWires.end());
  281. // Set input to 0V
  282. wire->inputModule->inputs[wire->inputId].value = 0.0;
  283. // Remove the wire
  284. gWires.erase(it);
  285. updateActive();
  286. }
  287. void engineSetParam(Module *module, int paramId, float value) {
  288. module->params[paramId].value = value;
  289. }
  290. void engineSetParamSmooth(Module *module, int paramId, float value) {
  291. // If another param is being smoothed, jump value
  292. if (smoothModule && !(smoothModule == module && smoothParamId == paramId)) {
  293. smoothModule->params[smoothParamId].value = smoothValue;
  294. }
  295. smoothParamId = paramId;
  296. smoothValue = value;
  297. smoothModule = module;
  298. }
  299. void engineSetSampleRate(float newSampleRate) {
  300. sampleRateRequested = newSampleRate;
  301. }
  302. float engineGetSampleRate() {
  303. return sampleRate;
  304. }
  305. float engineGetSampleTime() {
  306. return sampleTime;
  307. }
  308. } // namespace rack