1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! An extension to the **Signal** trait that monitors the RMS of a signal.
//!
//! ### Required Features
//!
//! - When using `dasp_signal`, this module requires the **rms** feature to be enabled.
//! - When using `dasp`, this module requires the **signal-rms** feature to be enabled.

use crate::Signal;
use dasp_frame::Frame;
use dasp_ring_buffer as ring_buffer;
use dasp_rms as rms;

/// An extension to the **Signal** trait that monitors the RMS of a signal.
///
/// ### Required Features
///
/// - When using `dasp_signal`, this item requires the **rms** feature to be enabled.
/// - When using `dasp`, this item requires the **signal-rms** feature to be enabled.
pub trait SignalRms: Signal {
    /// An adaptor that yields the RMS of the signal.
    ///
    /// The window size of the RMS detector is equal to the given ring buffer length.
    ///
    /// # Example
    ///
    /// ```
    /// use dasp_ring_buffer as ring_buffer;
    /// use dasp_signal::{self as signal, Signal};
    /// use dasp_signal::rms::SignalRms;
    ///
    /// fn main() {
    ///     let frames = [[0.9], [-0.8], [0.6], [-0.9]];
    ///     let signal = signal::from_iter(frames.iter().cloned());
    ///     let ring_buffer = ring_buffer::Fixed::from([[0.0]; 2]);
    ///     let mut rms_signal = signal.rms(ring_buffer);
    ///     assert_eq!(
    ///         [rms_signal.next(), rms_signal.next(), rms_signal.next()],
    ///         [[0.6363961030678927], [0.8514693182963201], [0.7071067811865476]]
    ///     );
    /// }
    /// ```
    ///
    /// ### Required Features
    ///
    /// - When using `dasp_signal`, this item requires the **rms** feature to be enabled.
    /// - When using `dasp`, this item requires the **signal-rms** feature to be enabled.
    fn rms<S>(self, ring_buffer: ring_buffer::Fixed<S>) -> Rms<Self, S>
    where
        Self: Sized,
        S: ring_buffer::Slice<Element = <Self::Frame as Frame>::Float> + ring_buffer::SliceMut,
    {
        Rms {
            signal: self,
            rms: rms::Rms::new(ring_buffer),
        }
    }
}

/// An adaptor that yields the RMS of the signal.
///
/// The window size of the RMS detector is equal to the given ring buffer length.
///
/// ### Required Features
///
/// - When using `dasp_signal`, this item requires the **rms** feature to be enabled.
/// - When using `dasp`, this item requires the **signal-rms** feature to be enabled.
#[derive(Clone)]
pub struct Rms<S, D>
where
    S: Signal,
    D: ring_buffer::Slice<Element = <S::Frame as Frame>::Float>,
{
    signal: S,
    rms: rms::Rms<S::Frame, D>,
}

impl<S, D> Rms<S, D>
where
    S: Signal,
    D: ring_buffer::Slice<Element = <S::Frame as Frame>::Float> + ring_buffer::SliceMut,
{
    /// The same as `Signal::next` but does not calculate the final square root required to
    /// determine the RMS.
    ///
    /// ### Required Features
    ///
    /// - When using `dasp_signal`, this item requires the **rms** feature to be enabled.
    /// - When using `dasp`, this item requires the **signal-rms** feature to be enabled.
    pub fn next_squared(&mut self) -> <Self as Signal>::Frame {
        self.rms.next_squared(self.signal.next())
    }

    /// Consumes the `Rms` signal and returns its inner signal `S` and `Rms` detector.
    ///
    /// ### Required Features
    ///
    /// - When using `dasp_signal`, this item requires the **rms** feature to be enabled.
    /// - When using `dasp`, this item requires the **signal-rms** feature to be enabled.
    pub fn into_parts(self) -> (S, rms::Rms<S::Frame, D>) {
        let Rms { signal, rms } = self;
        (signal, rms)
    }
}

impl<S, D> Signal for Rms<S, D>
where
    S: Signal,
    D: ring_buffer::Slice<Element = <S::Frame as Frame>::Float> + ring_buffer::SliceMut,
{
    type Frame = <S::Frame as Frame>::Float;
    fn next(&mut self) -> Self::Frame {
        self.rms.next(self.signal.next())
    }

    fn is_exhausted(&self) -> bool {
        self.signal.is_exhausted()
    }
}

impl<T> SignalRms for T where T: Signal {}