chatsounds/
channel_volume.rs

1use std::{
2    f32,
3    sync::{Arc, Mutex},
4    time::Duration,
5};
6
7use rodio::{cpal::FromSample, mixer::Mixer, source::ChannelVolume, PlayError, Sink, Source};
8
9pub struct ChannelVolumeSink {
10    pub sink: Sink,
11    channel_volumes: Arc<Mutex<Vec<f32>>>,
12}
13
14impl ChannelVolumeSink {
15    pub fn connect_new(mixer: &Mixer, channel_volumes: Vec<f32>) -> Result<Self, PlayError> {
16        Ok(Self {
17            sink: Sink::connect_new(mixer),
18            channel_volumes: Arc::new(Mutex::new(channel_volumes)),
19        })
20    }
21
22    pub fn set_channel_volumes(&self, channel_volumes: Vec<f32>) {
23        *self.channel_volumes.lock().unwrap() = channel_volumes;
24    }
25
26    pub fn append<S>(&self, source: S)
27    where
28        S: Source + Send + 'static,
29        f32: FromSample<S::Item>,
30    {
31        let channel_volumes = self.channel_volumes.clone();
32        let source = ChannelVolume::new(source, self.channel_volumes.lock().unwrap().clone())
33            .periodic_access(Duration::from_millis(10), move |i| {
34                let channel_volumes = channel_volumes.lock().unwrap();
35                for (channel, volume) in channel_volumes.iter().enumerate() {
36                    i.set_volume(channel, *volume);
37                }
38            });
39        self.sink.append(source);
40    }
41}