1mod constants;
2
3use crate::psg::PSG_FREQUENCY;
4use bincode::{Decode, Encode};
5use dsp::sinc::PerformanceSincResampler;
6use jgenesis_common::audio::fir_resampler::{FirKernel, LpfCoefficients, StereoFirResampler};
7use pce_config::PceAudioResampler;
8
9#[derive(Debug, Clone, Encode, Decode)]
10pub struct PsgLpfKernel;
11
12impl FirKernel<{ constants::LPF_TAPS }> for PsgLpfKernel {
13    fn lpf_coefficients() -> &'static LpfCoefficients<{ constants::LPF_TAPS }> {
14        constants::LPF_COEFFICIENTS
15    }
16}
17
18#[derive(Debug, Clone, Encode, Decode)]
19pub enum PsgResampler {
20    LowPassNearestNeighbor(StereoFirResampler<{ constants::LPF_TAPS }, PsgLpfKernel>),
21    WindowedSinc(PerformanceSincResampler<2>),
22}
23
24impl PsgResampler {
25    pub fn new(resampler: PceAudioResampler, output_frequency: u64) -> Self {
26        match resampler {
27            PceAudioResampler::WindowedSinc => Self::WindowedSinc(PerformanceSincResampler::new(
28                PSG_FREQUENCY,
29                output_frequency as f64,
30            )),
31            PceAudioResampler::LowPassNearestNeighbor => Self::LowPassNearestNeighbor(
32                StereoFirResampler::new(PSG_FREQUENCY, output_frequency),
33            ),
34        }
35    }
36
37    pub fn collect(&mut self, sample: [f64; 2]) {
38        match self {
39            Self::LowPassNearestNeighbor(resampler) => resampler.collect(sample),
40            Self::WindowedSinc(resampler) => resampler.collect(sample),
41        }
42    }
43
44    pub fn output_buffer_pop_front(&mut self) -> Option<[f64; 2]> {
45        match self {
46            Self::LowPassNearestNeighbor(resampler) => resampler.output_buffer_pop_front(),
47            Self::WindowedSinc(resampler) => resampler.output_buffer_pop_front(),
48        }
49    }
50
51    pub fn update_output_frequency(&mut self, output_frequency: f64) {
52        match self {
53            Self::LowPassNearestNeighbor(resampler) => {
54                resampler.update_output_frequency(output_frequency);
55            }
56            Self::WindowedSinc(resampler) => resampler.update_output_frequency(output_frequency),
57        }
58    }
59
60    pub fn resampler_impl(&self) -> PceAudioResampler {
61        match self {
62            Self::LowPassNearestNeighbor(..) => PceAudioResampler::LowPassNearestNeighbor,
63            Self::WindowedSinc(..) => PceAudioResampler::WindowedSinc,
64        }
65    }
66}