Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
Loading...
Searching...
No Matches
segment_envelope.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <array>
6#include <cstdint>
7#include <span>
8
9namespace ts {
10
22public:
24 static constexpr int segment_count = 4;
25
34 std::span<const double> targets,
35 std::span<const double> segment_samples,
36 std::span<const bool> linear,
37 double release_target,
38 double release_samples,
39 bool release_linear,
40 double after_release,
41 std::int64_t control_tick_samples);
42
44 [[nodiscard]] std::int64_t note_off_sample() const noexcept { return note_off_; }
45
47 [[nodiscard]] std::int64_t release_samples() const noexcept { return release_samples_; }
48
66 void note_off(std::int64_t sample, int damper = 0);
67
74 [[nodiscard]] static std::int64_t
75 defer_to_control_tick(std::int64_t sample, std::int64_t control_tick_samples) noexcept;
76
78 [[nodiscard]] double value_at(std::int64_t sample) const noexcept;
79
86 [[nodiscard]] bool is_finished(std::int64_t sample) const noexcept
87 {
88 if (note_off_ >= 0 && sample - note_off_ >= release_samples_) {
89 return true;
90 }
91 return targets_.back() <= 0.0 && sample >= to_.back();
92 }
93
99 [[nodiscard]] std::span<const double, segment_count> targets() const noexcept
100 {
101 return targets_;
102 }
103
106 [[nodiscard]] std::span<const std::int64_t, segment_count> segment_ends() const noexcept
107 {
108 return to_;
109 }
110
111private:
112 [[nodiscard]] double held(std::int64_t sample) const noexcept;
113
114 const EnvelopeMachine* machine_;
115 std::array<double, segment_count> targets_{};
116 std::array<bool, segment_count> linear_{};
117 std::array<std::int64_t, segment_count> from_{};
118 std::array<std::int64_t, segment_count> to_{};
119 std::array<double, segment_count> span_{};
120
121 double release_target_ = 0.0;
122 bool release_linear_ = false;
123 double release_span_ = 0.0;
124 std::int64_t release_samples_ = 1;
125 double after_release_ = 0.0;
126 std::int64_t control_tick_ = 1;
127
128 std::int64_t note_off_ = -1;
129 double at_note_off_ = 0.0;
130};
131
132} // namespace ts
The segment-rate and segment-shape machine shared by the TVA, TVF and pitch envelopes.
Definition envelope_machine.hpp:22
std::int64_t release_samples() const noexcept
The release duration in samples, at least one.
Definition segment_envelope.hpp:47
std::span< const double, segment_count > targets() const noexcept
The gain each segment ramps to, in the order they run.
Definition segment_envelope.hpp:99
SegmentEnvelope(const EnvelopeMachine &machine, std::span< const double > targets, std::span< const double > segment_samples, std::span< const bool > linear, double release_target, double release_samples, bool release_linear, double after_release, std::int64_t control_tick_samples)
Builds an envelope from decoded segment parameters.
static std::int64_t defer_to_control_tick(std::int64_t sample, std::int64_t control_tick_samples) noexcept
The control tick an event landing at a sample is acted on.
bool is_finished(std::int64_t sample) const noexcept
Whether the envelope has reached silence and cannot leave it.
Definition segment_envelope.hpp:86
static constexpr int segment_count
Segments before the release.
Definition segment_envelope.hpp:24
double value_at(std::int64_t sample) const noexcept
The envelope's value at a sample position relative to note-on.
std::int64_t note_off_sample() const noexcept
Where the release starts, or -1 while the note is still held.
Definition segment_envelope.hpp:44
std::span< const std::int64_t, segment_count > segment_ends() const noexcept
Where each segment ends, in samples from note-on.
Definition segment_envelope.hpp:106
void note_off(std::int64_t sample, int damper=0)
Starts the release at a sample position.
Definition control_decode.hpp:7
@ damper
Definition control_decode.hpp:22