MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TimeMap.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Tendency.hpp"
4
6
8
9/**
10 * @file TimeMap.hpp
11 * @brief Factories for TimeMap: seconds since a voice started in, position in
12 * recorded material out (frames for a sample stream).
13 *
14 * Doubles keep sub-frame precision on long recordings. Positions outside the
15 * material are allowed; the reader decides what they mean. For a fixed
16 * position use constant<double, double>(position).
17 */
18
19/**
20 * @brief Straight path from one position to another, then constant
21 * @param from Position at time zero
22 * @param to Position reached at @p duration and kept after
23 * @param duration Seconds to travel, zero or less gives @p to at every time
24 */
25inline TimeMap linear(double from, double to, double duration)
26{
27 return { .fn = [from, to, duration](const double& t) -> double {
28 if (duration <= 0.0) {
29 return to;
30 }
31 return map_clamped<double>(t, 0.0, duration, from, to);
32 } };
33}
34
35/**
36 * @brief Geometric path from one value to another, then constant
37 * @param from Value at time zero, must be positive
38 * @param to Value reached at @p duration and kept after, must be positive
39 * @param duration Seconds to travel, zero or less gives @p to at every time
40 *
41 * Each equal step of time multiplies the value by the same factor, so it
42 * suits lengths and rates that should shrink or grow by a constant ratio.
43 * A non-positive @p from or @p to gives @p to at every time.
44 */
45inline TimeMap exponential(double from, double to, double duration)
46{
47 return { .fn = [from, to, duration](const double& t) -> double {
48 if (duration <= 0.0 || from <= 0.0 || to <= 0.0) {
49 return to;
50 }
51 return from * std::pow(to / from, std::clamp(t / duration, 0.0, 1.0));
52 } };
53}
54
55/**
56 * @brief Constant acceleration from an initial velocity
57 * @param start Position at time zero
58 * @param velocity Initial velocity in position units per second, negative reverses
59 * @param acceleration Change of velocity per second, negative decelerates
60 *
61 * Position is start + velocity * t + acceleration * t^2 / 2 for t >= 0.
62 */
63inline TimeMap quadratic(double start, double velocity, double acceleration)
64{
65 return { .fn = [start, velocity, acceleration](const double& t) -> double {
66 const double s = std::max(t, 0.0);
67 return start + velocity * s + 0.5 * acceleration * s * s;
68 } };
69}
70
71/**
72 * @brief Triangle wave between two positions
73 * @param lo Lower turning point
74 * @param hi Upper turning point
75 * @param velocity Speed in position units per second, negative starts downward
76 * @param start Position at time zero, folded into [lo, hi]
77 */
78inline TimeMap triangle(double lo, double hi, double velocity, double start)
79{
80 return { .fn = [lo, hi, velocity, start](const double& t) -> double {
81 return ping_pong<double>(start + velocity * t, lo, hi);
82 } };
83}
84
85/**
86 * @brief Position of a moving reference minus a lag that can itself change
87 * @param origin Reference position at time zero, for a recording its write head
88 * @param rate Reference velocity in position units per second, the write rate
89 * @param lag Distance behind the reference at each time, in position units
90 *
91 * Reading a ring that is still being written gives a tap that trails the
92 * write head. Keep the lag above a couple of blocks so the tap stays behind
93 * the frames being written.
94 */
95inline TimeMap lagged(double origin, double rate, TimeMap lag)
96{
97 return { .fn = [origin, rate, lag = std::move(lag)](const double& t) -> double {
98 return origin + rate * t - lag(t);
99 } };
100}
101
102/**
103 * @brief Position that integrates a velocity you can change while it plays
104 * @param start Position at time zero
105 * @param velocity Position units per second, read at every evaluation. Negative
106 * reverses and zero holds.
107 *
108 * The position carries on from wherever it is when the velocity changes, so
109 * speeding up, slowing down, reversing or stopping never jumps. Unlike the other
110 * factories this map keeps a running position, so give each voice its own
111 * instance. Time going backwards restarts it from @p start.
112 */
113inline TimeMap integrated(double start, std::shared_ptr<const double> velocity)
114{
115 struct State {
116 double position;
117 double last;
118 };
119
120 auto state = std::make_shared<State>(State { .position = start, .last = 0.0 });
121
122 return { .fn = [state, start, velocity = std::move(velocity)](const double& t) -> double {
123 if (t < state->last) {
124 state->position = start;
125 state->last = 0.0;
126 }
127
128 state->position += *velocity * (t - state->last);
129 state->last = t;
130 return state->position;
131 } };
132}
133
134/**
135 * @brief Piecewise linear path through evenly spaced positions
136 * @param points Positions spread across [0, duration], for example a sampled
137 * Kinesis curve. Empty gives zero, one gives a constant.
138 * @param duration Seconds from the first point to the last, last point kept after
139 */
140inline TimeMap piecewise_linear(std::vector<double> points, double duration)
141{
142 return { .fn = [points = std::move(points), duration](const double& t) -> double {
143 if (points.empty()) {
144 return 0.0;
145 }
146 if (points.size() == 1 || duration <= 0.0) {
147 return points.back();
148 }
149
150 return sample_table(points, t / duration);
151 } };
152}
153
154} // namespace MayaFlux::Kinesis::TimeMaps
std::optional< glm::vec3 > position
Definition Decoder.cpp:93
std::vector< glm::vec2 > * points
float rate
TimeMap exponential(double from, double to, double duration)
Geometric path from one value to another, then constant.
Definition TimeMap.hpp:45
TimeMap triangle(double lo, double hi, double velocity, double start)
Triangle wave between two positions.
Definition TimeMap.hpp:78
TimeMap lagged(double origin, double rate, TimeMap lag)
Position of a moving reference minus a lag that can itself change.
Definition TimeMap.hpp:95
TimeMap linear(double from, double to, double duration)
Straight path from one position to another, then constant.
Definition TimeMap.hpp:25
TimeMap quadratic(double start, double velocity, double acceleration)
Constant acceleration from an initial velocity.
Definition TimeMap.hpp:63
TimeMap integrated(double start, std::shared_ptr< const double > velocity)
Position that integrates a velocity you can change while it plays.
Definition TimeMap.hpp:113
TimeMap piecewise_linear(std::vector< double > points, double duration)
Piecewise linear path through evenly spaced positions.
Definition TimeMap.hpp:140
T acceleration(const Memory::HistoryBuffer< T > &history, double dt) noexcept
Second difference: rate of change of velocity.
T velocity(const Memory::HistoryBuffer< T > &history, double dt) noexcept
First difference: rate of change of position.
double sample_table(std::span< const double > table, double t) noexcept
Read an evenly spaced table at a position in [0, 1], interpolating linearly.
Definition Scalar.hpp:79
std::function< R(const D &)> fn
Definition Tendency.hpp:23
Typed, composable, stateless callable from domain D to range R.
Definition Tendency.hpp:22