use {FloatSample, Sample};
use core;
use core::marker::PhantomData;
use frame::Frame;
use signal::{self, Signal};
pub trait Type {
fn at_phase<S: Sample>(phase: S) -> S;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Hanning;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Rectangle;
#[derive(Clone)]
pub struct Window<F, W>
where
F: Frame,
W: Type,
{
pub phase: signal::Phase<signal::ConstHz>,
marker: PhantomData<(F, W)>,
}
#[derive(Clone)]
pub struct Windower<'a, F, W>
where
F: 'a + Frame,
W: Type,
{
pub bin: usize,
pub hop: usize,
pub frames: &'a [F],
wttype: PhantomData<W>,
}
#[derive(Clone)]
pub struct Windowed<S, W>
where
S: Signal,
W: Type,
{
signal: S,
window: Window<<S::Frame as Frame>::Float, W>,
}
impl Type for Hanning {
fn at_phase<S: Sample>(phase: S) -> S {
const PI_2: f64 = core::f64::consts::PI * 2.0;
let v = phase.to_float_sample().to_sample() * PI_2;
(0.5 * (1.0 - super::ops::f64::cos(v)))
.to_sample::<S::Float>()
.to_sample::<S>()
}
}
impl Type for Rectangle {
fn at_phase<S: Sample>(_phase: S) -> S {
<S::Float as FloatSample>::identity().to_sample::<S>()
}
}
impl<F, W> Window<F, W>
where
F: Frame,
W: Type,
{
pub fn new(len: usize) -> Self {
let step = signal::rate(len as f64 - 1.0).const_hz(1.0);
Window {
phase: signal::phase(step),
marker: PhantomData,
}
}
}
impl<'a, F, W> Windower<'a, F, W>
where
F: 'a + Frame,
W: Type,
{
pub fn new(frames: &'a [F], bin: usize, hop: usize) -> Self {
Windower {
bin: bin,
hop: hop,
frames: frames,
wttype: PhantomData,
}
}
}
impl<'a, F> Windower<'a, F, Rectangle>
where
F: 'a + Frame,
{
pub fn rectangle(frames: &'a [F], bin: usize, hop: usize) -> Self {
Windower::new(frames, bin, hop)
}
}
impl<'a, F> Windower<'a, F, Hanning>
where
F: 'a + Frame,
{
pub fn hanning(frames: &'a [F], bin: usize, hop: usize) -> Self {
Windower::new(frames, bin, hop)
}
}
impl<F, W> Iterator for Window<F, W>
where
F: Frame,
W: Type,
{
type Item = F;
fn next(&mut self) -> Option<Self::Item> {
let v = W::at_phase(self.phase.next_phase());
let v_f: <F::Sample as Sample>::Float = v.to_sample();
Some(F::from_fn(|_| v_f.to_sample::<F::Sample>()))
}
}
impl<'a, F, W> Iterator for Windower<'a, F, W>
where
F: 'a + Frame,
W: Type,
{
type Item = Windowed<signal::FromIterator<core::iter::Cloned<core::slice::Iter<'a, F>>>, W>;
fn next(&mut self) -> Option<Self::Item> {
let num_frames = self.frames.len();
if self.bin <= num_frames {
let frames = &self.frames[..self.bin];
let window = Window::new(self.bin);
self.frames = if self.hop < num_frames {
&self.frames[self.hop..]
} else {
&[]
};
Some(Windowed {
signal: signal::from_iter(frames.iter().cloned()),
window: window,
})
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let num_frames = self.frames.len();
if self.bin < num_frames {
if self.hop == 0 {
return (core::usize::MAX, None);
}
let remaining_hop_frames = self.frames.len() - self.bin;
let remaining_iterations = remaining_hop_frames / self.hop;
(remaining_iterations, Some(remaining_iterations))
} else {
(0, Some(0))
}
}
}
impl<S, W> Iterator for Windowed<S, W>
where
S: Signal,
W: Type,
{
type Item = S::Frame;
fn next(&mut self) -> Option<Self::Item> {
self.window.next().map(|w_f| {
let s_f = self.signal.next();
s_f.mul_amp(w_f)
})
}
}
pub fn hanning<F>(num_frames: usize) -> Window<F, Hanning>
where
F: Frame,
{
Window::new(num_frames)
}
pub fn rectangle<F>(num_frames: usize) -> Window<F, Rectangle>
where
F: Frame,
{
Window::new(num_frames)
}