use core::fmt;
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum HpVoldBScaleError {
NullRange,
OutOfRange,
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub struct HpVoldB {
inner: u8,
}
impl Default for HpVoldB {
fn default() -> Self {
HpVoldB::Z0DB
}
}
impl HpVoldB {
pub const unsafe fn from_raw_unchecked(raw: u8) -> Self {
Self { inner: raw }
}
pub const fn from_raw(raw: u8) -> Self {
let raw = if raw < HpVoldB::MIN.inner {
HpVoldB::MIN.inner
} else if raw > HpVoldB::MAX.inner {
HpVoldB::MAX.inner
} else {
raw
};
Self { inner: raw }
}
pub const fn into_raw(self) -> u8 {
self.inner
}
pub fn from_scaled(
low_limit: i16,
high_limit: i16,
input: i16,
) -> Result<Self, HpVoldBScaleError> {
if low_limit == high_limit {
return Err(HpVoldBScaleError::NullRange);
} else if (low_limit < high_limit && (input < low_limit || input > high_limit))
|| (low_limit > high_limit && (input > low_limit || input < high_limit))
{
return Err(HpVoldBScaleError::OutOfRange);
}
const MIN: u8 = HpVoldB::MIN.inner;
const MAX: u8 = HpVoldB::MAX.inner;
let r1 = high_limit - low_limit;
let r2 = MAX - MIN;
let res = (((input - low_limit) * r2 as i16) + r1 / 2) / (r1) + MIN as i16;
let res = unsafe { HpVoldB::from_raw_unchecked(res as _) };
Ok(res)
}
pub fn increase(&mut self) {
if self.inner < HpVoldB::MAX.inner {
self.inner += 1;
}
}
pub fn decrease(&mut self) {
if self.inner > HpVoldB::MIN.inner {
self.inner -= 1;
}
}
pub const MUTE: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0101111) };
pub const N73DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0110000) };
pub const N72DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0110001) };
pub const N71DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0110010) };
pub const N70DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0110011) };
pub const N69DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0110100) };
pub const N68DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0110101) };
pub const N67DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0110110) };
pub const N66DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0110111) };
pub const N65DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0111000) };
pub const N64DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0111001) };
pub const N63DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0111010) };
pub const N62DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0111011) };
pub const N61DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0111100) };
pub const N60DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0111101) };
pub const N59DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0111110) };
pub const N58DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b0111111) };
pub const N57DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1000000) };
pub const N56DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1000001) };
pub const N55DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1000010) };
pub const N54DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1000011) };
pub const N53DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1000100) };
pub const N52DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1000101) };
pub const N51DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1000110) };
pub const N50DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1000111) };
pub const N49DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1001000) };
pub const N48DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1001001) };
pub const N47DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1001010) };
pub const N46DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1001011) };
pub const N45DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1001100) };
pub const N44DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1001101) };
pub const N43DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1001110) };
pub const N42DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1001111) };
pub const N41DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1010000) };
pub const N40DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1010001) };
pub const N39DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1010010) };
pub const N38DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1010011) };
pub const N37DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1010100) };
pub const N36DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1010101) };
pub const N35DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1010110) };
pub const N34DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1010111) };
pub const N33DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1011000) };
pub const N32DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1011001) };
pub const N31DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1011010) };
pub const N30DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1011011) };
pub const N29DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1011100) };
pub const N28DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1011101) };
pub const N27DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1011110) };
pub const N26DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1011111) };
pub const N25DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1100000) };
pub const N24DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1100001) };
pub const N23DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1100010) };
pub const N22DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1100011) };
pub const N21DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1100100) };
pub const N20DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1100101) };
pub const N19DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1100110) };
pub const N18DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1100111) };
pub const N17DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1101000) };
pub const N16DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1101001) };
pub const N15DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1101010) };
pub const N14DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1101011) };
pub const N13DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1101100) };
pub const N12DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1101101) };
pub const N11DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1101110) };
pub const N10DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1101111) };
pub const N9DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1110000) };
pub const N8DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1110001) };
pub const N7DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1110010) };
pub const N6DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1110011) };
pub const N5DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1110100) };
pub const N4DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1110101) };
pub const N3DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1110110) };
pub const N2DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1110111) };
pub const N1DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1111000) };
pub const Z0DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1111001) };
pub const P1DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1111010) };
pub const P2DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1111011) };
pub const P3DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1111100) };
pub const P4DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1111101) };
pub const P5DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1111110) };
pub const P6DB: HpVoldB = unsafe { HpVoldB::from_raw_unchecked(0b1111111) };
pub const MIN: HpVoldB = HpVoldB::MUTE;
pub const MAX: HpVoldB = HpVoldB::P6DB;
}
impl fmt::Display for HpVoldB {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let fmt = match self.inner {
0b0101111 => "Mute",
0b0110000 => "-73",
0b0110001 => "-72",
0b0110010 => "-71",
0b0110011 => "-70",
0b0110100 => "-69",
0b0110101 => "-68",
0b0110110 => "-67",
0b0110111 => "-66",
0b0111000 => "-65",
0b0111001 => "-64",
0b0111010 => "-63",
0b0111011 => "-62",
0b0111100 => "-61",
0b0111101 => "-60",
0b0111110 => "-59",
0b0111111 => "-58",
0b1000000 => "-57",
0b1000001 => "-56",
0b1000010 => "-55",
0b1000011 => "-54",
0b1000100 => "-53",
0b1000101 => "-52",
0b1000110 => "-51",
0b1000111 => "-50",
0b1001000 => "-49",
0b1001001 => "-48",
0b1001010 => "-47",
0b1001011 => "-46",
0b1001100 => "-45",
0b1001101 => "-44",
0b1001110 => "-43",
0b1001111 => "-42",
0b1010000 => "-41",
0b1010001 => "-40",
0b1010010 => "-39",
0b1010011 => "-38",
0b1010100 => "-37",
0b1010101 => "-36",
0b1010110 => "-35",
0b1010111 => "-34",
0b1011000 => "-33",
0b1011001 => "-32",
0b1011010 => "-31",
0b1011011 => "-30",
0b1011100 => "-29",
0b1011101 => "-28",
0b1011110 => "-27",
0b1011111 => "-26",
0b1100000 => "-25",
0b1100001 => "-24",
0b1100010 => "-23",
0b1100011 => "-22",
0b1100100 => "-21",
0b1100101 => "-20",
0b1100110 => "-19",
0b1100111 => "-18",
0b1101000 => "-17",
0b1101001 => "-16",
0b1101010 => "-15",
0b1101011 => "-14",
0b1101100 => "-13",
0b1101101 => "-12",
0b1101110 => "-11",
0b1101111 => "-10",
0b1110000 => "-9",
0b1110001 => "-8",
0b1110010 => "-7",
0b1110011 => "-6",
0b1110100 => "-5",
0b1110101 => "-4",
0b1110110 => "-3",
0b1110111 => "-2",
0b1111000 => "-1",
0b1111001 => "+0",
0b1111010 => "+1",
0b1111011 => "+2",
0b1111100 => "+3",
0b1111101 => "+4",
0b1111110 => "+5",
0b1111111 => "+6",
_ => "???", };
if self.inner > 0b0110000 {
write!(f, "{}dB", fmt)
} else {
write!(f, "{}", fmt)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn scale_test() {
let db = HpVoldB::from_scaled(0, 255, 0).unwrap().inner;
let expected = HpVoldB::MIN.inner;
assert!(db == expected, "Got {:#b},expected {:#b}", db, expected);
let db = HpVoldB::from_scaled(0, 255, 255).unwrap().inner;
let expected = HpVoldB::MAX.inner;
assert!(db == expected, "Got {:#b},expected {:#b}", db, expected);
let db = HpVoldB::from_scaled(255, 0, 0).unwrap().inner;
let expected = HpVoldB::MAX.inner;
assert!(db == expected, "Got {:#b},expected {:#b}", db, expected);
let db = HpVoldB::from_scaled(255, 0, 255).unwrap().inner;
let expected = HpVoldB::MIN.inner;
assert!(db == expected, "Got {:#b},expected {:#b}", db, expected);
let db = HpVoldB::from_scaled(128, 128, 128).unwrap_err();
let expected = HpVoldBScaleError::NullRange;
assert!(db == expected, "Got {:?},expected {:?}", db, expected);
let db = HpVoldB::from_scaled(0, 127, 128).unwrap_err();
let expected = HpVoldBScaleError::OutOfRange;
assert!(db == expected, "Got {:?},expected {:?}", db, expected);
}
#[test]
fn increase_decrease_saturation_test() {
let mut test = HpVoldB::MAX;
test.increase();
assert!(
test == HpVoldB::MAX,
"Got {}, expected {}",
test,
HpVoldB::MAX
);
let mut test = HpVoldB::MIN;
test.decrease();
assert!(
test == HpVoldB::MIN,
"Got {}, expected {}",
test,
HpVoldB::MIN
);
}
}