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

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