gst-plugins-rs/audio/audiofx/src/audioecho/ring_buffer.rs

85 lines
2.1 KiB
Rust

// Copyright (C) 2017,2018 Sebastian Dröge <sebastian@centricular.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at
// <https://mozilla.org/MPL/2.0/>.
//
// SPDX-License-Identifier: MPL-2.0
use std::iter;
pub struct RingBuffer {
buffer: Box<[f64]>,
pos: usize,
}
impl RingBuffer {
pub fn new(size: usize) -> Self {
let mut buffer = Vec::with_capacity(size);
buffer.extend(iter::repeat(0.0).take(size));
Self {
buffer: buffer.into_boxed_slice(),
pos: 0,
}
}
pub fn iter(&mut self, delay: usize) -> RingBufferIter {
RingBufferIter::new(self, delay)
}
}
pub struct RingBufferIter<'a> {
buffer: &'a mut [f64],
buffer_pos: &'a mut usize,
read_pos: usize,
write_pos: usize,
}
impl<'a> RingBufferIter<'a> {
fn new(buffer: &'a mut RingBuffer, delay: usize) -> RingBufferIter<'a> {
let size = buffer.buffer.len();
assert!(size >= delay);
assert_ne!(size, 0);
let read_pos = (size - delay + buffer.pos) % size;
let write_pos = buffer.pos % size;
let buffer_pos = &mut buffer.pos;
let buffer = &mut buffer.buffer;
RingBufferIter {
buffer,
buffer_pos,
read_pos,
write_pos,
}
}
}
impl<'a> Iterator for RingBufferIter<'a> {
type Item = (&'a mut f64, f64);
fn next(&mut self) -> Option<Self::Item> {
let res = unsafe {
let r = *self.buffer.get_unchecked(self.read_pos);
let w = self.buffer.get_unchecked_mut(self.write_pos);
// Cast needed to get from &mut f64 to &'a mut f64
(&mut *(w as *mut f64), r)
};
let size = self.buffer.len();
self.write_pos = (self.write_pos + 1) % size;
self.read_pos = (self.read_pos + 1) % size;
Some(res)
}
}
impl<'a> Drop for RingBufferIter<'a> {
fn drop(&mut self) {
*self.buffer_pos = self.write_pos;
}
}