Vital
Loading...
Searching...
No Matches
wavetable_group.cpp
Go to the documentation of this file.
1/*
2Summary:
3WavetableGroup manages a collection of WavetableComponents, each potentially generating or modifying waveforms. It allows adding, removing, and reordering components, provides methods to render their combined output at any position in the wavetable, and handles serialization. By grouping components, it supports layering and complex combinations that form part of a larger WavetableCreator pipeline.
4 */
5
6#include "wavetable_group.h"
7#include "synth_constants.h"
8#include "wave_frame.h"
9#include "wave_source.h"
10#include "wavetable.h"
11
13 for (int i = 0; i < components_.size(); ++i) {
14 if (components_[i].get() == component)
15 return i;
16 }
17 return -1;
18}
19
20void WavetableGroup::moveUp(int index) {
21 // Swap the component at index with the one above it, if possible.
22 if (index <= 0)
23 return;
24
25 components_[index].swap(components_[index - 1]);
26}
27
28void WavetableGroup::moveDown(int index) {
29 // Swap the component at index with the one below it, if possible.
30 if (index < 0 || index >= components_.size() - 1)
31 return;
32
33 components_[index].swap(components_[index + 1]);
34}
35
37 if (index < 0 || index >= components_.size())
38 return;
39
40 std::unique_ptr<WavetableComponent> component = std::move(components_[index]);
41 components_.erase(components_.begin() + index);
42}
43
45 // Clear all components and load a default configuration.
46 components_.clear();
48}
49
51 // Allow each component to do any precomputation before rendering.
52 for (auto& component : components_)
53 component->prerender();
54}
55
57 // Checks if all components are Shepard tone sources.
58 for (auto& component : components_) {
59 if (component->getType() != WavetableComponentFactory::kShepardToneSource)
60 return false;
61 }
62
63 return true;
64}
65
66void WavetableGroup::render(vital::WaveFrame* wave_frame, float position) const {
67 // Render all components and combine their outputs into wave_frame.
68 wave_frame->index = position;
69
70 for (auto& component : components_)
71 component->render(wave_frame, position);
72}
73
75 // Fill the wavetable by rendering each frame from 0 to kNumOscillatorWaveFrames - 1.
76 for (int i = 0; i < vital::kNumOscillatorWaveFrames; ++i) {
78
79 for (auto& component : components_)
80 component->render(&compute_frame_, i);
81
82 wavetable->loadWaveFrame(&compute_frame_);
83 }
84}
85
87 // Create a simple default group with a basic wave source that produces a linear ramp.
88 WaveSource* wave_source = new WaveSource();
89 wave_source->insertNewKeyframe(0);
90 vital::WaveFrame* wave_frame = wave_source->getWaveFrame(0);
91 for (int i = 0; i < vital::WaveFrame::kWaveformSize; ++i) {
92 float t = i / (vital::WaveFrame::kWaveformSize - 1.0f);
94 wave_frame->time_domain[half_shift] = 1.0f - 2.0f * t;
95 }
96 wave_frame->toFrequencyDomain();
97
98 addComponent(wave_source);
99}
100
102 // Find the maximum keyframe position among all components in this group.
103 int last_position = 0;
104 for (auto& component : components_)
105 last_position = std::max(last_position, component->getLastKeyframePosition());
106
107 return last_position;
108}
109
111 // Serialize all components in the group.
112 json json_components;
113 for (auto& component : components_) {
114 json json_component = component->stateToJson();
115 json_components.push_back(json_component);
116 }
117
118 return { { "components", json_components } };
119}
120
122 // Clear existing components and restore from JSON data.
123 components_.clear();
124
125 json json_components = data["components"];
126 for (json json_component : json_components) {
127 std::string type = json_component["type"];
129 component->jsonToState(json_component);
130 addComponent(component);
131 }
132}
A WavetableComponent that acts as a direct source of waveforms.
Definition wave_source.h:25
vital::WaveFrame * getWaveFrame(int index)
Gets a WaveFrame from a specified keyframe index.
Definition wave_source.cpp:47
static WavetableComponent * createComponent(ComponentType type)
Creates a new WavetableComponent instance of a given enumerated type.
Definition wavetable_component_factory.cpp:19
@ kShepardToneSource
Definition wavetable_component_factory.h:33
A base class representing a component in a wavetable synthesis chain.
Definition wavetable_component.h:32
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
void reset()
Clears all components and loads a default group configuration.
Definition wavetable_group.cpp:44
void jsonToState(json data)
Restores this group's state from a JSON object.
Definition wavetable_group.cpp:121
void addComponent(WavetableComponent *component)
Adds a new WavetableComponent to this group.
Definition wavetable_group.h:44
void moveUp(int index)
Moves a component one position up in the ordering.
Definition wavetable_group.cpp:20
void renderTo(vital::Wavetable *wavetable)
Renders the entire group directly into a Wavetable object.
Definition wavetable_group.cpp:74
int getComponentIndex(WavetableComponent *component)
Gets the index of a particular WavetableComponent within this group.
Definition wavetable_group.cpp:12
json stateToJson()
Serializes this group's state, including all its components, to JSON.
Definition wavetable_group.cpp:110
void prerender()
Allows components to precompute any necessary data before rendering.
Definition wavetable_group.cpp:50
int getLastKeyframePosition()
Gets the largest keyframe position among all components in the group.
Definition wavetable_group.cpp:101
void render(vital::WaveFrame *wave_frame, float position) const
Renders the combined waveform for a given position from all components.
Definition wavetable_group.cpp:66
void removeComponent(int index)
Removes a component at a given index.
Definition wavetable_group.cpp:36
bool isShepardTone()
Determines if all components in this group produce a Shepard tone.
Definition wavetable_group.cpp:56
vital::WaveFrame compute_frame_
Temporary WaveFrame for combining component outputs.
Definition wavetable_group.h:151
void loadDefaultGroup()
Loads a default group configuration (e.g., a basic wave source).
Definition wavetable_group.cpp:86
std::vector< std::unique_ptr< WavetableComponent > > components_
The list of components in this group.
Definition wavetable_group.h:152
void moveDown(int index)
Moves a component one position down in the ordering.
Definition wavetable_group.cpp:28
Represents a single frame of a wavetable, containing both time-domain and frequency-domain data.
Definition wave_frame.h:16
void toFrequencyDomain()
Converts the currently loaded time-domain data into frequency-domain representation.
Definition wave_frame.cpp:64
static constexpr int kWaveformSize
The size of the waveform (number of samples per frame).
Definition wave_frame.h:21
mono_float time_domain[2 *kWaveformSize]
The time-domain data, extended buffer size for FFT alignment.
Definition wave_frame.h:124
int index
The index of this frame in a wavetable.
Definition wave_frame.h:121
A class representing a wavetable, holding multiple frames of waveforms and their frequency-domain rep...
Definition wavetable.h:20
void loadWaveFrame(const WaveFrame *wave_frame)
Load a WaveFrame into the wavetable at the frame index specified by the WaveFrame.
Definition wavetable.cpp:89
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