rodio/source/
chirp.rs
1use std::{f32::consts::TAU, time::Duration};
4
5use crate::Source;
6
7#[inline]
9pub fn chirp(
10 sample_rate: cpal::SampleRate,
11 start_frequency: f32,
12 end_frequency: f32,
13 duration: Duration,
14) -> Chirp {
15 Chirp::new(sample_rate, start_frequency, end_frequency, duration)
16}
17
18#[derive(Clone, Debug)]
21pub struct Chirp {
22 start_frequency: f32,
23 end_frequency: f32,
24 sample_rate: cpal::SampleRate,
25 total_samples: u64,
26 elapsed_samples: u64,
27}
28
29impl Chirp {
30 fn new(
31 sample_rate: cpal::SampleRate,
32 start_frequency: f32,
33 end_frequency: f32,
34 duration: Duration,
35 ) -> Self {
36 Self {
37 sample_rate,
38 start_frequency,
39 end_frequency,
40 total_samples: (duration.as_secs_f64() * (sample_rate.0 as f64)) as u64,
41 elapsed_samples: 0,
42 }
43 }
44}
45
46impl Iterator for Chirp {
47 type Item = f32;
48
49 fn next(&mut self) -> Option<Self::Item> {
50 let i = self.elapsed_samples;
51 let ratio = self.elapsed_samples as f32 / self.total_samples as f32;
52 self.elapsed_samples += 1;
53 let freq = self.start_frequency * (1.0 - ratio) + self.end_frequency * ratio;
54 let t = (i as f32 / self.sample_rate() as f32) * TAU * freq;
55 Some(t.sin())
56 }
57}
58
59impl Source for Chirp {
60 fn current_frame_len(&self) -> Option<usize> {
61 None
62 }
63
64 fn channels(&self) -> u16 {
65 1
66 }
67
68 fn sample_rate(&self) -> u32 {
69 self.sample_rate.0
70 }
71
72 fn total_duration(&self) -> Option<Duration> {
73 let secs: f64 = self.total_samples as f64 / self.sample_rate.0 as f64;
74 Some(Duration::new(1, 0).mul_f64(secs))
75 }
76}