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.

107 lines
1.9KB

  1. #pragma once
  2. #include "util/math.hpp"
  3. namespace rack {
  4. /** Turns HIGH when value reaches 1.f, turns LOW when value reaches 0.f. */
  5. struct SchmittTrigger {
  6. enum State {
  7. UNKNOWN,
  8. LOW,
  9. HIGH
  10. };
  11. State state;
  12. SchmittTrigger() {
  13. reset();
  14. }
  15. void reset() {
  16. state = UNKNOWN;
  17. }
  18. /** Updates the state of the Schmitt Trigger given a value.
  19. Returns true if triggered, i.e. the value increases from 0 to 1.
  20. If different trigger thresholds are needed, use
  21. process(rescale(in, low, high, 0.f, 1.f))
  22. for example.
  23. */
  24. bool process(float in) {
  25. switch (state) {
  26. case LOW:
  27. if (in >= 1.f) {
  28. state = HIGH;
  29. return true;
  30. }
  31. break;
  32. case HIGH:
  33. if (in <= 0.f) {
  34. state = LOW;
  35. }
  36. break;
  37. default:
  38. if (in >= 1.f) {
  39. state = HIGH;
  40. }
  41. else if (in <= 0.f) {
  42. state = LOW;
  43. }
  44. break;
  45. }
  46. return false;
  47. }
  48. bool isHigh() {
  49. return state == HIGH;
  50. }
  51. };
  52. struct BooleanTrigger {
  53. bool lastState;
  54. BooleanTrigger() {
  55. reset();
  56. }
  57. void reset() {
  58. lastState = true;
  59. }
  60. bool process(bool state) {
  61. bool triggered = (state && !lastState);
  62. lastState = state;
  63. return triggered;
  64. }
  65. };
  66. /** When triggered, holds a high value for a specified time before going low again */
  67. struct PulseGenerator {
  68. float time;
  69. float triggerDuration;
  70. PulseGenerator() {
  71. reset();
  72. }
  73. /** Immediately resets the state to LOW */
  74. void reset() {
  75. time = 0.f;
  76. triggerDuration = 0.f;
  77. }
  78. /** Advances the state by `deltaTime`. Returns whether the pulse is in the HIGH state. */
  79. bool process(float deltaTime) {
  80. time += deltaTime;
  81. return time < triggerDuration;
  82. }
  83. /** Begins a trigger with the given `triggerDuration`. */
  84. void trigger(float triggerDuration) {
  85. // Keep the previous triggerDuration if the existing pulse would be held longer than the currently requested one.
  86. if (time + triggerDuration >= this->triggerDuration) {
  87. time = 0.f;
  88. this->triggerDuration = triggerDuration;
  89. }
  90. }
  91. };
  92. } // namespace rack