diff --git a/src/dac.rs b/src/dac.rs index f3fa49f..19773a5 100644 --- a/src/dac.rs +++ b/src/dac.rs @@ -135,4 +135,70 @@ impl<'a, T: DacInterface> DpcmDac<'a, T> { pub fn disable_output(&mut self) { self.output.disable(); } +} + + + +pub struct DpcmDecoder<'a> { + data: Option<&'a [u8]>, + index: usize, + prev_amplitude: usize, + step_size: usize, + min: usize, + max: usize, +} + +impl<'a> DpcmDecoder<'a> { + pub fn new() -> Self { + Self { + data: None, + index: 0, + prev_amplitude: 0x80, + step_size: 0x3, + min: 0x19, + max: 0xe6, + } + } + pub fn load_data(&mut self, data: &'a [u8]) { + self.data = Some(data); + } + pub fn seek_to_sample(&mut self, index: usize) { + self.index = index; + } + + // output the next sample's amplitude + pub fn output_next(&mut self) -> usize { + if let Some(data) = self.data { + let sub_index = 1 - self.index % 2; + + let sample = DpcmSample::new(data[self.index / 2], sub_index); + let new_amplitude = match sample.direction { + Direction::Down => self.prev_amplitude.saturating_sub(sample.step_count as usize * self.step_size).max(self.min), + Direction ::Up => (self.prev_amplitude + (sample.step_count as usize * self.step_size)).min(self.max), + }; + + // calculate normalized amplitude + // TODO: e4c811653781e69e40b63fd27a8c1e20 + let normalized_amplitude = (new_amplitude - self.min) * 100 / (self.max - self.min); + self.prev_amplitude = new_amplitude; + + + // increment the sample index + let mut samples_remaining = true; + self.index = self.index + 1; + + // reset the index to 0 if we roll over + if (self.index >= data.len() * 2) { + self.index = 0; + self.prev_amplitude = 0x74; + samples_remaining = false; + } + + // return the normalized amplitude + return normalized_amplitude; + } else { + // otherwise just output 0 + 0 + } + } } \ No newline at end of file