embedded_audio/decode/
pcm.rs1use crate::fixed::lerp_i8;
2
3#[derive(Debug, Clone, Copy)]
5pub struct Pcm8Stream<'a> {
6 data: &'a [u8],
7 phase_q16: u32,
8 speed_q16: u32,
9 looped: bool,
10 is_signed: bool,
11}
12
13impl<'a> Pcm8Stream<'a> {
14 pub fn new(data: &'a [u8], flags: u8) -> Self {
15 Self::with_speed(data, flags, 65536)
16 }
17
18 pub fn with_speed(data: &'a [u8], flags: u8, speed_q16: u32) -> Self {
19 Self {
20 data,
21 phase_q16: 0,
22 speed_q16,
23 looped: flags & crate::tier::flags::LOOP != 0,
24 is_signed: flags & crate::tier::flags::SIGNED != 0,
25 }
26 }
27
28 pub fn set_speed_q16(&mut self, speed_q16: u32) {
29 self.speed_q16 = speed_q16;
30 }
31
32 pub fn speed_q16(&self) -> u32 {
33 self.speed_q16
34 }
35
36 pub fn reset(&mut self) {
37 self.phase_q16 = 0;
38 }
39
40 pub fn is_done(&self) -> bool {
41 if self.data.is_empty() {
42 return true;
43 }
44 let pos = (self.phase_q16 >> 16) as usize;
45 !self.looped && pos >= self.data.len()
46 }
47
48 #[inline]
49 fn get_sample(&self, idx: usize) -> i8 {
50 if idx >= self.data.len() {
51 0
52 } else if self.is_signed {
53 self.data[idx] as i8
54 } else {
55 self.data[idx].wrapping_sub(128) as i8
56 }
57 }
58
59 pub fn next_sample(&mut self) -> Option<i8> {
60 if self.data.is_empty() {
61 return None;
62 }
63
64 let curr_idx = (self.phase_q16 >> 16) as usize;
65
66 if curr_idx >= self.data.len() {
67 if self.looped {
68 let len = self.data.len();
69 let wrap = (curr_idx % len) << 16;
70 self.phase_q16 = (wrap as u32) | (self.phase_q16 & 0xFFFF);
71 } else {
72 return None;
73 }
74 }
75
76 let idx = (self.phase_q16 >> 16) as usize;
77 let frac = ((self.phase_q16 >> 8) & 0xFF) as u8;
78
79 let a = self.get_sample(idx);
80 let next_idx = if idx + 1 < self.data.len() {
81 idx + 1
82 } else if self.looped {
83 0
84 } else {
85 idx
86 };
87 let b = self.get_sample(next_idx);
88
89 let sample = lerp_i8(a, b, frac);
90 self.phase_q16 = self.phase_q16.wrapping_add(self.speed_q16);
91
92 Some(sample)
93 }
94}