second_music_system/
fader.rs1use crate::PosFloat;
2
3#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
11pub enum FadeType {
12 Logarithmic,
16 Linear,
19 #[default]
23 Exponential,
24}
25
26#[derive(Debug, Clone, Copy)]
27pub(crate) enum FadeCurve {
28 Logarithmic { pos: f32, step: f32 },
29 Exponential { pos: f32, step: f32 },
30 Linear { pos: f32, step: f32 },
31}
32
33const SILENT_LOG: f32 = -11.1;
38
39const SILENT_EXP: f32 = 1.0000152;
44
45impl FadeCurve {
46 pub fn from(
47 typ: FadeType,
48 from: PosFloat,
49 to: PosFloat,
50 length: PosFloat,
51 ) -> FadeCurve {
52 match typ {
53 FadeType::Exponential => {
54 let from = from.exp().max(SILENT_EXP);
55 let to = to.exp().max(SILENT_EXP);
56 let step = (to - from) / (*length + 1.0);
57 FadeCurve::Exponential { pos: from, step }
58 }
59 FadeType::Logarithmic => {
60 let from = from.ln().max(SILENT_LOG);
61 let to = to.ln().max(SILENT_LOG);
62 let step = (to - from) / (*length + 1.0);
63 FadeCurve::Logarithmic { pos: from, step }
64 }
65 FadeType::Linear => {
66 let step = (*to - *from) / (*length + 1.0);
67 FadeCurve::Linear { pos: *from, step }
68 }
69 }
70 }
71 fn evaluate(&self) -> PosFloat {
73 PosFloat::new_clamped(match self {
74 Self::Exponential { pos, .. } => pos.ln(),
75 Self::Logarithmic { pos, .. } => pos.exp(),
76 Self::Linear { pos, .. } => *pos,
77 })
78 }
79 fn evaluate_t(&self, t: PosFloat) -> PosFloat {
81 PosFloat::new_clamped(match self {
82 Self::Exponential { pos, step } => (pos + step * *t).ln(),
83 Self::Logarithmic { pos, step } => (pos + step * *t).exp(),
84 Self::Linear { pos, step } => *pos + step * *t,
85 })
86 }
87 fn step_by_one(&mut self) {
89 match self {
90 Self::Logarithmic { pos, step }
91 | Self::Exponential { pos, step }
92 | Self::Linear { pos, step } => *pos += *step,
93 }
94 }
95 fn step_by(&mut self, count: PosFloat) {
97 match self {
98 Self::Logarithmic { pos, step }
99 | Self::Exponential { pos, step }
100 | Self::Linear { pos, step } => *pos += *step * *count,
101 }
102 }
103}
104
105#[derive(Debug, Clone)]
107pub struct Fader {
108 curve: FadeCurve,
109 to: PosFloat,
110 length: PosFloat, pos: PosFloat, }
113
114impl Fader {
115 pub fn new(volume: PosFloat) -> Fader {
117 Fader {
118 curve: FadeCurve::Linear {
119 pos: *volume,
120 step: 0.0,
121 },
122 to: volume,
123 length: PosFloat::ZERO,
124 pos: PosFloat::ONE,
125 }
126 }
127 pub fn start(
135 typ: FadeType,
136 from: PosFloat,
137 to: PosFloat,
138 length: PosFloat,
139 ) -> Fader {
140 Fader {
141 curve: FadeCurve::from(typ, from, to, length),
142 to,
143 length,
144 pos: PosFloat::ZERO,
145 }
146 }
147 pub fn maybe_start(
150 typ: FadeType,
151 from: PosFloat,
152 to: PosFloat,
153 length: PosFloat,
154 ) -> Option<Fader> {
155 if length > PosFloat::ZERO {
156 Some(Fader::start(typ, from, to, length))
157 } else {
158 None
159 }
160 }
161 pub fn complete(&self) -> bool {
163 self.pos >= self.length
164 }
165 pub fn evaluate(&self) -> PosFloat {
167 if self.complete() {
168 self.to
169 } else {
170 self.curve.evaluate()
171 }
172 }
173 pub fn evaluate_t(&self, t: PosFloat) -> PosFloat {
175 let new_pos = self.pos + t;
176 if new_pos >= self.length {
177 self.to
178 } else {
179 self.curve.evaluate_t(t)
180 }
181 }
182 pub fn step_by_one(&mut self) {
184 if !self.complete() {
185 self.curve.step_by_one();
186 self.pos = self.pos + PosFloat::ONE;
187 }
188 }
189 pub fn step_by(&mut self, count: PosFloat) {
191 if !self.complete() {
192 self.curve.step_by(count);
193 self.pos = self.pos + count;
194 }
195 }
196}
197
198impl Iterator for Fader {
199 type Item = PosFloat;
200 fn next(&mut self) -> Option<PosFloat> {
201 if self.complete() {
202 None
203 } else {
204 let ret = self.evaluate();
205 self.step_by_one();
206 Some(ret)
207 }
208 }
209 fn size_hint(&self) -> (usize, Option<usize>) {
210 let size = (self.length.ceil() - *self.pos) as usize;
211 (size, Some(size))
212 }
213 fn count(self) -> usize {
214 (self.length.ceil() - *self.pos) as usize
215 }
216}