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.

188 lines
5.2KB

  1. // Copyright 2013 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // Keyframe interpolator.
  28. #ifndef FRAMES_KEYFRAMER_H_
  29. #define FRAMES_KEYFRAMER_H_
  30. #include "stmlib/stmlib.h"
  31. namespace frames {
  32. const uint8_t kNumChannels = 4;
  33. const uint8_t kMaxNumKeyframe = 64;
  34. const uint32_t kMagicNumber = 0xCAFEBABE;
  35. const uint8_t kNumPaletteEntries = 8;
  36. enum EasingCurve {
  37. EASING_CURVE_STEP,
  38. EASING_CURVE_LINEAR,
  39. EASING_CURVE_IN_QUARTIC,
  40. EASING_CURVE_OUT_QUARTIC,
  41. EASING_CURVE_SINE,
  42. EASING_CURVE_BOUNCE
  43. };
  44. struct ChannelSettings {
  45. EasingCurve easing_curve;
  46. uint8_t response;
  47. };
  48. struct Keyframe {
  49. uint16_t timestamp;
  50. uint16_t id;
  51. uint16_t values[kNumChannels];
  52. };
  53. struct KeyframeLess {
  54. bool operator()(const Keyframe& lhs, const Keyframe& rhs) {
  55. return lhs.timestamp < rhs.timestamp;
  56. }
  57. };
  58. class Keyframer {
  59. public:
  60. Keyframer() { }
  61. ~Keyframer() { }
  62. void Init();
  63. void Save(uint16_t slot);
  64. void Load(uint16_t slot);
  65. void Calibrate(int32_t dc_offset_frame_modulation);
  66. bool AddKeyframe(uint16_t timestamp, uint16_t* values);
  67. bool RemoveKeyframe(uint16_t timestamp);
  68. int16_t FindNearestKeyframe(uint16_t timestamp, uint16_t tolerance);
  69. inline void set_immediate(uint8_t channel, uint16_t value) {
  70. immediate_[channel] = value;
  71. }
  72. inline uint16_t dac_code(uint8_t channel) const {
  73. return dac_code_[channel];
  74. }
  75. inline uint16_t level(uint8_t channel) const {
  76. return levels_[channel];
  77. }
  78. inline uint8_t color(uint8_t component) const {
  79. return color_[component];
  80. }
  81. inline const uint8_t* color() const {
  82. return &color_[0];
  83. }
  84. void Evaluate(uint16_t timestamp);
  85. inline ChannelSettings* mutable_settings(uint8_t channel) {
  86. return &settings_[channel];
  87. }
  88. inline const ChannelSettings& mutable_settings(uint8_t channel) const {
  89. return settings_[channel];
  90. }
  91. inline Keyframe* mutable_keyframe(uint16_t index) {
  92. return &keyframes_[index];
  93. }
  94. inline const Keyframe& keyframe(uint16_t index) const {
  95. return keyframes_[index];
  96. }
  97. inline uint16_t num_keyframes() const { return num_keyframes_; }
  98. uint16_t Easing(int32_t from, int32_t to, uint32_t scale, EasingCurve curve);
  99. // This creates a sample animation (between 0 to 65535 and back to 0) used
  100. // for animating the LED when editing the easing curve or response.
  101. uint16_t SampleAnimation(uint8_t channel, uint16_t tick, bool easing);
  102. inline int16_t position() const { return position_; }
  103. inline int16_t nearest_keyframe() const { return nearest_keyframe_; }
  104. void Clear();
  105. void Reset();
  106. void Randomize();
  107. static uint16_t ConvertToDacCode(uint16_t gain, uint8_t response);
  108. // In addition to the keyframer data, this extra word stores in
  109. // persistent storage things like sequencer mode on/off and
  110. // poly lfo mode on/off states.
  111. inline int32_t dc_offset_frame_modulation() const {
  112. return dc_offset_frame_modulation_;
  113. }
  114. private:
  115. uint16_t FindKeyframe(uint16_t timestamp);
  116. Keyframe keyframes_[kMaxNumKeyframe];
  117. ChannelSettings settings_[kNumChannels];
  118. uint16_t num_keyframes_;
  119. uint16_t id_counter_;
  120. public:
  121. uint8_t feature_mode_;
  122. uint8_t euclidean_length_[kNumChannels];
  123. uint16_t euclidean_shape_[kNumChannels];
  124. private:
  125. int32_t dc_offset_frame_modulation_;
  126. uint32_t magic_number_;
  127. uint8_t padding_[3];
  128. #ifndef TEST
  129. enum SettingsSize {
  130. SETTINGS_SIZE = sizeof(keyframes_) + sizeof(settings_) + \
  131. sizeof(num_keyframes_) + sizeof(id_counter_) + sizeof(feature_mode_) + \
  132. sizeof(euclidean_length_) + sizeof(euclidean_shape_) + \
  133. sizeof(dc_offset_frame_modulation_) + sizeof(magic_number_) + sizeof(padding_)
  134. };
  135. #endif // TEST
  136. uint16_t version_token_;
  137. int16_t position_;
  138. int16_t nearest_keyframe_;
  139. uint16_t dac_code_[kNumChannels];
  140. uint16_t levels_[kNumChannels];
  141. uint16_t immediate_[kNumChannels];
  142. uint8_t color_[3];
  143. static const uint8_t palette_[kNumPaletteEntries][3];
  144. DISALLOW_COPY_AND_ASSIGN(Keyframer);
  145. };
  146. } // namespace frames
  147. #endif // FRAMES_KEYFRAMER_H_