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.

261 lines
8.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. #include "frames/keyframer.h"
  29. #include <algorithm>
  30. #ifndef TEST
  31. #include "stmlib/system/storage.h"
  32. #endif // TEST
  33. #include "frames/resources.h"
  34. namespace frames {
  35. using namespace std;
  36. /* static */
  37. const uint8_t Keyframer::palette_[kNumPaletteEntries][3] = {
  38. { 255, 0, 0 },
  39. { 255, 64, 0 },
  40. { 255, 255, 0 },
  41. { 64, 255, 0 },
  42. { 0, 255, 64 },
  43. { 0, 0, 255 },
  44. { 255, 0, 255 },
  45. { 255, 0, 64 },
  46. };
  47. #ifndef TEST
  48. stmlib::Storage<0x8020000, 4> storage;
  49. #endif // TEST
  50. void Keyframer::Init() {
  51. #ifndef TEST
  52. if (!storage.ParsimoniousLoad(keyframes_, SETTINGS_SIZE, &version_token_)) {
  53. for (uint8_t i = 0; i < kNumChannels; ++i) {
  54. settings_[i].easing_curve = EASING_CURVE_LINEAR;
  55. settings_[i].response = 0;
  56. }
  57. extra_settings_ = 0;
  58. dc_offset_frame_modulation_ = 32767;
  59. Clear();
  60. }
  61. #endif // TEST
  62. }
  63. void Keyframer::Save(uint32_t extra_settings) {
  64. extra_settings_ = extra_settings;
  65. #ifndef TEST
  66. storage.ParsimoniousSave(keyframes_, SETTINGS_SIZE, &version_token_);
  67. #endif // TEST
  68. }
  69. void Keyframer::Calibrate(int32_t dc_offset_frame_modulation) {
  70. dc_offset_frame_modulation_ = dc_offset_frame_modulation;
  71. #ifndef TEST
  72. storage.ParsimoniousSave(keyframes_, SETTINGS_SIZE, &version_token_);
  73. #endif // TEST
  74. }
  75. void Keyframer::Clear() {
  76. Keyframe empty;
  77. empty.timestamp = 0;
  78. empty.id = 0;
  79. fill(&empty.values[0], &empty.values[kNumChannels], 0);
  80. fill(&keyframes_[0], &keyframes_[kMaxNumKeyframe], empty);
  81. num_keyframes_ = 0;
  82. id_counter_ = 0;
  83. }
  84. uint16_t Keyframer::FindKeyframe(uint16_t timestamp) {
  85. if (!num_keyframes_) {
  86. return 0;
  87. }
  88. Keyframe dummy;
  89. dummy.timestamp = timestamp;
  90. return lower_bound(
  91. keyframes_,
  92. keyframes_ + num_keyframes_,
  93. dummy,
  94. KeyframeLess()) - keyframes_;
  95. }
  96. /* static */
  97. uint16_t Keyframer::ConvertToDacCode(uint16_t gain, uint8_t response) {
  98. // Exponential response is easy, straight to the 2164.
  99. int32_t exponential = 65535 - gain;
  100. // Use a lookup table and interpolation to linearize the 2164
  101. int32_t a = lut_vca_linear[gain >> 6];
  102. int32_t b = lut_vca_linear[(gain >> 6) + 1];
  103. int32_t linear = a + ((b - a) * ((gain << 10) & 0xffff) >> 16);
  104. // Blend linear and exponential responses.
  105. uint16_t balance = lut_response_balance[response];
  106. return (linear + ((exponential - linear) * balance >> 15)) >> 4;
  107. }
  108. inline uint16_t Keyframer::Easing(
  109. int32_t from,
  110. int32_t to,
  111. uint32_t scale,
  112. EasingCurve curve) {
  113. int32_t shaped_scale = scale;
  114. if (curve == EASING_CURVE_STEP) {
  115. shaped_scale = scale < 32768 ? 0 : 65535;
  116. } else if (curve >= EASING_CURVE_IN_QUARTIC) {
  117. const uint16_t* easing_curve = lookup_table_table[
  118. curve - EASING_CURVE_IN_QUARTIC];
  119. int32_t scale_a = easing_curve[scale >> 6];
  120. int32_t scale_b = easing_curve[(scale >> 6) + 1];
  121. shaped_scale = scale_a + (((scale_b - scale_a) >> 1) * \
  122. ((scale << 10) & 0xffff) >> 15);
  123. }
  124. return from + ((to - from) * (shaped_scale >> 1) >> 15);
  125. }
  126. uint16_t Keyframer::SampleAnimation(
  127. uint8_t channel,
  128. uint16_t tick,
  129. bool easing) {
  130. uint16_t sample = Easing(
  131. tick > 32768 ? 65535 : 0,
  132. tick > 32768 ? 0 : 65535,
  133. (tick << 1) & 0xffff,
  134. easing ? settings_[channel].easing_curve : EASING_CURVE_LINEAR);
  135. if (!easing) {
  136. int32_t linear = sample;
  137. int32_t exponential = lut_exponential[sample >> 8];
  138. uint16_t balance = lut_response_balance[settings_[channel].response];
  139. sample = linear + ((exponential - linear) * balance >> 15);
  140. }
  141. return sample;
  142. }
  143. int16_t Keyframer::FindNearestKeyframe(uint16_t timestamp, uint16_t tolerance) {
  144. if (!num_keyframes_) {
  145. return -1;
  146. }
  147. uint16_t index = FindKeyframe(timestamp);
  148. uint16_t search_start = index ? index - 1 : 0;
  149. uint16_t search_end = index < num_keyframes_ - 1 ? index + 2 : num_keyframes_;
  150. for (uint16_t i = search_start; i < search_end; ++i) {
  151. uint16_t t = keyframes_[i].timestamp;
  152. int32_t distance = static_cast<int32_t>(t) - static_cast<int32_t>(timestamp);
  153. if (distance < tolerance && -distance < tolerance) {
  154. return i;
  155. }
  156. }
  157. return -1;
  158. }
  159. bool Keyframer::AddKeyframe(uint16_t timestamp, uint16_t* values) {
  160. if (num_keyframes_ == kMaxNumKeyframe) {
  161. return false;
  162. }
  163. uint16_t insertion_point = FindKeyframe(timestamp);
  164. if (insertion_point >= num_keyframes_ ||
  165. keyframes_[insertion_point].timestamp != timestamp) {
  166. for (int16_t i = num_keyframes_ - 1; i >= insertion_point; --i) {
  167. keyframes_[i + 1] = keyframes_[i];
  168. }
  169. keyframes_[insertion_point].timestamp = timestamp;
  170. keyframes_[insertion_point].id = id_counter_++;
  171. ++num_keyframes_;
  172. }
  173. copy(values, values + kNumChannels, keyframes_[insertion_point].values);
  174. return true;
  175. }
  176. bool Keyframer::RemoveKeyframe(uint16_t timestamp) {
  177. if (!num_keyframes_) {
  178. return false;
  179. }
  180. uint16_t splice_point = FindKeyframe(timestamp);
  181. if (keyframes_[splice_point].timestamp != timestamp) {
  182. return false;
  183. }
  184. for (uint16_t i = splice_point; i < num_keyframes_ - 1; ++i) {
  185. keyframes_[i] = keyframes_[i + 1];
  186. }
  187. --num_keyframes_;
  188. return true;
  189. }
  190. void Keyframer::Evaluate(uint16_t timestamp) {
  191. if (!num_keyframes_) {
  192. copy(immediate_, immediate_ + kNumChannels, levels_);
  193. fill(color_, color_ + 3, 0xff);
  194. position_ = -1;
  195. nearest_keyframe_ = -1;
  196. } else {
  197. uint16_t position = FindKeyframe(timestamp);
  198. position_ = position;
  199. // Check for the areas before the first keyframe, and after the last
  200. // keyframe.
  201. if (position == 0 || position == num_keyframes_) {
  202. const Keyframe& source = keyframes_[position == 0 ? 0 : num_keyframes_ - 1];
  203. copy(source.values, source.values + kNumChannels, levels_);
  204. const uint8_t* palette = palette_[source.id & (kNumPaletteEntries - 1)];
  205. copy(palette, palette + 3, color_);
  206. } else {
  207. // This is where the real interpolation takes place.
  208. const Keyframe& a = keyframes_[position - 1];
  209. const Keyframe& b = keyframes_[position];
  210. uint32_t scale = timestamp - a.timestamp;
  211. scale <<= 16;
  212. scale /= (b.timestamp - a.timestamp);
  213. for (uint8_t i = 0; i < kNumChannels; ++i) {
  214. int32_t from = a.values[i];
  215. int32_t to = b.values[i];
  216. levels_[i] = Easing(from, to, scale, settings_[i].easing_curve);
  217. }
  218. for (uint8_t i = 0; i < 3; ++i) {
  219. uint8_t a_color = palette_[a.id & (kNumPaletteEntries - 1)][i];
  220. uint8_t b_color = palette_[b.id & (kNumPaletteEntries - 1)][i];
  221. color_[i] = a_color + ((b_color - a_color) * scale >> 16);
  222. }
  223. }
  224. uint16_t t_this = timestamp - \
  225. (position == 0 ? 0 : keyframes_[position - 1].timestamp);
  226. uint16_t t_next = keyframes_[position].timestamp - timestamp;
  227. nearest_keyframe_ = t_next < t_this ? position + 1 : position;
  228. }
  229. for (uint16_t i = 0; i < kNumChannels; ++i) {
  230. dac_code_[i] = ConvertToDacCode(levels_[i], settings_[i].response);
  231. }
  232. }
  233. } // namespace frames