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