19 "the render path must bound an automated fader by exactly the range the "
20 "document accepts for a static one, or a curve could ask for a gain the "
21 "model refuses to store");
52 return value <= 0.0f ? 0.0f : 1.0f;
57 if (!(value >= -1.0f))
58 return value <= -1.0f ? -1.0f : 0.0f;
59 return value > 1.0f ? 1.0f : value;
71 return {pan > 0.0f ? 1.0f - pan : 1.0f, pan < 0.0f ? 1.0f + pan : 1.0f};
78 std::size_t channel_count)
noexcept {
79 if (channel_count < 2)
82 return channel % 2u == 0u ? gains.left : gains.right;
94 program_ = program && !program->empty() ? program :
nullptr;
102 return program_ !=
nullptr;
120 const auto tick = cold_ ? tempo_.seek(sample).tick : tempo_.advance(sample).tick;
122 if (sample < program_->segments().front().start_sample)
123 return program_->leading_value();
132 const auto segments = program_->segments();
134 const auto found = std::upper_bound(
135 segments.begin(), segments.end(), tick,
138 static_cast<long double>(segment.end_tick.value);
141 found == segments.end()
142 ? segments.size() - 1u
143 :
static_cast<std::size_t
>(found - segments.begin());
146 while (segment_index_ + 1u < segments.size() &&
147 tick >=
static_cast<long double>(
148 segments[segment_index_].end_tick.value))
151 if (tick <
static_cast<long double>(segments.front().start_tick.value))
152 return program_->leading_value();
153 const auto& segment = segments[segment_index_];
154 if (segment.start_tick == segment.end_tick)
155 return segment.end_value;
156 const auto start =
static_cast<long double>(segment.start_tick.value);
157 const auto end =
static_cast<long double>(segment.end_tick.value);
159 return segment.start_value;
161 return segment.end_value;
163 return segment.start_value;
164 const auto fraction = std::clamp((tick - start) / (end - start), 0.0L, 1.0L);
165 const auto bend =
static_cast<long double>(segment.curvature);
166 const auto quadratic =
167 bend >= 0.0L ? fraction * fraction : std::fma(-fraction, fraction, 2.0L * fraction);
168 const auto shaped = std::fma(std::abs(bend), quadratic - fraction, fraction);
169 return static_cast<float>(std::fma(
static_cast<long double>(segment.end_value) -
170 static_cast<long double>(segment.start_value),
171 shaped,
static_cast<long double>(segment.start_value)));
176 float constant_ = 1.0f;
178 std::size_t segment_index_ = 0;
Immutable tick- and sample-domain form of one automation lane.
Definition automation_program.hpp:55
Streams one mixer control's value in timeline-sample order without allocating.
Definition track_mixer_program.hpp:91
bool automated() const noexcept
Whether any position can yield something other than the constant.
Definition track_mixer_program.hpp:101
float value_at_tick(long double tick) noexcept
Evaluates a host-projected fractional document tick without first quantizing it through the integer s...
Definition track_mixer_program.hpp:129
float value_at(timebase::SamplePosition sample) noexcept
Definition track_mixer_program.hpp:116
void restart(const timebase::CompiledTempoMap &map) noexcept
Begins a fresh monotonic run.
Definition track_mixer_program.hpp:108
void reset(const AutomationProgram *program, float constant) noexcept
Definition track_mixer_program.hpp:93
Definition compiled_tempo_map.hpp:91
Definition compiled_tempo_map.hpp:164
constexpr float kMaximumTrackGainLinear
Largest admitted authored linear track gain.
Definition recording.hpp:146
@ Hold
Definition automation_curve.hpp:21
Definition audio_renderer.hpp:20
constexpr TrackMixerChannelGains track_mixer_channel_gains(float pan) noexcept
Definition track_mixer_program.hpp:70
constexpr float clamped_track_pan(float value) noexcept
Definition track_mixer_program.hpp:56
std::size_t select_automation_segment(const AutomationProgram &program, timebase::SamplePosition sample, bool cold, std::size_t segment_index) noexcept
Selects the segment governing an absolute timeline sample.
float evaluate_automation_segment(const AutomationProgram &program, std::size_t segment_index, timebase::SamplePosition sample, timebase::TickPosition tick) noexcept
The authored value of one already-selected segment at an exact tick.
constexpr float track_mixer_channel_gain(float pan, std::size_t channel, std::size_t channel_count) noexcept
The balance multiplier for one output channel.
Definition track_mixer_program.hpp:77
constexpr float kMaximumTrackMixerGain
Mirrors timeline::kMaximumTrackGainLinear.
Definition track_mixer_program.hpp:17
constexpr float clamped_track_gain(float value) noexcept
Constrains a streamed control value to the range the document accepts for the same control as a const...
Definition track_mixer_program.hpp:50
Definition automation_program.hpp:38
Per-side multipliers for a stereo balance.
Definition track_mixer_program.hpp:65
float right
Definition track_mixer_program.hpp:67
float left
Definition track_mixer_program.hpp:66
The compiled form of a track's own level and stereo placement.
Definition track_mixer_program.hpp:28
const AutomationProgram * gain_automation
Definition track_mixer_program.hpp:31
float gain_linear
Definition track_mixer_program.hpp:29
const AutomationProgram * pan_automation
Definition track_mixer_program.hpp:32
bool transparent() const noexcept
Whether this mixer can be skipped entirely.
Definition track_mixer_program.hpp:37
float pan
Definition track_mixer_program.hpp:30
Definition rational_time.hpp:9