Skip to main content

fixed_dsp/basic/
scale.rs

1use crate::{sat_i16, sat_i32};
2
3/// In-place Q15 scale, matching CMSIS `arm_scale_q15` scalar behavior.
4pub fn scale_i16(data: &mut [i16], scale: i16, shift: i8) {
5    let k_shift = 15 - shift;
6
7    for sample in data.iter_mut() {
8        *sample = sat_i16(((*sample as i32) * (scale as i32)) >> k_shift);
9    }
10}
11
12/// In-place Q31 scale, matching CMSIS `arm_scale_q31` scalar behavior.
13pub fn scale_i32(data: &mut [i32], scale: i32, shift: i8) {
14    let k_shift = shift + 1;
15
16    if k_shift >= 0 {
17        for sample in data.iter_mut() {
18            let in_val = ((*sample as i64) * (scale as i64)) >> 32;
19            *sample = sat_i32(in_val << k_shift);
20        }
21    } else {
22        for sample in data.iter_mut() {
23            let in_val = ((*sample as i64) * (scale as i64)) >> 32;
24            *sample = sat_i32(in_val >> -k_shift);
25        }
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32
33    #[test]
34    fn scale_i16_in_place_changes_buffer() {
35        let mut data = [0x4000_i16, -0x4000_i16, 0x2000_i16];
36        scale_i16(&mut data, 0x4000, 0);
37        assert_eq!(data, [0x2000, -0x2000, 0x1000]);
38    }
39
40    #[test]
41    fn scale_i32_in_place_changes_buffer() {
42        let mut data = [0x4000_0000_i32, -0x4000_0000_i32, 0x2000_0000_i32];
43        scale_i32(&mut data, 0x4000_0000, 0);
44        assert_eq!(data, [0x2000_0000, -0x2000_0000, 0x1000_0000]);
45    }
46}