Vital
Loading...
Searching...
No Matches
wavetable_component.cpp
Go to the documentation of this file.
1/*
2Summary:
3WavetableComponent is the base class for elements that produce or modify wavetables. It manages keyframes representing waveform states at certain positions, and supports interpolation between these states using none, linear, or cubic methods. By serializing and deserializing keyframes, it integrates smoothly with preset systems. Interpolation ensures smooth transitions across the wavetable dimension, enabling dynamic and evolving sounds.
4 */
5
7
9 VITAL_ASSERT(position >= 0 && position < vital::kNumOscillatorWaveFrames);
10
11 // Create a new keyframe for the given position and insert it at the correct sorted position.
12 WavetableKeyframe* keyframe = createKeyframe(position);
13 keyframe->setOwner(this);
14 keyframe->setPosition(position);
15
16 int index = getIndexFromPosition(position);
17 keyframes_.insert(keyframes_.begin() + index, std::unique_ptr<WavetableKeyframe>(keyframe));
18 return keyframe;
19}
20
22 // Remove and re-insert a keyframe after its position changed to maintain sorted order.
23 int start_index = indexOf(keyframe);
24 keyframes_[start_index].release();
25 keyframes_.erase(keyframes_.begin() + start_index);
26
27 int new_index = getIndexFromPosition(keyframe->position());
28 keyframes_.insert(keyframes_.begin() + new_index, std::unique_ptr<WavetableKeyframe>(keyframe));
29}
30
32 // Erase a keyframe from the vector.
33 int start_index = indexOf(keyframe);
34 keyframes_.erase(keyframes_.begin() + start_index);
35}
36
38 // Clears current keyframes and load them from the JSON structure.
39 keyframes_.clear();
40 for (json json_keyframe : data["keyframes"]) {
41 WavetableKeyframe* keyframe = insertNewKeyframe(json_keyframe["position"]);
42 keyframe->jsonToState(json_keyframe);
43 }
44
45 if (data.count("interpolation_style"))
46 interpolation_style_ = data["interpolation_style"];
47}
48
50 // Serialize all keyframes and the component's interpolation style.
51 json keyframes_data;
52 for (int i = 0; i < keyframes_.size(); ++i)
53 keyframes_data.emplace_back(keyframes_[i]->stateToJson());
54
55 return {
56 { "keyframes", keyframes_data },
58 { "interpolation_style", interpolation_style_ }
59 };
60}
61
63 // Clear all keyframes and add a default one at position 0.
64 keyframes_.clear();
66}
67
69 // Given a position, find the appropriate keyframes to interpolate between.
70 if (numFrames() == 0)
71 return;
72
73 int index = getIndexFromPosition(position) - 1;
74 int clamped_index = std::min(std::max(index, 0), numFrames() - 1);
75 WavetableKeyframe* from_frame = keyframes_[clamped_index].get();
76
77 // Depending on the interpolation style, copy, linear interpolate, or cubic interpolate.
78 if (index < 0 || index >= numFrames() - 1 || interpolation_style_ == kNone)
79 dest->copy(from_frame);
80 else if (interpolation_style_ == kLinear) {
81 WavetableKeyframe* to_frame = keyframes_[index + 1].get();
82 int from_position = keyframes_[index]->position();
83 int to_position = keyframes_[index + 1]->position();
84 float t = (1.0f * position - from_position) / (to_position - from_position);
85 dest->interpolate(from_frame, to_frame, t);
86 }
87 else if (interpolation_style_ == kCubic) {
88 // Cubic interpolation uses prev and next frames as well.
89 int next_index = index + 2;
90 int prev_index = index - 1;
91 if (next_index >= numFrames())
92 next_index = index;
93 if (prev_index < 0)
94 prev_index = index + 1;
95
96 WavetableKeyframe* to_frame = keyframes_[index + 1].get();
97 WavetableKeyframe* next_frame = keyframes_[next_index].get();
98 WavetableKeyframe* prev_frame = keyframes_[prev_index].get();
99
100 int from_position = keyframes_[index]->position();
101 int to_position = keyframes_[index + 1]->position();
102 float t = (1.0f * position - from_position) / (to_position - from_position);
103 dest->smoothInterpolate(prev_frame, from_frame, to_frame, next_frame, t);
104 }
105}
106
108 // Returns the insertion index to keep keyframes sorted by their position.
109 int index = 0;
110 for (auto& keyframe : keyframes_) {
111 if (position < keyframe->position())
112 break;
113 index++;
114 }
115
116 return index;
117}
118
120 int index = getIndexFromPosition(position);
121 if (index < 0 || index >= keyframes_.size())
122 return nullptr;
123
124 return keyframes_[index].get();
125}
126
128 if (keyframes_.size() == 0)
129 return 0;
130 if (!hasKeyframes())
132 return keyframes_[keyframes_.size() - 1]->position();
133}
static std::string getComponentName(ComponentType type)
Gets the human-readable name of a component from its enumerated type.
Definition wavetable_component_factory.cpp:75
int numFrames() const
Gets the number of keyframes.
Definition wavetable_component.h:155
virtual WavetableKeyframe * createKeyframe(int position)=0
Creates a new keyframe at a given position.
@ kLinear
Linear interpolation between adjacent keyframes.
Definition wavetable_component.h:40
@ kNone
No interpolation, just jumps between keyframes.
Definition wavetable_component.h:39
@ kCubic
Cubic interpolation for smoother transitions.
Definition wavetable_component.h:41
virtual json stateToJson()
Serializes the component’s state and all keyframes to a JSON object.
Definition wavetable_component.cpp:49
void interpolate(WavetableKeyframe *dest, float position)
Interpolates a destination keyframe at a given position.
Definition wavetable_component.cpp:68
void reset()
Clears all keyframes and inserts a default one at position 0.
Definition wavetable_component.cpp:62
WavetableKeyframe * insertNewKeyframe(int position)
Inserts a new keyframe at the given position, creating and sorting it into the array.
Definition wavetable_component.cpp:8
virtual void jsonToState(json data)
Restores the component’s state from a JSON object.
Definition wavetable_component.cpp:37
int getLastKeyframePosition()
Gets the highest position among all keyframes.
Definition wavetable_component.cpp:127
int indexOf(WavetableKeyframe *keyframe) const
Finds the index of a given keyframe.
Definition wavetable_component.h:163
std::vector< std::unique_ptr< WavetableKeyframe > > keyframes_
The list of keyframes sorted by position.
Definition wavetable_component.h:219
WavetableKeyframe * getFrameAtPosition(int position)
Gets a keyframe by position if one matches exactly, or nullptr otherwise.
Definition wavetable_component.cpp:119
virtual WavetableComponentFactory::ComponentType getType()=0
Returns the type of this WavetableComponent.
int getIndexFromPosition(int position) const
Finds the insertion index for a given position to keep keyframes sorted.
Definition wavetable_component.cpp:107
void remove(WavetableKeyframe *keyframe)
Removes a specific keyframe from the component.
Definition wavetable_component.cpp:31
virtual bool hasKeyframes()
Indicates whether this component relies on multiple keyframes.
Definition wavetable_component.h:108
void reposition(WavetableKeyframe *keyframe)
Repositions a keyframe in the keyframe list after its position changed.
Definition wavetable_component.cpp:21
InterpolationStyle interpolation_style_
Current interpolation style (none, linear, cubic).
Definition wavetable_component.h:220
Represents a single state of a waveform at a specific position in a wavetable.
Definition wavetable_keyframe.h:35
int position() const
Gets the wavetable frame position of this keyframe.
Definition wavetable_keyframe.h:81
void setPosition(int position)
Sets the frame position of this keyframe.
Definition wavetable_keyframe.h:88
virtual void smoothInterpolate(const WavetableKeyframe *prev_keyframe, const WavetableKeyframe *from_keyframe, const WavetableKeyframe *to_keyframe, const WavetableKeyframe *next_keyframe, float t)
Performs a smooth (cubic) interpolation using four keyframes for even smoother transitions.
Definition wavetable_keyframe.h:121
virtual void interpolate(const WavetableKeyframe *from_keyframe, const WavetableKeyframe *to_keyframe, float t)=0
Linearly interpolates between two keyframes.
virtual void copy(const WavetableKeyframe *keyframe)=0
Copies the state from another keyframe of the same type.
void setOwner(WavetableComponent *owner)
Sets the owner of this keyframe.
Definition wavetable_keyframe.h:159
virtual void jsonToState(json data)
Restores the keyframe's state from a JSON object.
Definition wavetable_keyframe.cpp:41
#define VITAL_ASSERT(x)
Definition common.h:11
nlohmann::json json
Definition line_generator.h:7
constexpr int kNumOscillatorWaveFrames
Number of wave frames in each oscillator’s wavetable.
Definition synth_constants.h:19