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.

309 lines
9.1KB

  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 "stmlib/utils/random.h"
  34. #include "frames/resources.h"
  35. namespace frames {
  36. using namespace std;
  37. /* static */
  38. const uint8_t Keyframer::palette_[kNumPaletteEntries][3] = {
  39. { 255, 0, 0 },
  40. { 255, 64, 0 },
  41. { 255, 255, 0 },
  42. { 64, 255, 0 },
  43. { 0, 255, 64 },
  44. { 0, 0, 255 },
  45. { 255, 0, 255 },
  46. { 255, 0, 64 },
  47. };
  48. #ifndef TEST
  49. stmlib::Storage<0x8020000, 4> storage;
  50. stmlib::Storage<0x801f000, 4> preset_storage;
  51. #endif // TEST
  52. void Keyframer::Reset() {
  53. for (uint8_t i = 0; i < kNumChannels; ++i) {
  54. settings_[i].easing_curve = EASING_CURVE_LINEAR;
  55. settings_[i].response = 0;
  56. }
  57. feature_mode_ = 0;
  58. for (int i=0; i<kNumChannels; i++) {
  59. euclidean_length_[i] = 16;
  60. euclidean_shape_[i] = 4000;
  61. }
  62. magic_number_ = kMagicNumber;
  63. dc_offset_frame_modulation_ = 32767;
  64. Clear();
  65. }
  66. void Keyframer::Init() {
  67. #ifndef TEST
  68. if (!storage.ParsimoniousLoad(keyframes_, SETTINGS_SIZE, &version_token_)) {
  69. Reset();
  70. }
  71. #endif // TEST
  72. }
  73. void Keyframer::Save(uint16_t slot) {
  74. #ifndef TEST
  75. if (slot == 0)
  76. storage.ParsimoniousSave(keyframes_, SETTINGS_SIZE, &version_token_);
  77. else
  78. preset_storage.Save(keyframes_, SETTINGS_SIZE, slot - 1);
  79. #endif // TEST
  80. }
  81. void Keyframer::Load(uint16_t slot) {
  82. #ifndef TEST
  83. if (slot == 0){
  84. storage.ParsimoniousLoad(keyframes_, SETTINGS_SIZE, &version_token_);
  85. } else {
  86. int32_t calibration = dc_offset_frame_modulation_;
  87. preset_storage.Load(keyframes_, SETTINGS_SIZE, slot - 1);
  88. // calibration data needs to remain like in the default slot.
  89. dc_offset_frame_modulation_ = calibration;
  90. // lightweight protection against corrupted/empty memory slots
  91. if (magic_number_ != kMagicNumber)
  92. Reset();
  93. }
  94. #endif // TEST
  95. }
  96. void Keyframer::Calibrate(int32_t dc_offset_frame_modulation) {
  97. dc_offset_frame_modulation_ = dc_offset_frame_modulation;
  98. #ifndef TEST
  99. storage.ParsimoniousSave(keyframes_, SETTINGS_SIZE, &version_token_);
  100. #endif // TEST
  101. }
  102. void Keyframer::Clear() {
  103. Keyframe empty;
  104. empty.timestamp = 0;
  105. empty.id = 0;
  106. fill(&empty.values[0], &empty.values[kNumChannels], 0);
  107. fill(&keyframes_[0], &keyframes_[kMaxNumKeyframe], empty);
  108. num_keyframes_ = 0;
  109. id_counter_ = 0;
  110. }
  111. void Keyframer::Randomize() {
  112. for (int i=0; i<kMaxNumKeyframe; i++) {
  113. for (int j=0; j<kNumChannels; j++) {
  114. keyframes_[i].values[j] = stmlib::Random::GetWord();
  115. }
  116. }
  117. }
  118. uint16_t Keyframer::FindKeyframe(uint16_t timestamp) {
  119. if (!num_keyframes_) {
  120. return 0;
  121. }
  122. Keyframe dummy;
  123. dummy.timestamp = timestamp;
  124. return lower_bound(
  125. keyframes_,
  126. keyframes_ + num_keyframes_,
  127. dummy,
  128. KeyframeLess()) - keyframes_;
  129. }
  130. /* static */
  131. uint16_t Keyframer::ConvertToDacCode(uint16_t gain, uint8_t response) {
  132. // Exponential response is easy, straight to the 2164.
  133. int32_t exponential = 65535 - gain;
  134. // Use a lookup table and interpolation to linearize the 2164
  135. int32_t a = lut_vca_linear[gain >> 6];
  136. int32_t b = lut_vca_linear[(gain >> 6) + 1];
  137. int32_t linear = a + ((b - a) * ((gain << 10) & 0xffff) >> 16);
  138. // Blend linear and exponential responses.
  139. uint16_t balance = lut_response_balance[response];
  140. return (linear + ((exponential - linear) * balance >> 15)) >> 4;
  141. }
  142. inline uint16_t Keyframer::Easing(
  143. int32_t from,
  144. int32_t to,
  145. uint32_t scale,
  146. EasingCurve curve) {
  147. int32_t shaped_scale = scale;
  148. if (curve == EASING_CURVE_STEP) {
  149. shaped_scale = scale < 32768 ? 0 : 65535;
  150. } else if (curve >= EASING_CURVE_IN_QUARTIC) {
  151. const uint16_t* easing_curve = lookup_table_table[
  152. curve - EASING_CURVE_IN_QUARTIC];
  153. int32_t scale_a = easing_curve[scale >> 6];
  154. int32_t scale_b = easing_curve[(scale >> 6) + 1];
  155. shaped_scale = scale_a + (((scale_b - scale_a) >> 1) * \
  156. ((scale << 10) & 0xffff) >> 15);
  157. }
  158. return from + ((to - from) * (shaped_scale >> 1) >> 15);
  159. }
  160. uint16_t Keyframer::SampleAnimation(
  161. uint8_t channel,
  162. uint16_t tick,
  163. bool easing) {
  164. uint16_t sample = Easing(
  165. tick > 32768 ? 65535 : 0,
  166. tick > 32768 ? 0 : 65535,
  167. (tick << 1) & 0xffff,
  168. easing ? settings_[channel].easing_curve : EASING_CURVE_LINEAR);
  169. if (!easing) {
  170. int32_t linear = sample;
  171. int32_t exponential = lut_exponential[sample >> 8];
  172. uint16_t balance = lut_response_balance[settings_[channel].response];
  173. sample = linear + ((exponential - linear) * balance >> 15);
  174. }
  175. return sample;
  176. }
  177. int16_t Keyframer::FindNearestKeyframe(uint16_t timestamp, uint16_t tolerance) {
  178. if (!num_keyframes_) {
  179. return -1;
  180. }
  181. uint16_t index = FindKeyframe(timestamp);
  182. uint16_t search_start = index ? index - 1 : 0;
  183. uint16_t search_end = index < num_keyframes_ - 1 ? index + 2 : num_keyframes_;
  184. for (uint16_t i = search_start; i < search_end; ++i) {
  185. uint16_t t = keyframes_[i].timestamp;
  186. int32_t distance = static_cast<int32_t>(t) - static_cast<int32_t>(timestamp);
  187. if (distance < tolerance && -distance < tolerance) {
  188. return i;
  189. }
  190. }
  191. return -1;
  192. }
  193. bool Keyframer::AddKeyframe(uint16_t timestamp, uint16_t* values) {
  194. if (num_keyframes_ == kMaxNumKeyframe) {
  195. return false;
  196. }
  197. uint16_t insertion_point = FindKeyframe(timestamp);
  198. if (insertion_point >= num_keyframes_ ||
  199. keyframes_[insertion_point].timestamp != timestamp) {
  200. for (int16_t i = num_keyframes_ - 1; i >= insertion_point; --i) {
  201. keyframes_[i + 1] = keyframes_[i];
  202. }
  203. keyframes_[insertion_point].timestamp = timestamp;
  204. keyframes_[insertion_point].id = id_counter_++;
  205. ++num_keyframes_;
  206. }
  207. copy(values, values + kNumChannels, keyframes_[insertion_point].values);
  208. return true;
  209. }
  210. bool Keyframer::RemoveKeyframe(uint16_t timestamp) {
  211. if (!num_keyframes_) {
  212. return false;
  213. }
  214. uint16_t splice_point = FindKeyframe(timestamp);
  215. if (keyframes_[splice_point].timestamp != timestamp) {
  216. return false;
  217. }
  218. for (uint16_t i = splice_point; i < num_keyframes_ - 1; ++i) {
  219. keyframes_[i] = keyframes_[i + 1];
  220. }
  221. --num_keyframes_;
  222. return true;
  223. }
  224. void Keyframer::Evaluate(uint16_t timestamp) {
  225. if (!num_keyframes_) {
  226. copy(immediate_, immediate_ + kNumChannels, levels_);
  227. fill(color_, color_ + 3, 0xff);
  228. position_ = -1;
  229. nearest_keyframe_ = -1;
  230. } else {
  231. uint16_t position = FindKeyframe(timestamp);
  232. position_ = position;
  233. // This is where the real interpolation takes place.
  234. volatile int8_t a_index = position == 0 ? num_keyframes_ - 1 :
  235. (position - 1) % num_keyframes_;
  236. int8_t b_index = position % num_keyframes_;
  237. volatile const Keyframe& a = keyframes_[a_index];
  238. volatile const Keyframe& b = keyframes_[b_index];
  239. volatile uint32_t scale;
  240. if (a.timestamp > b.timestamp) {
  241. // wraparound
  242. uint16_t rest = UINT16_MAX - a.timestamp;
  243. if (timestamp > a.timestamp) {
  244. scale = timestamp - a.timestamp;
  245. } else /* if (timestamp < b.timestamp) */ {
  246. scale = rest + timestamp;
  247. }
  248. scale <<= 16;
  249. scale /= rest + b.timestamp;
  250. } else {
  251. // normal
  252. scale = timestamp - a.timestamp;
  253. scale <<= 16;
  254. scale /= (b.timestamp - a.timestamp);
  255. }
  256. for (uint8_t i = 0; i < kNumChannels; ++i) {
  257. int32_t from = a.values[i];
  258. int32_t to = b.values[i];
  259. levels_[i] = Easing(from, to, scale, settings_[i].easing_curve);
  260. }
  261. for (uint8_t i = 0; i < 3; ++i) {
  262. uint8_t a_color = palette_[a.id & (kNumPaletteEntries - 1)][i];
  263. uint8_t b_color = palette_[b.id & (kNumPaletteEntries - 1)][i];
  264. color_[i] = a_color + ((b_color - a_color) * scale >> 16);
  265. }
  266. nearest_keyframe_ = scale < 32768 ? a_index + 1 : b_index + 1;
  267. }
  268. for (uint16_t i = 0; i < kNumChannels; ++i) {
  269. dac_code_[i] = ConvertToDacCode(levels_[i], settings_[i].response);
  270. }
  271. }
  272. } // namespace frames