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.

399 lines
9.4KB

  1. #include <engine/Module.hpp>
  2. #include <engine/Engine.hpp>
  3. #include <plugin.hpp>
  4. #include <system.hpp>
  5. #include <settings.hpp>
  6. #include <asset.hpp>
  7. #include <context.hpp>
  8. #include <patch.hpp>
  9. namespace rack {
  10. namespace engine {
  11. // Arbitrary prime number so it doesn't over- or under-estimate time of buffered processors.
  12. static const int METER_DIVIDER = 37;
  13. static const int METER_BUFFER_LEN = 32;
  14. static const float METER_TIME = 1.f;
  15. struct Module::Internal {
  16. bool bypassed = false;
  17. int meterSamples = 0;
  18. float meterDurationTotal = 0.f;
  19. float meterBuffer[METER_BUFFER_LEN] = {};
  20. int meterIndex = 0;
  21. };
  22. Module::Module() {
  23. internal = new Internal;
  24. }
  25. Module::~Module() {
  26. for (ParamQuantity* paramQuantity : paramQuantities) {
  27. if (paramQuantity)
  28. delete paramQuantity;
  29. }
  30. for (PortInfo* inputInfo : inputInfos) {
  31. if (inputInfo)
  32. delete inputInfo;
  33. }
  34. for (PortInfo* outputInfo : outputInfos) {
  35. if (outputInfo)
  36. delete outputInfo;
  37. }
  38. for (LightInfo* lightInfo : lightInfos) {
  39. if (lightInfo)
  40. delete lightInfo;
  41. }
  42. delete internal;
  43. }
  44. void Module::config(int numParams, int numInputs, int numOutputs, int numLights) {
  45. // This method should only be called once.
  46. assert(params.empty() && inputs.empty() && outputs.empty() && lights.empty() && paramQuantities.empty());
  47. params.resize(numParams);
  48. inputs.resize(numInputs);
  49. outputs.resize(numOutputs);
  50. lights.resize(numLights);
  51. // Initialize paramQuantities
  52. paramQuantities.resize(numParams);
  53. for (int i = 0; i < numParams; i++) {
  54. configParam(i, 0.f, 1.f, 0.f);
  55. }
  56. // Initialize PortInfos
  57. inputInfos.resize(numInputs);
  58. for (int i = 0; i < numInputs; i++) {
  59. configInput(i);
  60. }
  61. outputInfos.resize(numOutputs);
  62. for (int i = 0; i < numOutputs; i++) {
  63. configOutput(i);
  64. }
  65. // Initialize LightInfos with null
  66. lightInfos.resize(numLights);
  67. }
  68. std::string Module::createPatchStorageDirectory() {
  69. std::string path = getPatchStorageDirectory();
  70. system::createDirectories(path);
  71. return path;
  72. }
  73. std::string Module::getPatchStorageDirectory() {
  74. if (id < 0)
  75. throw Exception("getPatchStorageDirectory() cannot be called unless Module belongs to Engine and thus has a valid ID");
  76. return system::join(APP->patch->autosavePath, "modules", std::to_string(id));
  77. }
  78. void Module::processBypass(const ProcessArgs& args) {
  79. for (BypassRoute& bypassRoute : bypassRoutes) {
  80. // Route input voltages to output
  81. Input& input = inputs[bypassRoute.inputId];
  82. Output& output = outputs[bypassRoute.outputId];
  83. int channels = input.getChannels();
  84. for (int c = 0; c < channels; c++) {
  85. float v = input.getVoltage(c);
  86. output.setVoltage(v, c);
  87. }
  88. output.setChannels(channels);
  89. }
  90. }
  91. json_t* Module::toJson() {
  92. json_t* rootJ = json_object();
  93. // id
  94. json_object_set_new(rootJ, "id", json_integer(id));
  95. // plugin
  96. json_object_set_new(rootJ, "plugin", json_string(model->plugin->slug.c_str()));
  97. // model
  98. json_object_set_new(rootJ, "model", json_string(model->slug.c_str()));
  99. // version
  100. json_object_set_new(rootJ, "version", json_string(model->plugin->version.c_str()));
  101. // params
  102. json_t* paramsJ = paramsToJson();
  103. if (paramsJ)
  104. json_object_set_new(rootJ, "params", paramsJ);
  105. // bypass
  106. if (internal->bypassed)
  107. json_object_set_new(rootJ, "bypass", json_boolean(true));
  108. // leftModuleId
  109. if (leftExpander.moduleId >= 0)
  110. json_object_set_new(rootJ, "leftModuleId", json_integer(leftExpander.moduleId));
  111. // rightModuleId
  112. if (rightExpander.moduleId >= 0)
  113. json_object_set_new(rootJ, "rightModuleId", json_integer(rightExpander.moduleId));
  114. // data
  115. json_t* dataJ = dataToJson();
  116. if (dataJ) {
  117. json_object_set_new(rootJ, "data", dataJ);
  118. }
  119. return rootJ;
  120. }
  121. void Module::fromJson(json_t* rootJ) {
  122. plugin::Model* model = plugin::modelFromJson(rootJ);
  123. assert(model);
  124. if (model != this->model)
  125. throw Exception("Model %s %s does not match Module's model %s %s.", model->plugin->slug.c_str(), model->slug.c_str(), this->model->plugin->slug.c_str(), this->model->slug.c_str());
  126. // Check plugin version
  127. json_t* versionJ = json_object_get(rootJ, "version");
  128. if (versionJ) {
  129. std::string version = json_string_value(versionJ);
  130. if (version != this->model->plugin->version) {
  131. INFO("Patch created with %s v%s, currently using v%s.", this->model->plugin->slug.c_str(), version.c_str(), this->model->plugin->version.c_str());
  132. }
  133. }
  134. // id
  135. // Only set ID if unset
  136. if (id < 0) {
  137. json_t* idJ = json_object_get(rootJ, "id");
  138. if (idJ)
  139. id = json_integer_value(idJ);
  140. }
  141. // params
  142. json_t* paramsJ = json_object_get(rootJ, "params");
  143. if (paramsJ)
  144. paramsFromJson(paramsJ);
  145. // bypass
  146. json_t* bypassJ = json_object_get(rootJ, "bypass");
  147. // legacy "disabled" in v1
  148. if (!bypassJ)
  149. bypassJ = json_object_get(rootJ, "disabled");
  150. if (bypassJ)
  151. internal->bypassed = json_boolean_value(bypassJ);
  152. // leftModuleId
  153. json_t *leftModuleIdJ = json_object_get(rootJ, "leftModuleId");
  154. if (leftModuleIdJ)
  155. leftExpander.moduleId = json_integer_value(leftModuleIdJ);
  156. // rightModuleId
  157. json_t *rightModuleIdJ = json_object_get(rootJ, "rightModuleId");
  158. if (rightModuleIdJ)
  159. rightExpander.moduleId = json_integer_value(rightModuleIdJ);
  160. // data
  161. json_t* dataJ = json_object_get(rootJ, "data");
  162. if (dataJ)
  163. dataFromJson(dataJ);
  164. }
  165. json_t* Module::paramsToJson() {
  166. json_t* rootJ = json_array();
  167. for (size_t paramId = 0; paramId < paramQuantities.size(); paramId++) {
  168. // Don't serialize unbounded Params
  169. if (!paramQuantities[paramId]->isBounded())
  170. continue;
  171. json_t* paramJ = paramQuantities[paramId]->toJson();
  172. json_object_set_new(paramJ, "id", json_integer(paramId));
  173. json_array_append(rootJ, paramJ);
  174. }
  175. return rootJ;
  176. }
  177. void Module::paramsFromJson(json_t* rootJ) {
  178. size_t i;
  179. json_t* paramJ;
  180. json_array_foreach(rootJ, i, paramJ) {
  181. // Get paramId
  182. json_t* paramIdJ = json_object_get(paramJ, "id");
  183. // Legacy v0.6 to <v1
  184. if (!paramIdJ)
  185. paramIdJ = json_object_get(paramJ, "paramId");
  186. size_t paramId;
  187. if (paramIdJ)
  188. paramId = json_integer_value(paramIdJ);
  189. // Use index if all else fails
  190. else
  191. paramId = i;
  192. // Check ID bounds
  193. if (paramId >= paramQuantities.size())
  194. continue;
  195. ParamQuantity* pq = paramQuantities[paramId];
  196. // Check that the Param is bounded
  197. if (!pq->isBounded())
  198. continue;
  199. json_t* valueJ = json_object_get(paramJ, "value");
  200. if (valueJ)
  201. pq->setValue(json_number_value(valueJ));
  202. }
  203. }
  204. void Module::onReset(const ResetEvent& e) {
  205. // Reset all parameters
  206. for (ParamQuantity* pq : paramQuantities) {
  207. if (!pq->resetEnabled)
  208. continue;
  209. if (!pq->isBounded())
  210. continue;
  211. pq->reset();
  212. }
  213. // Call deprecated event
  214. onReset();
  215. }
  216. void Module::onRandomize(const RandomizeEvent& e) {
  217. // Randomize all parameters
  218. for (ParamQuantity* pq : paramQuantities) {
  219. if (!pq->randomizeEnabled)
  220. continue;
  221. if (!pq->isBounded())
  222. continue;
  223. pq->randomize();
  224. }
  225. // Call deprecated event
  226. onRandomize();
  227. }
  228. bool Module::isBypassed() {
  229. return internal->bypassed;
  230. }
  231. void Module::setBypassed(bool bypassed) {
  232. internal->bypassed = bypassed;
  233. }
  234. const float* Module::meterBuffer() {
  235. return internal->meterBuffer;
  236. }
  237. int Module::meterLength() {
  238. return METER_BUFFER_LEN;
  239. }
  240. int Module::meterIndex() {
  241. return internal->meterIndex;
  242. }
  243. static void Port_step(Port* that, float deltaTime) {
  244. // Set plug lights
  245. if (that->channels == 0) {
  246. that->plugLights[0].setBrightness(0.f);
  247. that->plugLights[1].setBrightness(0.f);
  248. that->plugLights[2].setBrightness(0.f);
  249. }
  250. else if (that->channels == 1) {
  251. float v = that->getVoltage() / 10.f;
  252. that->plugLights[0].setSmoothBrightness(-v, deltaTime);
  253. that->plugLights[1].setSmoothBrightness(v, deltaTime);
  254. that->plugLights[2].setBrightness(0.f);
  255. }
  256. else {
  257. float v = that->getVoltageRMS() / 10.f;
  258. that->plugLights[0].setBrightness(0.f);
  259. that->plugLights[1].setBrightness(0.f);
  260. that->plugLights[2].setSmoothBrightness(v, deltaTime);
  261. }
  262. }
  263. void Module::doProcess(const ProcessArgs& args) {
  264. // This global setting can change while the function is running, so use a local variable.
  265. bool meterEnabled = settings::cpuMeter && (args.frame % METER_DIVIDER == 0);
  266. // Start CPU timer
  267. double startTime;
  268. if (meterEnabled) {
  269. startTime = system::getTime();
  270. }
  271. // Step module
  272. if (!internal->bypassed)
  273. process(args);
  274. else
  275. processBypass(args);
  276. // Stop CPU timer
  277. if (meterEnabled) {
  278. double endTime = system::getTime();
  279. // Subtract call time of getTime() itself, since we only want to measure process() time.
  280. double endTime2 = system::getTime();
  281. float duration = (endTime - startTime) - (endTime2 - endTime);
  282. internal->meterSamples++;
  283. internal->meterDurationTotal += duration;
  284. // Seconds we've been measuring
  285. float meterTime = internal->meterSamples * METER_DIVIDER * args.sampleTime;
  286. if (meterTime >= METER_TIME) {
  287. // Push time to buffer
  288. if (internal->meterSamples > 0) {
  289. internal->meterIndex++;
  290. internal->meterIndex %= METER_BUFFER_LEN;
  291. internal->meterBuffer[internal->meterIndex] = internal->meterDurationTotal / internal->meterSamples;
  292. }
  293. // Reset total
  294. internal->meterSamples = 0;
  295. internal->meterDurationTotal = 0.f;
  296. }
  297. }
  298. // Iterate ports to step plug lights
  299. const int portDivider = 8;
  300. if (args.frame % portDivider == 0) {
  301. float portTime = args.sampleTime * portDivider;
  302. for (Input& input : inputs) {
  303. Port_step(&input, portTime);
  304. }
  305. for (Output& output : outputs) {
  306. Port_step(&output, portTime);
  307. }
  308. }
  309. }
  310. void Module::jsonStripIds(json_t* rootJ) {
  311. json_object_del(rootJ, "id");
  312. json_object_del(rootJ, "leftModuleId");
  313. json_object_del(rootJ, "rightModuleId");
  314. }
  315. } // namespace engine
  316. } // namespace rack