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.

177 lines
5.0KB

  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 uint8_t kNumPaletteEntries = 8;
  35. enum EasingCurve {
  36. EASING_CURVE_STEP,
  37. EASING_CURVE_LINEAR,
  38. EASING_CURVE_IN_QUARTIC,
  39. EASING_CURVE_OUT_QUARTIC,
  40. EASING_CURVE_SINE,
  41. EASING_CURVE_BOUNCE
  42. };
  43. struct ChannelSettings {
  44. EasingCurve easing_curve;
  45. uint8_t response;
  46. };
  47. struct Keyframe {
  48. uint16_t timestamp;
  49. uint16_t id;
  50. uint16_t values[kNumChannels];
  51. };
  52. struct KeyframeLess {
  53. bool operator()(const Keyframe& lhs, const Keyframe& rhs) {
  54. return lhs.timestamp < rhs.timestamp;
  55. }
  56. };
  57. class Keyframer {
  58. public:
  59. Keyframer() { }
  60. ~Keyframer() { }
  61. void Init();
  62. void Save(uint32_t extra_settings);
  63. void Calibrate(int32_t dc_offset_frame_modulation);
  64. bool AddKeyframe(uint16_t timestamp, uint16_t* values);
  65. bool RemoveKeyframe(uint16_t timestamp);
  66. int16_t FindNearestKeyframe(uint16_t timestamp, uint16_t tolerance);
  67. inline void set_immediate(uint8_t channel, uint16_t value) {
  68. immediate_[channel] = value;
  69. }
  70. inline uint16_t dac_code(uint8_t channel) const {
  71. return dac_code_[channel];
  72. }
  73. inline uint16_t level(uint8_t channel) const {
  74. return levels_[channel];
  75. }
  76. inline uint8_t color(uint8_t component) const {
  77. return color_[component];
  78. }
  79. inline const uint8_t* color() const {
  80. return &color_[0];
  81. }
  82. void Evaluate(uint16_t timestamp);
  83. inline ChannelSettings* mutable_settings(uint8_t channel) {
  84. return &settings_[channel];
  85. }
  86. inline const ChannelSettings& mutable_settings(uint8_t channel) const {
  87. return settings_[channel];
  88. }
  89. inline Keyframe* mutable_keyframe(uint16_t index) {
  90. return &keyframes_[index];
  91. }
  92. inline const Keyframe& keyframe(uint16_t index) const {
  93. return keyframes_[index];
  94. }
  95. inline uint16_t num_keyframes() const { return num_keyframes_; }
  96. uint16_t Easing(int32_t from, int32_t to, uint32_t scale, EasingCurve curve);
  97. // This creates a sample animation (between 0 to 65535 and back to 0) used
  98. // for animating the LED when editing the easing curve or response.
  99. uint16_t SampleAnimation(uint8_t channel, uint16_t tick, bool easing);
  100. inline int16_t position() const { return position_; }
  101. inline int16_t nearest_keyframe() const { return nearest_keyframe_; }
  102. void Clear();
  103. static uint16_t ConvertToDacCode(uint16_t gain, uint8_t response);
  104. // In addition to the keyframer data, this extra word stores in
  105. // persistent storage things like sequencer mode on/off and
  106. // poly lfo mode on/off states.
  107. inline uint32_t extra_settings() const { return extra_settings_; }
  108. inline int32_t dc_offset_frame_modulation() const {
  109. return dc_offset_frame_modulation_;
  110. }
  111. private:
  112. uint16_t FindKeyframe(uint16_t timestamp);
  113. Keyframe keyframes_[kMaxNumKeyframe];
  114. ChannelSettings settings_[kNumChannels];
  115. uint16_t num_keyframes_;
  116. uint16_t id_counter_;
  117. uint32_t extra_settings_;
  118. int32_t dc_offset_frame_modulation_;
  119. #ifndef TEST
  120. enum SettingsSize {
  121. SETTINGS_SIZE = sizeof(Keyframe)*kMaxNumKeyframe/*keyframes_*/ + sizeof(ChannelSettings)*kNumChannels/*settings_*/ + \
  122. sizeof(uint16_t)/*num_keyframes_*/ + sizeof(uint16_t)/*id_counter_*/ + sizeof(uint32_t)/*extra_settings_*/ + \
  123. sizeof(int32_t)/*dc_offset_frame_modulation_*/
  124. };
  125. #endif // TEST
  126. uint16_t version_token_;
  127. int16_t position_;
  128. int16_t nearest_keyframe_;
  129. uint16_t dac_code_[kNumChannels];
  130. uint16_t levels_[kNumChannels];
  131. uint16_t immediate_[kNumChannels];
  132. uint8_t color_[3];
  133. static const uint8_t palette_[kNumPaletteEntries][3];
  134. DISALLOW_COPY_AND_ASSIGN(Keyframer);
  135. };
  136. } // namespace frames
  137. #endif // FRAMES_KEYFRAMER_H_