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.

100 lines
2.4KB

  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 = 0.f;
  50. /** Inverse time constant in 1/seconds */
  51. float lambda = 30.f;
  52. void reset() {
  53. v = 0.f;
  54. }
  55. void process(float deltaTime, float value) {
  56. if (mode == RMS) {
  57. value = std::pow(value, 2);
  58. v += (value - v) * lambda * deltaTime;
  59. }
  60. else {
  61. value = std::fabs(value);
  62. if (value >= v) {
  63. v = value;
  64. }
  65. else {
  66. v += (value - v) * lambda * deltaTime;
  67. }
  68. }
  69. }
  70. /** Returns the LED brightness measuring tick marks between dbMin and dbMax.
  71. For example, `getBrightness(-6.f, 0.f)` will be at minimum brightness at -6dB and maximum brightness at 0dB.
  72. Set dbMin == dbMax == 0.f for a clip indicator that turns fully on when db >= dbMax.
  73. Expensive, so call this infrequently.
  74. */
  75. float getBrightness(float dbMin, float dbMax) {
  76. float db = amplitudeToDb((mode == RMS) ? std::sqrt(v) : v);
  77. if (db >= dbMax)
  78. return 1.f;
  79. else if (db <= dbMin)
  80. return 0.f;
  81. else
  82. return math::rescale(db, dbMin, dbMax, 0.f, 1.f);
  83. }
  84. };
  85. } // namespace dsp
  86. } // namespace rack