SNES audio resampling code

3use crate::apu;
4use bincode::{Decode, Encode};
5use dsp::design::FilterType;
6use dsp::iir::FirstOrderIirFilter;
7use dsp::sinc::QualitySincResampler;
8use jgenesis_common::frontend::AudioOutput;
10const SNES_AUDIO_FREQUENCY: f64 = apu::OUTPUT_FREQUENCY as f64;
11
12fn new_dc_offset_filter() -> FirstOrderIirFilter {
13    dsp::design::butterworth(5.0, SNES_AUDIO_FREQUENCY, FilterType::HighPass)
14}
15
16#[derive(Debug, Clone, Encode, Decode)]
17pub struct AudioResampler {
18    dc_offset_l: FirstOrderIirFilter,
19    dc_offset_r: FirstOrderIirFilter,
20    resampler: QualitySincResampler<2>,
21}
22
23impl AudioResampler {
24    pub fn new() -> Self {
25        Self {
26            dc_offset_l: new_dc_offset_filter(),
27            dc_offset_r: new_dc_offset_filter(),
28            resampler: QualitySincResampler::new(SNES_AUDIO_FREQUENCY, 48000.0),
29        }
30    }
31
32    pub fn collect_sample(&mut self, sample_l: f64, sample_r: f64) {
33        let sample_l = self.dc_offset_l.filter(sample_l);
34        let sample_r = self.dc_offset_r.filter(sample_r);
35        self.resampler.collect([sample_l, sample_r]);
36    }
37
38    pub fn output_samples<A: AudioOutput>(&mut self, audio_output: &mut A) -> Result<(), A::Err> {
39        while let Some([sample_l, sample_r]) = self.resampler.output_buffer_pop_front() {
40            audio_output.push_sample(sample_l, sample_r)?;
41        }
42
43        Ok(())
44    }
45
46    pub fn update_output_frequency(&mut self, output_frequency: u64) {
47        self.resampler.update_output_frequency(output_frequency as f64);
48    }
49}