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.6KB

  1. // Copyright 2012 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. #ifndef BRAIDS_ENVELOPE_H_
  16. #define BRAIDS_ENVELOPE_H_
  17. #include "stmlib/stmlib.h"
  18. #include "stmlib/utils/dsp.h"
  19. #include "braids/resources.h"
  20. namespace braids {
  21. using namespace stmlib;
  22. enum EnvelopeSegment {
  23. ENV_SEGMENT_ATTACK = 0,
  24. ENV_SEGMENT_DECAY = 1,
  25. ENV_SEGMENT_DEAD = 2,
  26. ENV_NUM_SEGMENTS,
  27. };
  28. class Envelope {
  29. public:
  30. Envelope() { }
  31. ~Envelope() { }
  32. void Init() {
  33. target_[ENV_SEGMENT_ATTACK] = 65535;
  34. target_[ENV_SEGMENT_DECAY] = 0;
  35. target_[ENV_SEGMENT_DEAD] = 0;
  36. increment_[ENV_SEGMENT_DEAD] = 0;
  37. }
  38. inline EnvelopeSegment segment() const {
  39. return static_cast<EnvelopeSegment>(segment_);
  40. }
  41. inline void Update(int32_t a, int32_t d) {
  42. increment_[ENV_SEGMENT_ATTACK] = lut_env_portamento_increments[a];
  43. increment_[ENV_SEGMENT_DECAY] = lut_env_portamento_increments[d];
  44. }
  45. inline void Trigger(EnvelopeSegment segment) {
  46. if (segment == ENV_SEGMENT_DEAD) {
  47. value_ = 0;
  48. }
  49. a_ = value_;
  50. b_ = target_[segment];
  51. segment_ = segment;
  52. phase_ = 0;
  53. }
  54. inline uint16_t Render() {
  55. uint32_t increment = increment_[segment_];
  56. phase_ += increment;
  57. if (phase_ < increment) {
  58. value_ = Mix(a_, b_, 65535);
  59. Trigger(static_cast<EnvelopeSegment>(segment_ + 1));
  60. }
  61. if (increment_[segment_]) {
  62. value_ = Mix(a_, b_, Interpolate824(lut_env_expo, phase_));
  63. }
  64. return value_;
  65. }
  66. inline uint16_t value() const { return value_; }
  67. private:
  68. // Phase increments for each segment.
  69. uint32_t increment_[ENV_NUM_SEGMENTS];
  70. // Value that needs to be reached at the end of each segment.
  71. uint16_t target_[ENV_NUM_SEGMENTS];
  72. // Current segment.
  73. size_t segment_;
  74. // Start and end value of the current segment.
  75. uint16_t a_;
  76. uint16_t b_;
  77. uint16_t value_;
  78. uint32_t phase_;
  79. DISALLOW_COPY_AND_ASSIGN(Envelope);
  80. };
  81. } // namespace braids
  82. #endif // BRAIDS_ENVELOPE_H_