pounder_test/dsp/src/unwrap.rs

81 lines
2.1 KiB
Rust
Raw Normal View History

2020-12-05 16:56:41 +08:00
use serde::{Deserialize, Serialize};
/// Get phase wrap from x to y.
///
2020-12-05 18:58:59 +08:00
/// Phases are modulo integer overflow. The wraps have the same bias as
/// the base data type itself.
2020-12-05 16:56:41 +08:00
///
/// Args:
/// * `x`: Old phase sample
/// * `y`: New phase sample
///
/// Returns:
2020-12-05 18:58:59 +08:00
/// A tuple containg the (wrapped) phase difference and the signum of the wrap.
#[inline(always)]
2020-12-05 16:56:41 +08:00
pub fn get_wrap(x: i32, y: i32) -> (i32, i8) {
let delta = y.wrapping_sub(x);
let wrap = (delta >= 0) as i8 - (y >= x) as i8;
(delta, wrap)
}
/// Phase unwrapper.
#[derive(Copy, Clone, Default, Deserialize, Serialize)]
pub struct Unwrapper {
// last input
x: i32,
// last wraps
v: i32,
}
impl Unwrapper {
2020-12-05 18:58:59 +08:00
/// Unwrap a new sample from a phase sequence and update the unwrapper
/// state.
2020-12-05 16:56:41 +08:00
///
/// Args:
/// * `x`: New phase sample
///
/// Returns:
2020-12-05 18:58:59 +08:00
/// A tuple containing the (wrapped) phase difference and the signed
/// number of phase wraps accumulated to the new sample.
2020-12-05 16:56:41 +08:00
pub fn update(&mut self, x: i32) -> (i32, i32) {
let (dx, v) = get_wrap(self.x, x);
self.x = x;
self.v = self.v.wrapping_add(v as i32);
(dx, self.v)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mini() {
for (x0, x1, v) in [
(0i32, 0i32, 0i8),
2020-12-05 18:58:59 +08:00
(0, 1, 0),
(0, -1, 0),
(1, 0, 0),
(-1, 0, 0),
2020-12-05 16:56:41 +08:00
(0, 0x7fff_ffff, 0),
(-1, 0x7fff_ffff, -1),
2020-12-05 18:58:59 +08:00
(-2, 0x7fff_ffff, -1),
(-1, -0x8000_0000, 0),
2020-12-05 16:56:41 +08:00
(0, -0x8000_0000, 0),
(1, -0x8000_0000, 1),
(-0x6000_0000, 0x6000_0000, -1),
(0x6000_0000, -0x6000_0000, 1),
2020-12-05 18:58:59 +08:00
(-0x4000_0000, 0x3fff_ffff, 0),
(-0x4000_0000, 0x4000_0000, -1),
(-0x4000_0000, 0x4000_0001, -1),
(0x4000_0000, -0x3fff_ffff, 0),
(0x4000_0000, -0x4000_0000, 0),
(0x4000_0000, -0x4000_0001, 1),
2020-12-05 16:56:41 +08:00
]
.iter()
{
let (_dx, w) = get_wrap(*x0, *x1);
assert_eq!(*v, w, " = get_wrap({:#x}, {:#x})", *x0, *x1);
}
}
}