ezk_audio_nodes/convert/
mod.rs1use self::channels::ChannelMixer;
2use self::format::convert_sample_format;
3use self::rate::RateConverter;
4use ezk::{ConfigRange, NextEventIsCancelSafe, Result, Source, SourceEvent};
5use ezk_audio::{RawAudio, RawAudioConfig, RawAudioConfigRange};
6
7mod channels;
8mod format;
9mod rate;
10
11pub struct AudioConvert<S> {
13 source: S,
14
15 stream: Option<Stream>,
16}
17
18impl<S: Source<MediaType = RawAudio> + NextEventIsCancelSafe> NextEventIsCancelSafe
19 for AudioConvert<S>
20{
21}
22
23struct Stream {
24 config: RawAudioConfig,
25 channel_mixer: Option<ChannelMixer>,
26 rate_converter: Option<RateConverter>,
27}
28
29impl<S: Source<MediaType = RawAudio>> AudioConvert<S> {
30 pub fn new(source: S) -> Self {
31 Self {
32 source,
33 stream: None,
34 }
35 }
36}
37
38impl<S: Source<MediaType = RawAudio>> Source for AudioConvert<S> {
39 type MediaType = RawAudio;
40
41 async fn capabilities(&mut self) -> Result<Vec<RawAudioConfigRange>> {
42 let mut caps = self.source.capabilities().await?;
43 caps.push(RawAudioConfigRange::any());
44 Ok(caps)
45 }
46
47 async fn negotiate_config(
48 &mut self,
49 mut available: Vec<RawAudioConfigRange>,
50 ) -> Result<RawAudioConfig> {
51 let mut original = available.clone();
53
54 available.push(RawAudioConfigRange::any());
55
56 let negotiated_config = self.source.negotiate_config(available).await?;
57
58 if original
60 .iter()
61 .any(|original| original.contains(&negotiated_config))
62 {
63 self.stream = Some(Stream {
65 config: negotiated_config.clone(),
66 channel_mixer: None,
67 rate_converter: None,
68 });
69
70 return Ok(negotiated_config);
71 }
72
73 let best_config = original.remove(0);
76
77 let best_config = RawAudioConfig {
78 sample_rate: best_config.sample_rate.first_value(),
79 channels: best_config.channels.first_value(),
80 format: best_config.format.first_value(),
81 };
82
83 let channel_mixer = if negotiated_config.channels != best_config.channels {
84 Some(ChannelMixer::new(
85 negotiated_config.channels.clone(),
86 best_config.channels.clone(),
87 ))
88 } else {
89 None
90 };
91
92 let rate_converter = if negotiated_config.sample_rate != best_config.sample_rate {
93 Some(RateConverter::new(
94 best_config.format,
95 negotiated_config.sample_rate,
96 best_config.sample_rate,
97 best_config.channels.clone(),
98 ))
99 } else {
100 None
101 };
102
103 self.stream = Some(Stream {
104 config: best_config.clone(),
105 channel_mixer,
106 rate_converter,
107 });
108
109 Ok(best_config)
110 }
111
112 async fn next_event(&mut self) -> Result<SourceEvent<Self::MediaType>> {
113 let Some(stream) = &mut self.stream else {
114 return Ok(SourceEvent::RenegotiationNeeded);
115 };
116
117 loop {
118 match self.source.next_event().await? {
119 SourceEvent::Frame(mut frame) => {
120 if let Some(channel_mixer) = &mut stream.channel_mixer {
121 frame = channel_mixer.convert(frame);
122 }
123
124 if let Some(rate_converter) = stream.rate_converter.as_mut() {
125 if let Some(f) = rate_converter.convert(frame) {
127 frame = f;
128 } else {
129 continue;
131 }
132 } else {
133 frame = convert_sample_format(frame, stream.config.format);
134 }
135
136 return Ok(SourceEvent::Frame(frame));
137 }
138 SourceEvent::EndOfData => return Ok(SourceEvent::EndOfData),
139 SourceEvent::RenegotiationNeeded => return Ok(SourceEvent::RenegotiationNeeded),
140 }
141 }
142 }
143}