1use std::collections::VecDeque;
2use std::sync::{Arc, Mutex, MutexGuard};
3
4use crate::mix::lock;
5
6pub const PCM_EDGE_SECONDS: f32 = 0.002;
7
8struct Inner {
9 samples: VecDeque<f32>,
10 closed: bool,
11}
12
13pub(crate) struct PcmRing {
14 inner: Mutex<Inner>,
15 capacity: usize,
16 channels: usize,
17}
18
19impl PcmRing {
20 fn new(channels: usize, capacity_frames: usize) -> Arc<Self> {
21 Arc::new(Self {
22 inner: Mutex::new(Inner {
23 samples: VecDeque::new(),
24 closed: false,
25 }),
26 capacity: capacity_frames.max(1),
27 channels: channels.max(1),
28 })
29 }
30
31 fn lock(&self) -> MutexGuard<'_, Inner> {
32 lock(&self.inner)
33 }
34}
35
36pub struct PcmSender {
37 ring: Arc<PcmRing>,
38 rate: u32,
39}
40
41impl PcmSender {
42 pub fn push(&self, samples: &[f32]) -> usize {
43 let channels = self.ring.channels;
44 let mut inner = self.ring.lock();
45 let queued = inner.samples.len() / channels;
46 let room = self.ring.capacity.saturating_sub(queued);
47 let frames = (samples.len() / channels).min(room);
48 inner.samples.extend(&samples[..frames * channels]);
49 frames
50 }
51
52 pub fn queued_frames(&self) -> usize {
53 self.ring.lock().samples.len() / self.ring.channels
54 }
55
56 pub fn capacity_frames(&self) -> usize {
57 self.ring.capacity
58 }
59
60 pub fn room_frames(&self) -> usize {
61 self.ring.capacity.saturating_sub(self.queued_frames())
62 }
63
64 pub fn channels(&self) -> u16 {
65 self.ring.channels as u16
66 }
67
68 pub fn rate(&self) -> u32 {
69 self.rate
70 }
71
72 pub fn is_connected(&self) -> bool {
73 Arc::strong_count(&self.ring) > 1
74 }
75
76 pub fn finish(&self) {
77 self.ring.lock().closed = true;
78 }
79}
80
81impl Drop for PcmSender {
82 fn drop(&mut self) {
83 self.finish();
84 }
85}
86
87pub(crate) fn pcm_pair(channels: u16, capacity_frames: usize, rate: u32) -> (PcmVoice, PcmSender) {
88 let ring = PcmRing::new(usize::from(channels), capacity_frames);
89 let edge = ((f64::from(PCM_EDGE_SECONDS) * f64::from(rate)).round() as u32).max(1);
90 let voice = PcmVoice {
91 ring: Arc::clone(&ring),
92 local: VecDeque::new(),
93 level: 0.0,
94 step: 1.0 / edge as f32,
95 last: (0.0, 0.0),
96 };
97 (voice, PcmSender { ring, rate })
98}
99
100pub(crate) struct PcmVoice {
101 ring: Arc<PcmRing>,
102 local: VecDeque<(f32, f32)>,
103 level: f32,
104 step: f32,
105 last: (f32, f32),
106}
107
108impl PcmVoice {
109 pub(crate) fn channels(&self) -> u16 {
110 self.ring.channels.min(2) as u16
111 }
112
113 pub(crate) fn fill(&mut self, frames: usize) {
114 if self.local.len() >= frames {
115 return;
116 }
117 let channels = self.ring.channels;
118 let mut inner = self.ring.lock();
119 let take = (inner.samples.len() / channels).min(frames - self.local.len());
120 for _ in 0..take {
121 let left = inner.samples.pop_front().unwrap_or(0.0);
122 let right = if channels > 1 {
123 inner.samples.pop_front().unwrap_or(0.0)
124 } else {
125 left
126 };
127 for _ in 2..channels {
128 inner.samples.pop_front();
129 }
130 self.local.push_back((left, right));
131 }
132 }
133
134 pub(crate) fn next(&mut self) -> (f32, f32) {
135 match self.local.pop_front() {
136 Some(frame) => {
137 self.last = frame;
138 self.level = (self.level + self.step).min(1.0);
139 (frame.0 * self.level, frame.1 * self.level)
140 }
141 None => {
142 self.level = (self.level - self.step).max(0.0);
143 (self.last.0 * self.level, self.last.1 * self.level)
144 }
145 }
146 }
147
148 pub(crate) fn finished(&self) -> bool {
149 if self.level > 0.0 || !self.local.is_empty() {
150 return false;
151 }
152 let inner = self.ring.lock();
153 inner.closed && inner.samples.is_empty()
154 }
155}