1#![allow(unused_imports)]
6
7#[cfg(feature = "std")]
8use std::{vec::Vec, marker::PhantomData, f32::consts::E};
9
10#[cfg(not(feature = "std"))]
11use core::{marker::PhantomData, f32::consts::E};
12
13#[cfg(all(not(feature = "std"), feature = "alloc"))]
14use alloc::vec::Vec;
15
16use num_traits::Float;
17
18#[derive(Clone, Debug)]
49pub struct Adsr {
50 attack_time: f32,
52 decay_time: f32,
53 sustain_level: f32,
54 release_time: f32,
55
56 value: f32,
58 gate: bool,
59 stage: AdsrStage,
60
61 sample_rate: f32,
63 attack_increment: f32,
64 decay_increment: f32,
65 release_increment: f32,
66}
67
68#[derive(Clone, Copy, Debug, PartialEq)]
69enum AdsrStage {
70 Attack,
71 Decay,
72 Sustain,
73 Release,
74 Done,
75}
76
77impl Adsr {
78 pub fn new(sample_rate: f32) -> Self {
80 let mut adsr = Self {
81 attack_time: 0.01,
82 decay_time: 0.1,
83 sustain_level: 0.7,
84 release_time: 0.2,
85 value: 0.0,
86 gate: false,
87 stage: AdsrStage::Release,
88 sample_rate,
89 attack_increment: 1.0 / (0.01 * sample_rate),
90 decay_increment: (0.7 - 1.0) / (0.1 * sample_rate),
91 release_increment: -0.7 / (0.2 * sample_rate),
92 };
93 adsr.reset();
94 adsr
95 }
96
97 pub fn set_times(&mut self, attack: f32, decay: f32, sustain: f32, release: f32) {
106 self.attack_time = attack.max(0.0001); self.decay_time = decay.max(0.0001);
108 self.sustain_level = sustain.clamp(0.0, 1.0);
109 self.release_time = release.max(0.0001);
110
111 self.attack_increment = 1.0 / (self.attack_time * self.sample_rate);
113 self.decay_increment = (self.sustain_level - 1.0) / (self.decay_time * self.sample_rate);
114 self.release_increment = -self.sustain_level / (self.release_time * self.sample_rate);
115 }
116
117 pub fn set_attack(&mut self, attack: f32) {
119 self.attack_time = attack.max(0.0001);
120 self.attack_increment = 1.0 / (self.attack_time * self.sample_rate);
121 }
122
123 pub fn set_decay(&mut self, decay: f32) {
125 self.decay_time = decay.max(0.0001);
126 self.decay_increment = (self.sustain_level - 1.0) / (self.decay_time * self.sample_rate);
127 }
128
129 pub fn set_sustain(&mut self, sustain: f32) {
131 self.sustain_level = sustain.clamp(0.0, 1.0);
132 self.decay_increment = (self.sustain_level - 1.0) / (self.decay_time * self.sample_rate);
133 self.release_increment = -self.sustain_level / (self.release_time * self.sample_rate);
134 }
135
136 pub fn set_release(&mut self, release: f32) {
138 self.release_time = release.max(0.0001);
139 self.release_increment = -self.sustain_level / (self.release_time * self.sample_rate);
140 }
141
142 pub fn gate(&mut self, gate: bool) {
144 if gate && !self.gate {
145 self.stage = AdsrStage::Attack;
147 } else if !gate && self.gate {
148 self.stage = AdsrStage::Release;
150 }
151 self.gate = gate;
152 }
153
154 pub fn value(&self) -> f32 {
156 self.value
157 }
158
159 pub fn stage(&self) -> u32 {
161 match self.stage {
162 AdsrStage::Attack => 0,
163 AdsrStage::Decay => 1,
164 AdsrStage::Sustain => 2,
165 AdsrStage::Release => 3,
166 AdsrStage::Done => 4,
167 }
168 }
169
170 pub fn reset(&mut self) {
172 self.value = 0.0;
173 self.stage = if self.gate { AdsrStage::Attack } else { AdsrStage::Release };
174 }
175
176 pub fn next(&mut self) -> f32 {
178 match self.stage {
179 AdsrStage::Attack => {
180 self.value += self.attack_increment;
181 if self.value >= 1.0 {
182 self.value = 1.0;
183 self.stage = AdsrStage::Decay;
184 }
185 }
186 AdsrStage::Decay => {
187 self.value += self.decay_increment;
188 if self.value <= self.sustain_level {
189 self.value = self.sustain_level;
190 self.stage = AdsrStage::Sustain;
191 }
192 }
193 AdsrStage::Sustain => {
194 self.value = self.sustain_level;
195 if !self.gate {
196 self.stage = AdsrStage::Release;
197 }
198 }
199 AdsrStage::Release => {
200 self.value += self.release_increment;
201 if self.value <= 0.0 {
202 self.value = 0.0;
203 self.stage = AdsrStage::Done;
204 }
205 }
206 AdsrStage::Done => {
207 self.value = 0.0;
208 if self.gate {
209 self.stage = AdsrStage::Attack;
210 }
211 }
212 }
213 self.value
214 }
215}
216
217pub struct CubicLfo {
224 ratio: f32,
225 ratio_step: f32,
226
227 value_from: f32,
228 value_to: f32,
229 value_range: f32,
230
231 target_low: f32,
232 target_high: f32,
233 target_rate: f32,
234
235 rate_random: f32,
236 depth_random: f32,
237
238 fresh_reset: bool,
239
240 seed: u64,
242}
243
244impl CubicLfo {
245 pub fn new() -> Self {
247 let mut lfo = Self {
248 ratio: 0.0,
249 ratio_step: 0.0,
250 value_from: 0.0,
251 value_to: 1.0,
252 value_range: 1.0,
253 target_low: 0.0,
254 target_high: 1.0,
255 target_rate: 0.0,
256 rate_random: 0.5,
257 depth_random: 0.0,
258 fresh_reset: true,
259 seed: 0,
260 };
261
262 #[cfg(feature = "std")]
264 {
265 use std::time::{SystemTime, UNIX_EPOCH};
266 let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default();
267 lfo.seed = now.as_secs() ^ (now.subsec_nanos() as u64);
268 }
269
270 #[cfg(not(feature = "std"))]
271 {
272 lfo.seed = 12345;
274 }
275
276 lfo.reset();
277 lfo
278 }
279
280 pub fn with_seed(seed: u64) -> Self {
282 let mut lfo = Self {
283 ratio: 0.0,
284 ratio_step: 0.0,
285 value_from: 0.0,
286 value_to: 1.0,
287 value_range: 1.0,
288 target_low: 0.0,
289 target_high: 1.0,
290 target_rate: 0.0,
291 rate_random: 0.5,
292 depth_random: 0.0,
293 fresh_reset: true,
294 seed,
295 };
296 lfo.reset();
297 lfo
298 }
299
300 fn random(&mut self) -> f32 {
302 self.seed ^= self.seed << 13;
303 self.seed ^= self.seed >> 17;
304 self.seed ^= self.seed << 5;
305 (self.seed & 0xFFFFFF) as f32 / 0xFFFFFF as f32
306 }
307
308 fn random_rate(&mut self) -> f32 {
309 self.target_rate * (E.powf(self.rate_random * (self.random() - 0.5)))
310 }
311
312 fn random_target(&mut self, previous: f32) -> f32 {
313 let random_offset = self.depth_random * self.random() * (self.target_low - self.target_high);
314 if previous < (self.target_low + self.target_high) * 0.5 {
315 self.target_high + random_offset
316 } else {
317 self.target_low - random_offset
318 }
319 }
320
321 pub fn reset(&mut self) {
323 self.ratio = self.random();
324 self.ratio_step = self.random_rate();
325
326 if self.random() < 0.5 {
327 self.value_from = self.target_low;
328 self.value_to = self.target_high;
329 } else {
330 self.value_from = self.target_high;
331 self.value_to = self.target_low;
332 }
333
334 self.value_range = self.value_to - self.value_from;
335 self.fresh_reset = true;
336 }
337
338 pub fn set(&mut self, low: f32, high: f32, rate: f32, rate_variation: f32, depth_variation: f32) {
349 let rate = rate * 2.0; self.target_rate = rate;
351 self.target_low = low.min(high);
352 self.target_high = low.max(high);
353 self.rate_random = rate_variation;
354 self.depth_random = depth_variation.max(0.0).min(1.0);
355
356 if self.fresh_reset {
358 return self.reset();
359 }
360
361 let max_random_ratio = E.powf(0.5 * self.rate_random);
363 if self.ratio_step > rate * max_random_ratio || self.ratio_step < rate / max_random_ratio {
364 self.ratio_step = self.random_rate();
365 }
366 }
367
368 pub fn next(&mut self) -> f32 {
370 self.fresh_reset = false;
371 let result = self.ratio * self.ratio * (3.0 - 2.0 * self.ratio) * self.value_range + self.value_from;
372
373 self.ratio += self.ratio_step;
374 while self.ratio >= 1.0 {
375 self.ratio -= 1.0;
376 self.ratio_step = self.random_rate();
377 self.value_from = self.value_to;
378 self.value_to = self.random_target(self.value_from);
379 self.value_range = self.value_to - self.value_from;
380 }
381
382 result
383 }
384}
385
386pub struct BoxSum<T: Float> {
388 buffer_length: usize,
389 index: usize,
390 buffer: Vec<T>,
391 sum: T,
392 wrap_jump: T,
393}
394
395impl<T: Float> BoxSum<T> {
396 pub fn new(max_length: usize) -> Self {
398 let mut result = Self {
399 buffer_length: 0,
400 index: 0,
401 buffer: Vec::new(),
402 sum: T::zero(),
403 wrap_jump: T::zero(),
404 };
405 result.resize(max_length);
406 result
407 }
408
409 pub fn resize(&mut self, max_length: usize) {
411 self.buffer_length = max_length + 1;
412 self.buffer.resize(self.buffer_length, T::zero());
413 self.reset(T::zero());
414 }
415
416 pub fn reset(&mut self, value: T) {
418 self.index = 0;
419 self.sum = T::zero();
420
421 for i in 0..self.buffer.len() {
422 self.buffer[i] = self.sum;
423 self.sum = self.sum + value;
424 }
425
426 self.wrap_jump = self.sum;
427 self.sum = T::zero();
428 }
429
430 pub fn read(&self, width: usize) -> T {
432 let mut read_index = self.index as isize - width as isize;
433 let mut result = self.sum;
434
435 if read_index < 0 {
436 result = result + self.wrap_jump;
437 read_index += self.buffer_length as isize;
438 }
439
440 result - self.buffer[read_index as usize]
441 }
442
443 pub fn write(&mut self, value: T) {
445 self.index += 1;
446 if self.index == self.buffer_length {
447 self.index = 0;
448 self.wrap_jump = self.sum;
449 self.sum = T::zero();
450 }
451
452 self.sum = self.sum + value;
453 self.buffer[self.index] = self.sum;
454 }
455
456 pub fn read_write(&mut self, value: T, width: usize) -> T {
458 self.write(value);
459 self.read(width)
460 }
461}
462
463pub struct BoxFilter<T: Float> {
467 box_sum: BoxSum<T>,
468 length: usize,
469 max_length: usize,
470 multiplier: T,
471}
472
473impl<T: Float> BoxFilter<T> {
474 pub fn new(max_length: usize) -> Self {
476 let mut result = Self {
477 box_sum: BoxSum::new(max_length),
478 length: 0,
479 max_length: 0,
480 multiplier: T::one(),
481 };
482 result.resize(max_length);
483 result
484 }
485
486 pub fn resize(&mut self, max_length: usize) {
488 self.max_length = max_length;
489 self.box_sum.resize(max_length);
490 self.set(max_length);
491 }
492
493 pub fn set(&mut self, length: usize) {
495 self.length = length;
496 self.multiplier = T::one() / T::from(length).unwrap();
497
498 if length > self.max_length {
499 self.resize(length);
500 }
501 }
502
503 pub fn reset(&mut self, fill: T) {
505 self.box_sum.reset(fill);
506 }
507
508 pub fn process(&mut self, v: T) -> T {
510 self.box_sum.read_write(v, self.length) * self.multiplier
511 }
512}
513
514pub struct BoxStackFilter<T: Float> {
519 size: usize,
520 layers: Vec<BoxStackLayer<T>>,
521}
522
523struct BoxStackLayer<T: Float> {
524 ratio: f32,
525 length_error: f32,
526 length: usize,
527 filter: BoxFilter<T>,
528}
529
530impl<T: Float> BoxStackFilter<T> {
531 pub fn new(max_size: usize, layers: usize) -> Self {
533 let mut result = Self {
534 size: 0,
535 layers: Vec::new(),
536 };
537 result.resize(max_size, layers);
538 result
539 }
540
541 pub fn optimal_ratios(layer_count: usize) -> Vec<f32> {
543 static HARDCODED: [f32; 21] = [
545 1.0, 0.58224186169, 0.41775813831, 0.404078562416, 0.334851475794, 0.261069961789,
546 0.307944914938, 0.27369945234, 0.22913263601, 0.189222996712, 0.248329349789,
547 0.229253789144, 0.201191468123, 0.173033035122, 0.148192357821, 0.205275202874,
548 0.198413552119, 0.178256637764, 0.157821404506, 0.138663023387, 0.121570179349
549 ];
550
551 if layer_count <= 0 {
552 return Vec::new();
553 } else if layer_count <= 6 {
554 let start = layer_count * (layer_count - 1) / 2;
555 return HARDCODED[start..start + layer_count].to_vec();
556 }
557
558 let mut result = vec![0.0; layer_count];
559
560 let inv_n = 1.0 / layer_count as f32;
561 let sqrt_n = (layer_count as f32).sqrt();
562 let p = 1.0 - inv_n;
563 let k = 1.0 + 4.5 / sqrt_n + 0.08 * sqrt_n;
564
565 let mut sum = 0.0;
566 for i in 0..layer_count {
567 let x = i as f32 * inv_n;
568 let power = -x * (1.0 - p * (-x * k).exp());
569 let length = 2.0f32.powf(power);
570 result[i] = length;
571 sum += length;
572 }
573
574 let factor = 1.0 / sum;
575 for r in &mut result {
576 *r *= factor;
577 }
578
579 result
580 }
581
582 pub fn layers_to_bandwidth(layers: usize) -> f32 {
584 1.58 * (layers as f32 + 0.1)
585 }
586
587 pub fn layers_to_peak_db(layers: usize) -> f32 {
589 5.0 - layers as f32 * 18.0
590 }
591
592 pub fn resize(&mut self, max_size: usize, layer_count: usize) {
594 self.resize_with_ratios(max_size, Self::optimal_ratios(layer_count));
595 }
596
597 pub fn resize_with_ratios(&mut self, max_size: usize, ratios: Vec<f32>) {
599 self.setup_layers(ratios);
600
601 for layer in &mut self.layers {
602 layer.filter.resize(0);
603 }
604
605 self.size = 0;
606 self.set(max_size);
607 self.reset();
608 }
609
610 fn setup_layers(&mut self, ratios: Vec<f32>) {
611 self.layers.clear();
612
613 let mut sum = 0.0;
614 for ratio in &ratios {
615 self.layers.push(BoxStackLayer {
616 ratio: *ratio,
617 length_error: 0.0,
618 length: 0,
619 filter: BoxFilter::new(0),
620 });
621 sum += ratio;
622 }
623
624 let factor = 1.0 / sum;
625 for layer in &mut self.layers {
626 layer.ratio *= factor;
627 }
628 }
629
630 pub fn set(&mut self, size: usize) {
632 if self.layers.is_empty() {
633 return;
634 }
635
636 if self.size == size {
637 return;
638 }
639
640 self.size = size;
641 let order = size - 1;
642 let mut total_order = 0;
643
644 for layer in &mut self.layers {
645 let layer_order_fractional = layer.ratio * order as f32;
646 let layer_order = layer_order_fractional as usize;
647 layer.length = layer_order + 1;
648 layer.length_error = layer_order as f32 - layer_order_fractional;
649 total_order += layer_order;
650 }
651
652 while total_order < order {
654 let mut min_index = 0;
655 let mut min_error = self.layers[0].length_error;
656
657 for i in 1..self.layers.len() {
658 if self.layers[i].length_error < min_error {
659 min_error = self.layers[i].length_error;
660 min_index = i;
661 }
662 }
663
664 self.layers[min_index].length += 1;
665 self.layers[min_index].length_error += 1.0;
666 total_order += 1;
667 }
668
669 for layer in &mut self.layers {
670 layer.filter.set(layer.length);
671 }
672 }
673
674 pub fn reset(&mut self) {
676 for layer in &mut self.layers {
677 layer.filter.reset(T::zero());
678 }
679 }
680
681 pub fn process(&mut self, v: T) -> T {
683 let mut result = v;
684 for layer in &mut self.layers {
685 result = layer.filter.process(result);
686 }
687 result
688 }
689}
690
691pub struct PeakHold<T: Float> {
700 buffer_mask: usize,
701 buffer: Vec<T>,
702 back_index: isize,
703 middle_start: isize,
704 working_index: isize,
705 middle_end: isize,
706 front_index: isize,
707 front_max: T,
708 working_max: T,
709 middle_max: T,
710}
711
712impl<T: Float> PeakHold<T> {
713 pub fn new(max_length: usize) -> Self {
715 let mut result = Self {
716 buffer_mask: 0,
717 buffer: Vec::new(),
718 back_index: 0,
719 middle_start: 0,
720 working_index: 0,
721 middle_end: 0,
722 front_index: 0,
723 front_max: T::min_value(),
724 working_max: T::min_value(),
725 middle_max: T::min_value(),
726 };
727 result.resize(max_length);
728 result
729 }
730
731 pub fn size(&self) -> usize {
733 (self.front_index - self.back_index) as usize
734 }
735
736 pub fn resize(&mut self, max_length: usize) {
738 let mut buffer_length = 1;
739 while buffer_length < max_length {
740 buffer_length *= 2;
741 }
742
743 self.buffer.resize(buffer_length, T::min_value());
744 self.buffer_mask = buffer_length - 1;
745
746 self.front_index = self.back_index + max_length as isize;
747 self.reset();
748 }
749
750 pub fn reset(&mut self) {
752 let prev_size = self.size();
753
754 for i in 0..self.buffer.len() {
755 self.buffer[i] = T::min_value();
756 }
757
758 self.front_max = T::min_value();
759 self.working_max = T::min_value();
760 self.middle_max = T::min_value();
761
762 self.middle_end = 0;
763 self.working_index = 0;
764 self.front_index = 0;
765 self.middle_start = self.middle_end - (prev_size as isize / 2);
766 self.back_index = self.front_index - prev_size as isize;
767 }
768
769 pub fn set(&mut self, new_size: usize, preserve_current_peak: bool) {
777 while self.size() < new_size {
778 let back_prev_idx = (self.back_index as usize) & self.buffer_mask;
779 let back_prev = self.buffer[back_prev_idx];
780
781 self.back_index -= 1;
782
783 let back_idx = (self.back_index as usize) & self.buffer_mask;
784 if preserve_current_peak {
785 self.buffer[back_idx] = back_prev;
786 } else {
787 self.buffer[back_idx] = self.buffer[back_idx].max(back_prev);
788 }
789 }
790
791 while self.size() > new_size {
792 self.pop();
793 }
794 }
795
796 pub fn push(&mut self, v: T) {
798 let front_idx = (self.front_index as usize) & self.buffer_mask;
799 self.buffer[front_idx] = v;
800 self.front_index += 1;
801 self.front_max = self.front_max.max(v);
802 }
803
804 pub fn pop(&mut self) {
806 if self.back_index == self.middle_start {
807 self.working_max = T::min_value();
809 self.middle_max = self.front_max;
810 self.front_max = T::min_value();
811
812 let prev_front_length = self.front_index - self.middle_end;
813 let prev_middle_length = self.middle_end - self.middle_start;
814
815 if prev_front_length <= prev_middle_length + 1 {
816 self.middle_start = self.middle_end;
818 self.middle_end = self.front_index;
819 self.working_index = self.middle_end;
820 } else {
821 let middle_length = (self.front_index - self.middle_start) / 2;
824 self.middle_start = self.middle_end;
825 self.middle_end += middle_length;
826
827 let back_length = self.middle_start - self.back_index;
829 let working_length = back_length.min(self.middle_end - self.middle_start);
830 self.working_index = self.middle_start + working_length;
831
832 for i in self.middle_end..self.front_index {
834 let idx = (i as usize) & self.buffer_mask;
835 self.front_max = self.front_max.max(self.buffer[idx]);
836 }
837
838 for i in (self.working_index..self.middle_end).rev() {
840 let idx = (i as usize) & self.buffer_mask;
841 self.buffer[idx] = self.working_max;
842 self.working_max = self.working_max.max(self.buffer[idx]);
843 }
844 }
845
846 if self.back_index == self.middle_start {
848 self.working_max = T::min_value();
850 self.middle_max = self.front_max;
851 self.front_max = T::min_value();
852 self.middle_start = self.middle_end;
853 self.working_index = self.middle_end;
854
855 if self.back_index == self.middle_start {
856 self.back_index -= 1; }
858 }
859
860 let front_idx = (self.front_index as usize) & self.buffer_mask;
862 self.buffer[front_idx] = T::min_value();
863 }
864
865 self.back_index += 1;
866
867 if self.working_index != self.middle_start {
868 self.working_index -= 1;
869 let idx = (self.working_index as usize) & self.buffer_mask;
870 self.buffer[idx] = self.working_max;
871 self.working_max = self.working_max.max(self.buffer[idx]);
872 }
873 }
874
875 pub fn read(&self) -> T {
877 let back_idx = (self.back_index as usize) & self.buffer_mask;
878 let back_max = self.buffer[back_idx];
879 back_max.max(self.middle_max).max(self.front_max)
880 }
881
882 pub fn process(&mut self, v: T) -> T {
884 self.push(v);
885 self.pop();
886 self.read()
887 }
888}
889
890pub struct PeakDecayLinear<T: Float> {
895 peak_hold: PeakHold<T>,
896 value: T,
897 step_multiplier: T,
898}
899
900impl<T: Float> PeakDecayLinear<T> {
901 pub fn new(max_length: usize) -> Self {
903 let mut result = Self {
904 peak_hold: PeakHold::new(max_length),
905 value: T::min_value(),
906 step_multiplier: T::one(),
907 };
908 result.set(max_length as f32);
909 result
910 }
911
912 pub fn resize(&mut self, max_length: usize) {
914 self.peak_hold.resize(max_length);
915 self.reset();
916 }
917
918 pub fn set(&mut self, length: f32) {
920 let window_size = length.ceil() as usize;
921 self.peak_hold.set(window_size, true);
922 self.step_multiplier = T::from(1.0 / window_size as f32).unwrap();
923 }
924
925 pub fn reset(&mut self) {
927 self.peak_hold.reset();
928 self.set(self.peak_hold.size() as f32);
929 self.value = T::min_value();
930 }
931
932 pub fn process(&mut self, v: T) -> T {
934 let peak = self.peak_hold.read();
935 self.peak_hold.process(v);
936
937 let decay_step = peak * self.step_multiplier;
939 self.value = v.max(self.value - decay_step);
940 self.value
941 }
942}
943
944#[cfg(test)]
945mod tests {
946 use super::*;
947
948 #[test]
949 fn test_cubic_lfo() {
950 let mut lfo = CubicLfo::with_seed(12345);
951
952 lfo.set(0.0, 1.0, 0.1, 0.0, 0.0);
954
955 let mut samples = Vec::new();
957 for _ in 0..100 {
958 samples.push(lfo.next());
959 }
960
961 for sample in &samples {
963 assert!(*sample >= 0.0 && *sample <= 1.0);
964 }
965
966 let min = samples.iter().fold(f32::INFINITY, |a, &b| a.min(b));
968 let max = samples.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b));
969
970 assert!(min < 0.1);
971 assert!(max > 0.9);
972 }
973
974 #[test]
975 fn test_box_filter() {
976 let mut filter = BoxFilter::<f32>::new(10);
977
978 filter.set(5);
980
981 let mut output = Vec::new();
983 for i in 0..20 {
984 let input = if i >= 10 { 1.0 } else { 0.0 };
985 output.push(filter.process(input));
986 }
987
988 assert_eq!(output[9], 0.0);
990 assert_eq!(output[10], 0.2);
991 assert_eq!(output[11], 0.4);
992 assert_eq!(output[12], 0.6);
993 assert_eq!(output[13], 0.8);
994 assert_eq!(output[14], 1.0);
995 }
996
997 #[test]
998 fn test_box_stack_filter() {
999 let mut filter = BoxStackFilter::<f32>::new(20, 3);
1000
1001 let mut output = Vec::new();
1003 for i in 0..40 {
1004 let input = if i >= 20 { 1.0 } else { 0.0 };
1005 output.push(filter.process(input));
1006 }
1007
1008 assert!(output[39] > 0.99);
1010
1011 for i in 1..output.len() {
1013 assert!(output[i] >= output[i-1]);
1014 }
1015 }
1016
1017 fn test_peak_hold() {
1018 let mut filter = PeakHold::<f32>::new(5);
1019
1020 let input = vec![0.1, 0.5, 0.3, 0.2, 0.4, 0.1, 0.0];
1022 let mut output = Vec::new();
1023
1024 for &v in &input {
1025 output.push(filter.process(v));
1026 }
1027
1028 assert_eq!(output[0], 0.1); assert_eq!(output[1], 0.5); assert_eq!(output[2], 0.5); assert_eq!(output[3], 0.5); assert_eq!(output[4], 0.5); assert_eq!(output[5], 0.4); assert_eq!(output[6], 0.4); }
1037
1038 #[test]
1039 fn test_peak_decay_linear() {
1040 let mut filter = PeakDecayLinear::<f32>::new(10);
1041
1042 let input = vec![0.1, 0.5, 0.3, 0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0];
1044 let mut output = Vec::new();
1045
1046 filter.reset();
1048
1049 for &v in &input {
1050 output.push(filter.process(v));
1051 }
1052
1053 let decay_per_sample = 0.5 / 10.0; assert!((output[0] - 0.1).abs() < 1e-6); assert!((output[1] - 0.5).abs() < 1e-6); assert!((output[2] - 0.45).abs() < 1e-5, "Sample 2 mismatch: expected 0.45, got {}", output[2]);
1061 assert!((output[3] - 0.40).abs() < 1e-5);
1062 assert!((output[4] - 0.35).abs() < 1e-5);
1063 assert!((output[5] - 0.30).abs() < 1e-5);
1064 assert!((output[6] - 0.25).abs() < 1e-5);
1065 assert!((output[7] - 0.20).abs() < 1e-5);
1066 assert!((output[8] - 0.15).abs() < 1e-5);
1067 assert!((output[9] - 0.10).abs() < 1e-5);
1068 }
1069
1070 #[test]
1071 fn test_adsr_basic() {
1072 let sample_rate = 44100.0;
1073 let mut adsr = Adsr::new(sample_rate);
1074
1075 adsr.set_times(0.01, 0.1, 0.7, 0.2);
1077
1078 adsr.gate(true);
1080
1081 let attack_samples = (0.01 * sample_rate) as usize;
1083 for _ in 0..attack_samples {
1084 adsr.next();
1085 }
1086 assert!(adsr.value() >= 0.99);
1087
1088 let decay_samples = (0.1 * sample_rate) as usize;
1090 for _ in 0..decay_samples {
1091 adsr.next();
1092 }
1093 assert!((adsr.value() - 0.7).abs() < 0.01);
1094
1095 adsr.gate(false);
1097
1098 let release_samples = (0.2 * sample_rate) as usize;
1100 for _ in 0..release_samples {
1101 adsr.next();
1102 }
1103 assert!(adsr.value() <= 0.01);
1104 }
1105
1106 #[test]
1107 fn test_adsr_sustain_level() {
1108 let sample_rate = 44100.0;
1109 let mut adsr = Adsr::new(sample_rate);
1110
1111 adsr.set_times(0.001, 0.001, 0.5, 0.001);
1112 adsr.gate(true);
1113
1114 for _ in 0..100 {
1116 adsr.next();
1117 }
1118
1119 let sustain_val = adsr.next();
1121 assert!((sustain_val - 0.5).abs() < 0.01);
1122 }
1123
1124 #[test]
1125 fn test_adsr_gate_control() {
1126 let sample_rate = 44100.0;
1127 let mut adsr = Adsr::new(sample_rate);
1128
1129 adsr.set_times(0.01, 0.01, 0.7, 0.01);
1130
1131 assert_eq!(adsr.value(), 0.0);
1133
1134 adsr.gate(true);
1136 let val1 = adsr.next();
1137 assert!(val1 > 0.0, "Should be attacking");
1138
1139 adsr.gate(false);
1141 for _ in 0..1000 {
1143 adsr.next();
1144 }
1145 let val2 = adsr.next();
1146 assert!(val2 >= 0.0 && val2 <= 1.0, "Value should be in range during release");
1147 }
1148}