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.

226 lines
4.5KB

  1. #include <algorithm>
  2. #include <engine/ParamQuantity.hpp>
  3. #include <context.hpp>
  4. #include <engine/Engine.hpp>
  5. #include <string.hpp>
  6. namespace rack {
  7. namespace engine {
  8. engine::Param* ParamQuantity::getParam() {
  9. if (!module)
  10. return NULL;
  11. if (!(0 <= paramId && paramId < (int) module->params.size()))
  12. return NULL;
  13. return &module->params[paramId];
  14. }
  15. void ParamQuantity::setValue(float value) {
  16. if (!module)
  17. return;
  18. value = math::clampSafe(value, getMinValue(), getMaxValue());
  19. if (snapEnabled)
  20. value = std::round(value);
  21. if (smoothEnabled)
  22. APP->engine->setParamSmoothValue(module, paramId, value);
  23. else
  24. APP->engine->setParamValue(module, paramId, value);
  25. }
  26. float ParamQuantity::getValue() {
  27. if (!module)
  28. return 0.f;
  29. // Get smoothing target value regardless of `smoothEnabled`.
  30. // If smoothing is enabled, value is set, and smoothing is then disabled, calling getParamValue() will return the incorrect value.
  31. return APP->engine->getParamSmoothValue(module, paramId);
  32. }
  33. void ParamQuantity::setImmediateValue(float value) {
  34. if (!module)
  35. return;
  36. value = math::clampSafe(value, getMinValue(), getMaxValue());
  37. if (snapEnabled)
  38. value = std::round(value);
  39. APP->engine->setParamValue(module, paramId, value);
  40. }
  41. float ParamQuantity::getImmediateValue() {
  42. if (!module)
  43. return 0.f;
  44. return APP->engine->getParamValue(module, paramId);
  45. }
  46. float ParamQuantity::getMinValue() {
  47. return minValue;
  48. }
  49. float ParamQuantity::getMaxValue() {
  50. return maxValue;
  51. }
  52. float ParamQuantity::getDefaultValue() {
  53. return defaultValue;
  54. }
  55. float ParamQuantity::getDisplayValue() {
  56. float v = getValue();
  57. if (displayBase == 0.f) {
  58. // Linear
  59. // v is unchanged
  60. }
  61. else if (displayBase < 0.f) {
  62. // Logarithmic
  63. v = std::log(v) / std::log(-displayBase);
  64. }
  65. else {
  66. // Exponential
  67. v = std::pow(displayBase, v);
  68. }
  69. return v * displayMultiplier + displayOffset;
  70. }
  71. void ParamQuantity::setDisplayValue(float displayValue) {
  72. // Handle displayOffset
  73. float v = displayValue - displayOffset;
  74. // Handle displayMultiplier
  75. if (displayMultiplier == 0.f)
  76. v = 0.f;
  77. else
  78. v /= displayMultiplier;
  79. // Handle displayBase
  80. if (displayBase == 0.f) {
  81. // Linear
  82. // v is unchanged
  83. }
  84. else if (displayBase < 0.f) {
  85. // Logarithmic
  86. v = std::pow(-displayBase, v);
  87. }
  88. else {
  89. // Exponential
  90. v = std::log(v) / std::log(displayBase);
  91. }
  92. if (std::isnan(v))
  93. return;
  94. // Set the value directly without smoothing
  95. setImmediateValue(v);
  96. }
  97. int ParamQuantity::getDisplayPrecision() {
  98. return displayPrecision;
  99. }
  100. std::string ParamQuantity::getDisplayValueString() {
  101. return Quantity::getDisplayValueString();
  102. }
  103. void ParamQuantity::setDisplayValueString(std::string s) {
  104. Quantity::setDisplayValueString(s);
  105. }
  106. std::string ParamQuantity::getLabel() {
  107. if (name == "")
  108. return string::f("#%d", paramId + 1);
  109. return name;
  110. }
  111. std::string ParamQuantity::getUnit() {
  112. return unit;
  113. }
  114. void ParamQuantity::reset() {
  115. setImmediateValue(getDefaultValue());
  116. }
  117. void ParamQuantity::randomize() {
  118. if (!isBounded())
  119. return;
  120. if (snapEnabled) {
  121. // Randomize inclusive of the maximum value
  122. float value = math::rescale(random::uniform(), 0.f, 1.f, getMinValue(), getMaxValue() + 1.f);
  123. value = std::floor(value);
  124. setImmediateValue(value);
  125. }
  126. else {
  127. // Same as Quantity::randomize() but with setImmediateValue()
  128. setImmediateValue(fromScaled(random::uniform()));
  129. }
  130. }
  131. std::string ParamQuantity::getDescription() {
  132. return description;
  133. }
  134. json_t* ParamQuantity::toJson() {
  135. json_t* rootJ = json_object();
  136. json_object_set_new(rootJ, "value", json_real(getValue()));
  137. return rootJ;
  138. }
  139. void ParamQuantity::fromJson(json_t* rootJ) {
  140. json_t* valueJ = json_object_get(rootJ, "value");
  141. if (valueJ)
  142. setImmediateValue(json_number_value(valueJ));
  143. }
  144. void ParamQuantity::setSmoothValue(float value) {
  145. setValue(value);
  146. }
  147. float ParamQuantity::getSmoothValue() {
  148. return getValue();
  149. }
  150. // SwitchQuantity
  151. std::string SwitchQuantity::getDisplayValueString() {
  152. int index = (int) std::floor(getValue() - getMinValue());
  153. if (!(0 <= index && index < (int) labels.size()))
  154. return "";
  155. return labels[index];
  156. }
  157. void SwitchQuantity::setDisplayValueString(std::string s) {
  158. // Find label that matches string, case insensitive.
  159. auto it = std::find_if(labels.begin(), labels.end(), [&](const std::string& a) {
  160. return string::lowercase(a) == string::lowercase(s);
  161. });
  162. if (it == labels.end())
  163. return;
  164. int index = std::distance(labels.begin(), it);
  165. setImmediateValue(getMinValue() + index);
  166. }
  167. } // namespace engine
  168. } // namespace rack