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.

135 lines
4.5KB

  1. /* Copyright 2013-2019 Matt Tytel
  2. *
  3. * vital is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * vital is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with vital. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "wavetable_component.h"
  17. WavetableKeyframe* WavetableComponent::insertNewKeyframe(int position) {
  18. VITAL_ASSERT(position >= 0 && position < vital::kNumOscillatorWaveFrames);
  19. WavetableKeyframe* keyframe = createKeyframe(position);
  20. keyframe->setOwner(this);
  21. keyframe->setPosition(position);
  22. int index = getIndexFromPosition(position);
  23. keyframes_.insert(keyframes_.begin() + index, std::unique_ptr<WavetableKeyframe>(keyframe));
  24. return keyframe;
  25. }
  26. void WavetableComponent::reposition(WavetableKeyframe* keyframe) {
  27. int start_index = indexOf(keyframe);
  28. keyframes_[start_index].release();
  29. keyframes_.erase(keyframes_.begin() + start_index);
  30. int new_index = getIndexFromPosition(keyframe->position());
  31. keyframes_.insert(keyframes_.begin() + new_index, std::unique_ptr<WavetableKeyframe>(keyframe));
  32. }
  33. void WavetableComponent::remove(WavetableKeyframe* keyframe) {
  34. int start_index = indexOf(keyframe);
  35. keyframes_.erase(keyframes_.begin() + start_index);
  36. }
  37. void WavetableComponent::jsonToState(json data) {
  38. keyframes_.clear();
  39. for (json json_keyframe : data["keyframes"]) {
  40. WavetableKeyframe* keyframe = insertNewKeyframe(json_keyframe["position"]);
  41. keyframe->jsonToState(json_keyframe);
  42. }
  43. if (data.count("interpolation_style"))
  44. interpolation_style_ = data["interpolation_style"];
  45. }
  46. json WavetableComponent::stateToJson() {
  47. json keyframes_data;
  48. for (int i = 0; i < keyframes_.size(); ++i)
  49. keyframes_data.emplace_back(keyframes_[i]->stateToJson());
  50. return {
  51. { "keyframes", keyframes_data },
  52. { "type", WavetableComponentFactory::getComponentName(getType()) },
  53. { "interpolation_style", interpolation_style_ }
  54. };
  55. }
  56. void WavetableComponent::reset() {
  57. keyframes_.clear();
  58. insertNewKeyframe(0);
  59. }
  60. void WavetableComponent::interpolate(WavetableKeyframe* dest, float position) {
  61. if (numFrames() == 0)
  62. return;
  63. int index = getIndexFromPosition(position) - 1;
  64. int clamped_index = std::min(std::max(index, 0), numFrames() - 1);
  65. WavetableKeyframe* from_frame = keyframes_[clamped_index].get();
  66. if (index < 0 || index >= numFrames() - 1 || interpolation_style_ == kNone)
  67. dest->copy(from_frame);
  68. else if (interpolation_style_ == kLinear) {
  69. WavetableKeyframe* to_frame = keyframes_[index + 1].get();
  70. int from_position = keyframes_[index]->position();
  71. int to_position = keyframes_[index + 1]->position();
  72. float t = (1.0f * position - from_position) / (to_position - from_position);
  73. dest->interpolate(from_frame, to_frame, t);
  74. }
  75. else if (interpolation_style_ == kCubic) {
  76. int next_index = index + 2;
  77. int prev_index = index - 1;
  78. if (next_index >= numFrames())
  79. next_index = index;
  80. if (prev_index < 0)
  81. prev_index = index + 1;
  82. WavetableKeyframe* to_frame = keyframes_[index + 1].get();
  83. WavetableKeyframe* next_frame = keyframes_[next_index].get();
  84. WavetableKeyframe* prev_frame = keyframes_[prev_index].get();
  85. int from_position = keyframes_[index]->position();
  86. int to_position = keyframes_[index + 1]->position();
  87. float t = (1.0f * position - from_position) / (to_position - from_position);
  88. dest->smoothInterpolate(prev_frame, from_frame, to_frame, next_frame, t);
  89. }
  90. }
  91. int WavetableComponent::getIndexFromPosition(int position) const {
  92. int index = 0;
  93. for (auto& keyframe : keyframes_) {
  94. if (position < keyframe->position())
  95. break;
  96. index++;
  97. }
  98. return index;
  99. }
  100. WavetableKeyframe* WavetableComponent::getFrameAtPosition(int position) {
  101. int index = getIndexFromPosition(position);
  102. if (index < 0 || index >= keyframes_.size())
  103. return nullptr;
  104. return keyframes_[index].get();
  105. }
  106. int WavetableComponent::getLastKeyframePosition() {
  107. if (keyframes_.size() == 0)
  108. return 0;
  109. if (!hasKeyframes())
  110. return vital::kNumOscillatorWaveFrames - 1;
  111. return keyframes_[keyframes_.size() - 1]->position();
  112. }