30 std::span<const ParamSnapshotEntry> initial_values = {})
34 for (
const auto& initial : initial_values) {
35 add_or_update(initial.param_id, initial.value,
true);
38 for (
const auto& event : events_) {
39 ensure_event_entry(event.param_id);
44 if (sample_offset < position_)
return;
46 while (next_event_ < events_.size() &&
47 events_[next_event_].sample_offset <= sample_offset) {
48 update_ramps_to(events_[next_event_].sample_offset);
49 apply_event(events_[next_event_]);
53 update_ramps_to(sample_offset);
54 position_ = sample_offset;
58 if (
const auto* entry = find_entry(
id))
return entry->value;
59 return store_ ? store_->get_value(
id) : 0.0f;
63 if (
const auto* entry = find_entry(
id)) {
64 return value_for_entry_at(*entry, sample_offset);
66 return store_ ? store_->get_value(
id) : 0.0f;
70 if (
const auto* entry = find_entry(
id))
return entry->ramping;
80 if (
const auto* entry = find_entry(
id))
return entry->ramp_target_value;
84 if (
const auto* entry = find_entry(
id))
return entry->ramp_end_sample_offset;
89 return find_entry(
id) !=
nullptr;
99 float ramp_start_value = 0.0f;
100 float ramp_target_value = 0.0f;
101 int32_t ramp_start_sample_offset = 0;
102 int32_t ramp_end_sample_offset = 0;
103 bool ramping =
false;
106 Entry* find_entry(
ParamID id) {
107 for (std::size_t i = 0; i < entry_count_; ++i) {
108 if (entries_[i].param_id ==
id)
return &entries_[i];
113 const Entry* find_entry(
ParamID id)
const {
114 for (std::size_t i = 0;
i < entry_count_; ++
i) {
115 if (entries_[i].param_id ==
id)
return &entries_[
i];
122 if (
const auto* info = store_->info(
id)) {
134 bool is_registered(
ParamID id)
const {
135 return store_ && store_->info(
id) !=
nullptr;
138 void add_or_update(
ParamID id,
float value,
bool allow_unregistered) {
139 if (!allow_unregistered && !is_registered(
id))
return;
140 if (
auto* entry = find_entry(
id)) {
141 entry->value = clamp_value(
id,
value);
142 entry->ramping =
false;
145 if (entry_count_ >= entries_.size())
return;
146 const float clamped = clamp_value(
id,
value);
147 entries_[entry_count_++] = Entry{
150 .ramp_start_value = clamped,
151 .ramp_target_value = clamped,
155 void ensure_event_entry(
ParamID id) {
156 if (find_entry(
id) !=
nullptr)
return;
157 if (!is_registered(
id))
return;
158 add_or_update(
id, store_->get_value(
id),
false);
161 float value_for_entry_at(
const Entry& entry, int32_t sample_offset)
const {
162 if (!entry.ramping)
return entry.value;
163 if (sample_offset <= entry.ramp_start_sample_offset) {
164 return entry.ramp_start_value;
166 if (sample_offset >= entry.ramp_end_sample_offset) {
167 return entry.ramp_target_value;
170 const auto elapsed =
static_cast<float>(sample_offset - entry.ramp_start_sample_offset);
171 const auto duration =
static_cast<float>(entry.ramp_end_sample_offset
172 - entry.ramp_start_sample_offset);
173 const float t = duration > 0.0f ? (elapsed / duration) : 1.0f;
174 return entry.ramp_start_value + (entry.ramp_target_value - entry.ramp_start_value) * t;
177 void update_ramps_to(int32_t sample_offset) {
178 for (std::size_t i = 0;
i < entry_count_; ++
i) {
179 auto& entry = entries_[
i];
180 if (!entry.ramping)
continue;
181 entry.value = value_for_entry_at(entry, sample_offset);
182 if (sample_offset >= entry.ramp_end_sample_offset) {
183 entry.value = entry.ramp_target_value;
184 entry.ramping =
false;
189 int32_t ramp_end_for(
const ParameterEvent& event)
const {
190 if (event.ramp_duration_sample_frames <= 0)
return event.sample_offset;
191 const auto max = std::numeric_limits<int32_t>::max();
192 if (event.sample_offset > max - event.ramp_duration_sample_frames)
return max;
193 return event.sample_offset +
event.ramp_duration_sample_frames;
196 void apply_event(
const ParameterEvent& event) {
197 if (!is_registered(event.param_id))
return;
198 ensure_event_entry(event.param_id);
199 auto* entry = find_entry(event.param_id);
202 const float target = clamp_value(event.param_id, event.value);
203 if (event.ramp_duration_sample_frames <= 0) {
204 entry->value = target;
205 entry->ramping =
false;
209 entry->ramp_start_value = entry->value;
210 entry->ramp_target_value = target;
211 entry->ramp_start_sample_offset =
event.sample_offset;
212 entry->ramp_end_sample_offset = ramp_end_for(event);
213 entry->ramping = entry->ramp_end_sample_offset > entry->ramp_start_sample_offset;
214 if (!entry->ramping) {
215 entry->value = target;
219 const StateStore* store_ =
nullptr;
220 std::span<const ParameterEvent> events_;
221 std::size_t next_event_ = 0;
222 std::array<Entry, ParameterEventQueue::kCapacity> entries_{};
223 std::size_t entry_count_ = 0;
224 int32_t position_ = std::numeric_limits<int32_t>::min();
Definition param_cursor.hpp:21
ParamID param_id
Definition param_cursor.hpp:22
float value
Definition param_cursor.hpp:23