wfdb_rust/
signal.rs

1//! Parsing logic for each signal format type
2
3/// Parse a byte buffer of data in format 212, 12-bit two's complement amplitude.
4///
5/// Two 12-bit samples in 3 bytes:
6///
7/// ```text
8/// | 8 7 6 5 4 3 2 1 | 12 11 10 9 12 11 10 9 | 8 7 6 5 4 3 2 1 |
9/// ```
10///
11pub fn parse_212_format(buf: &[u8]) -> Vec<i16> {
12    let mut output_buf = vec![];
13    for idx in (0..buf.len()).step_by(3) {
14        if idx + 1 >= buf.len() { break }
15        let sample_1_lower = buf[idx] as u16;
16        let mut sample_1_upper = ((buf[idx+1] & 0x0F) as u16) << 8;
17        if (sample_1_upper & 0x0800) != 0 {
18            // Extend two's complement sign bits if last bit is 1
19            sample_1_upper |= 0xF000;
20        }
21        output_buf.push((sample_1_lower | sample_1_upper) as i16);
22
23        if idx + 2 >= buf.len() { break }
24        let sample_2_lower = buf[idx+2] as u16;
25        let mut sample_2_upper = ((buf[idx+1] & 0xF0) as u16) << 4;
26        if (sample_2_upper & 0x0800) != 0 {
27            // Extend two's complement sign bits if last bit is 1
28            sample_2_upper |= 0xF000;
29        }
30        output_buf.push((sample_2_lower | sample_2_upper) as i16);
31    }
32    output_buf
33}
34
35#[cfg(test)]
36mod test {
37    use super::*;
38    #[test]
39    fn basic_byte_parser() {
40        let byte_buf = [
41            0xF0, 0x68, 0x80,
42            0xF0, 0x68, 0x80,
43        ];
44        assert_eq!(
45            parse_212_format(&byte_buf),
46            vec![
47                -1808, 1664, // 0x8F0, 0x680
48                -1808, 1664, // 0x8F0, 0x680
49            ]
50        );
51    }
52
53    #[test]
54    fn incomplete_buffer() {
55        let byte_buf = [
56            0xF0, 0x86,
57        ];
58        assert_eq!(
59            parse_212_format(&byte_buf),
60            vec![
61                1776, //0x6F0
62            ]
63        );
64    }
65
66    #[test]
67    fn negative_values_buffer() {
68        let byte_buf = [
69            0xFF, 0x8F, 0x80
70        ];
71        assert_eq!(
72            parse_212_format(&byte_buf),
73            vec![
74                -1, -1920 // 0xFFF, 0x880
75            ]
76        );
77    }
78}