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.

digital.hpp 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #pragma once
  2. #include <dsp/common.hpp>
  3. namespace rack {
  4. namespace dsp {
  5. /** Detects when a boolean changes from false to true */
  6. struct BooleanTrigger {
  7. bool state = true;
  8. void reset() {
  9. state = true;
  10. }
  11. bool process(bool state) {
  12. bool triggered = (state && !this->state);
  13. this->state = state;
  14. return triggered;
  15. }
  16. };
  17. /** Turns HIGH when value reaches 1.f, turns LOW when value reaches 0.f. */
  18. template <typename T = float>
  19. struct TSchmittTrigger {
  20. T state;
  21. TSchmittTrigger() {
  22. reset();
  23. }
  24. void reset() {
  25. state = T::mask();
  26. }
  27. T process(T in) {
  28. T on = (in >= 1.f);
  29. T off = (in <= 0.f);
  30. T triggered = ~state & on;
  31. state = on | (state & ~off);
  32. return triggered;
  33. }
  34. };
  35. template <>
  36. struct TSchmittTrigger<float> {
  37. bool state = true;
  38. void reset() {
  39. state = true;
  40. }
  41. /** Updates the state of the Schmitt Trigger given a value.
  42. Returns true if triggered, i.e. the value increases from 0 to 1.
  43. If different trigger thresholds are needed, use
  44. process(rescale(in, low, high, 0.f, 1.f))
  45. for example.
  46. */
  47. bool process(float in) {
  48. if (state) {
  49. // HIGH to LOW
  50. if (in <= 0.f) {
  51. state = false;
  52. }
  53. }
  54. else {
  55. // LOW to HIGH
  56. if (in >= 1.f) {
  57. state = true;
  58. return true;
  59. }
  60. }
  61. return false;
  62. }
  63. bool isHigh() {
  64. return state;
  65. }
  66. };
  67. typedef TSchmittTrigger<> SchmittTrigger;
  68. /** When triggered, holds a high value for a specified time before going low again */
  69. struct PulseGenerator {
  70. float remaining = 0.f;
  71. /** Immediately disables the pulse */
  72. void reset() {
  73. remaining = 0.f;
  74. }
  75. /** Advances the state by `deltaTime`. Returns whether the pulse is in the HIGH state. */
  76. bool process(float deltaTime) {
  77. if (remaining > 0.f) {
  78. remaining -= deltaTime;
  79. return true;
  80. }
  81. return false;
  82. }
  83. /** Begins a trigger with the given `duration`. */
  84. void trigger(float duration = 1e-3f) {
  85. // Keep the previous pulse if the existing pulse will be held longer than the currently requested one.
  86. if (duration > remaining) {
  87. remaining = duration;
  88. }
  89. }
  90. };
  91. struct Timer {
  92. float time = 0.f;
  93. void reset() {
  94. time = 0.f;
  95. }
  96. /** Returns the time since last reset or initialization. */
  97. float process(float deltaTime) {
  98. time += deltaTime;
  99. return time;
  100. }
  101. };
  102. struct ClockDivider {
  103. uint32_t clock = 0;
  104. uint32_t division = 1;
  105. void reset() {
  106. clock = 0;
  107. }
  108. void setDivision(uint32_t division) {
  109. this->division = division;
  110. }
  111. uint32_t getDivision() {
  112. return division;
  113. }
  114. uint32_t getClock() {
  115. return clock;
  116. }
  117. /** Returns true when the clock reaches `division` and resets. */
  118. bool process() {
  119. clock++;
  120. if (clock >= division) {
  121. clock = 0;
  122. return true;
  123. }
  124. return false;
  125. }
  126. };
  127. } // namespace dsp
  128. } // namespace rack