wavecraft_metering/
lib.rs1#[derive(Clone, Copy, Default, Debug)]
11#[repr(C)]
12pub struct MeterFrame {
13 pub peak_l: f32,
15 pub peak_r: f32,
17 pub rms_l: f32,
19 pub rms_r: f32,
21 pub timestamp: u64,
23}
24
25pub struct MeterProducer {
29 producer: rtrb::Producer<MeterFrame>,
30}
31
32impl MeterProducer {
33 #[inline]
38 pub fn push(&mut self, frame: MeterFrame) {
39 let _ = self.producer.push(frame);
41 }
42
43 #[inline]
45 pub fn available_write(&self) -> usize {
46 self.producer.slots()
47 }
48}
49
50pub struct MeterConsumer {
54 consumer: rtrb::Consumer<MeterFrame>,
55}
56
57impl MeterConsumer {
58 pub fn read_latest(&mut self) -> Option<MeterFrame> {
63 let mut latest = None;
64 while let Ok(frame) = self.consumer.pop() {
65 latest = Some(frame);
66 }
67 latest
68 }
69
70 pub fn pop(&mut self) -> Option<MeterFrame> {
74 self.consumer.pop().ok()
75 }
76
77 pub fn available_read(&self) -> usize {
79 self.consumer.slots()
80 }
81}
82
83pub fn create_meter_channel(capacity: usize) -> (MeterProducer, MeterConsumer) {
90 let (producer, consumer) = rtrb::RingBuffer::new(capacity);
91 (MeterProducer { producer }, MeterConsumer { consumer })
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn meter_ring_push_pop() {
100 let (mut producer, mut consumer) = create_meter_channel(4);
101
102 let frame = MeterFrame {
103 peak_l: 0.5,
104 peak_r: 0.6,
105 rms_l: 0.3,
106 rms_r: 0.4,
107 timestamp: 1000,
108 };
109
110 producer.push(frame);
111 let read = consumer.pop().expect("should read frame");
112
113 assert_eq!(read.peak_l, 0.5);
114 assert_eq!(read.peak_r, 0.6);
115 assert_eq!(read.rms_l, 0.3);
116 assert_eq!(read.rms_r, 0.4);
117 assert_eq!(read.timestamp, 1000);
118 }
119
120 #[test]
121 fn meter_ring_overflow() {
122 let (mut producer, mut consumer) = create_meter_channel(2);
123
124 producer.push(MeterFrame {
126 peak_l: 1.0,
127 ..Default::default()
128 });
129 producer.push(MeterFrame {
130 peak_l: 2.0,
131 ..Default::default()
132 });
133
134 producer.push(MeterFrame {
136 peak_l: 3.0,
137 ..Default::default()
138 });
139
140 assert_eq!(consumer.pop().unwrap().peak_l, 1.0);
142 assert_eq!(consumer.pop().unwrap().peak_l, 2.0);
143
144 assert!(consumer.pop().is_none());
146 }
147
148 #[test]
149 fn read_latest_discards_old() {
150 let (mut producer, mut consumer) = create_meter_channel(8);
151
152 for i in 0..5 {
154 producer.push(MeterFrame {
155 peak_l: i as f32,
156 ..Default::default()
157 });
158 }
159
160 let latest = consumer.read_latest().expect("should have frame");
162 assert_eq!(latest.peak_l, 4.0);
163
164 assert!(consumer.pop().is_none());
166 }
167
168 #[test]
169 fn empty_buffer_returns_none() {
170 let (_, mut consumer) = create_meter_channel(4);
171 assert!(consumer.pop().is_none());
172 assert!(consumer.read_latest().is_none());
173 }
174
175 #[test]
176 fn available_counts() {
177 let (mut producer, mut consumer) = create_meter_channel(4);
178
179 assert_eq!(consumer.available_read(), 0);
180
181 producer.push(MeterFrame::default());
182 producer.push(MeterFrame::default());
183
184 assert_eq!(consumer.available_read(), 2);
185
186 consumer.pop();
187 assert_eq!(consumer.available_read(), 1);
188 }
189}