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.

104 lines
2.5KB

  1. #pragma once
  2. #include "dsp/common.hpp"
  3. namespace rack {
  4. namespace dsp {
  5. /** Deprecated. Use VuMeter2 instead. */
  6. struct VuMeter {
  7. /** Decibel level difference between adjacent meter lights */
  8. float dBInterval = 3.0;
  9. float dBScaled;
  10. /** Value should be scaled so that 1.0 is clipping */
  11. void setValue(float v) {
  12. dBScaled = std::log10(std::fabs(v)) * 20.0 / dBInterval;
  13. }
  14. /** Returns the brightness of the light indexed by i.
  15. Light 0 is a clip light (red) which is either on or off.
  16. All others are smooth lights which are fully bright at -dBInterval*i and higher, and fully off at -dBInterval*(i-1).
  17. */
  18. float getBrightness(int i) {
  19. if (i == 0) {
  20. return (dBScaled >= 0.0) ? 1.0 : 0.0;
  21. }
  22. else {
  23. return math::clamp(dBScaled + i, 0.0, 1.0);
  24. }
  25. }
  26. };
  27. DEPRECATED typedef VuMeter VUMeter;
  28. /** Models a VU meter with smoothing.
  29. Supports peak and RMS (root-mean-square) metering.
  30. Usage example for a strip of lights with 3dB increments:
  31. ```
  32. // Update VuMeter state every frame.
  33. vuMeter.process(deltaTime, output);
  34. // Iterate lights every ~512 frames (less than a screen refresh).
  35. for (int i = 0; i < 6; i++) {
  36. float b = vuMeter.getBrightness(-3.f * (i + 1), -3.f * i);
  37. // No need to use setSmoothBrightness() since VuMeter2 smooths the value for you.
  38. lights[i].setBrightness(b);
  39. }
  40. ```
  41. */
  42. struct VuMeter2 {
  43. enum Mode {
  44. PEAK,
  45. RMS
  46. };
  47. Mode mode = PEAK;
  48. /** Either the smoothed peak or the mean-square of the brightness, depending on the mode. */
  49. float v;
  50. /** Inverse time constant in 1/seconds */
  51. float lambda = 30.f;
  52. VuMeter2() {
  53. reset();
  54. }
  55. void reset() {
  56. v = 0.f;
  57. }
  58. void process(float deltaTime, float value) {
  59. if (mode == RMS) {
  60. value = std::pow(value, 2);
  61. v += (value - v) * lambda * deltaTime;
  62. }
  63. else {
  64. value = std::fabs(value);
  65. if (value >= v) {
  66. v = value;
  67. }
  68. else {
  69. v += (value - v) * lambda * deltaTime;
  70. }
  71. }
  72. }
  73. /** Returns the LED brightness measuring tick marks between dbMin and dbMax.
  74. For example, `getBrightness(-6.f, 0.f)` will be at minimum brightness at -6dB and maximum brightness at 0dB.
  75. Set dbMin == dbMax == 0.f for a clip indicator that turns fully on when db >= dbMax.
  76. Expensive, so call this infrequently.
  77. */
  78. float getBrightness(float dbMin, float dbMax) {
  79. float db = amplitudeToDb((mode == RMS) ? std::sqrt(v) : v);
  80. if (db >= dbMax)
  81. return 1.f;
  82. else if (db <= dbMin)
  83. return 0.f;
  84. else
  85. return math::rescale(db, dbMin, dbMax, 0.f, 1.f);
  86. }
  87. };
  88. } // namespace dsp
  89. } // namespace rack