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
//! Peak envelope detection over a signal.

#![cfg_attr(not(feature = "std"), no_std)]

use dasp_frame::Frame;
use dasp_sample::Sample;

/// Types that may be used to rectify a signal of frames `F` for a `Peak` detector.
pub trait Rectifier<F>
where
    F: Frame,
{
    /// Frames that can be detected.
    type Output: Frame<NumChannels = F::NumChannels>;
    /// Rectify the given frame.
    fn rectify(&mut self, frame: F) -> Self::Output;
}

/// A signal rectifier that produces the absolute amplitude from samples.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct FullWave;
/// A signal rectifier that produces only the positive samples.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct PositiveHalfWave;
/// A signal rectifier that produces only the negative samples.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct NegativeHalfWave;

impl<F> Rectifier<F> for FullWave
where
    F: Frame,
{
    type Output = F::Signed;
    fn rectify(&mut self, frame: F) -> Self::Output {
        full_wave(frame)
    }
}

impl<F> Rectifier<F> for PositiveHalfWave
where
    F: Frame,
{
    type Output = F;
    fn rectify(&mut self, frame: F) -> Self::Output {
        positive_half_wave(frame)
    }
}

impl<F> Rectifier<F> for NegativeHalfWave
where
    F: Frame,
{
    type Output = F;
    fn rectify(&mut self, frame: F) -> Self::Output {
        negative_half_wave(frame)
    }
}

/// A signal rectifier that produces the absolute amplitude from samples.
pub fn full_wave<F>(frame: F) -> F::Signed
where
    F: Frame,
{
    frame.map(|s| {
        let signed = s.to_signed_sample();
        if signed < Sample::EQUILIBRIUM {
            -signed
        } else {
            signed
        }
    })
}

/// A signal rectifier that produces only the positive samples.
pub fn positive_half_wave<F>(frame: F) -> F
where
    F: Frame,
{
    frame.map(|s| {
        if s < Sample::EQUILIBRIUM {
            Sample::EQUILIBRIUM
        } else {
            s
        }
    })
}

/// A signal rectifier that produces only the negative samples.
pub fn negative_half_wave<F>(frame: F) -> F
where
    F: Frame,
{
    frame.map(|s| {
        if s > Sample::EQUILIBRIUM {
            Sample::EQUILIBRIUM
        } else {
            s
        }
    })
}