different downsample types
This commit is contained in:
parent
bfb895ef4c
commit
659fc4869a
|
@ -9,7 +9,7 @@ use cpal::{
|
|||
};
|
||||
use futures::executor;
|
||||
use gb_emu_lib::{
|
||||
connect::{AudioOutput, EmulatorMessage, JoypadState, Renderer, RomFile},
|
||||
connect::{AudioOutput, DownsampleType, EmulatorMessage, JoypadState, Renderer, RomFile},
|
||||
util::scale_buffer,
|
||||
EmulatorCore,
|
||||
};
|
||||
|
@ -115,6 +115,9 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
const FRAMES_TO_BUFFER: usize = 1;
|
||||
const DOWNSAMPLE_TYPE: DownsampleType = DownsampleType::ZeroOrderHold;
|
||||
|
||||
fn create_audio_output() -> (AudioOutput, Stream) {
|
||||
let host = cpal::default_host();
|
||||
|
||||
|
@ -132,7 +135,8 @@ fn create_audio_output() -> (AudioOutput, Stream) {
|
|||
|
||||
let sample_rate = config.sample_rate().0;
|
||||
|
||||
let (output, mut rx) = AudioOutput::new_unfilled(sample_rate as f32, true, 1);
|
||||
let (output, mut rx) =
|
||||
AudioOutput::new_unfilled(sample_rate as f32, true, FRAMES_TO_BUFFER, DOWNSAMPLE_TYPE);
|
||||
|
||||
let stream = device
|
||||
.build_output_stream(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use async_ringbuf::AsyncHeapConsumer;
|
||||
use futures::executor;
|
||||
use gb_emu_lib::{
|
||||
connect::{AudioOutput, EmulatorMessage, JoypadButtons, RomFile},
|
||||
connect::{AudioOutput, DownsampleType, EmulatorMessage, JoypadButtons, RomFile},
|
||||
EmulatorCore,
|
||||
};
|
||||
use nih_plug::prelude::*;
|
||||
|
@ -34,6 +34,7 @@ type JoypadSender = Mutex<Option<Sender<(JoypadButtons, bool)>>>;
|
|||
|
||||
const FRAMES_TO_BUFFER: usize = 1;
|
||||
const INCLUDE_BOOTROM: bool = false;
|
||||
const DOWNSAMPLE_TYPE: DownsampleType = DownsampleType::ZeroOrderHold;
|
||||
|
||||
impl Plugin for GameboyEmu {
|
||||
const NAME: &'static str = "Gameboy";
|
||||
|
@ -128,16 +129,24 @@ impl Plugin for GameboyEmu {
|
|||
};
|
||||
|
||||
if let Some(ref mut vars) = self.vars {
|
||||
let (output, rx) =
|
||||
AudioOutput::new_unfilled(buffer_config.sample_rate, false, FRAMES_TO_BUFFER);
|
||||
let (output, rx) = AudioOutput::new_unfilled(
|
||||
buffer_config.sample_rate,
|
||||
false,
|
||||
FRAMES_TO_BUFFER,
|
||||
DOWNSAMPLE_TYPE,
|
||||
);
|
||||
|
||||
vars.emulator_core.replace_output(output);
|
||||
vars.rx = rx;
|
||||
} else {
|
||||
let (sender, receiver) = channel::<EmulatorMessage>();
|
||||
|
||||
let (output, rx) =
|
||||
AudioOutput::new_unfilled(buffer_config.sample_rate, false, FRAMES_TO_BUFFER);
|
||||
let (output, rx) = AudioOutput::new_unfilled(
|
||||
buffer_config.sample_rate,
|
||||
false,
|
||||
FRAMES_TO_BUFFER,
|
||||
DOWNSAMPLE_TYPE,
|
||||
);
|
||||
|
||||
let (renderer, frame_receiver, key_handler) = EmulatorRenderer::new();
|
||||
|
||||
|
|
|
@ -8,6 +8,12 @@ pub enum EmulatorMessage {
|
|||
Stop,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum DownsampleType {
|
||||
Linear,
|
||||
ZeroOrderHold,
|
||||
}
|
||||
|
||||
pub enum RomFile {
|
||||
Path(String),
|
||||
Raw(Vec<u8>),
|
||||
|
@ -43,6 +49,7 @@ pub struct AudioOutput {
|
|||
pub sample_rate: f32,
|
||||
pub send_rb: AsyncHeapProducer<[f32; 2]>,
|
||||
pub wait_for_output: bool,
|
||||
pub downsample_type: DownsampleType,
|
||||
}
|
||||
|
||||
impl AudioOutput {
|
||||
|
@ -50,8 +57,14 @@ impl AudioOutput {
|
|||
sample_rate: f32,
|
||||
wait_for_output: bool,
|
||||
frames_to_buffer: usize,
|
||||
downsample_type: DownsampleType,
|
||||
) -> (Self, AsyncHeapConsumer<[f32; 2]>) {
|
||||
let (mut output, rx) = Self::new_unfilled(sample_rate, wait_for_output, frames_to_buffer);
|
||||
let (mut output, rx) = Self::new_unfilled(
|
||||
sample_rate,
|
||||
wait_for_output,
|
||||
frames_to_buffer,
|
||||
downsample_type,
|
||||
);
|
||||
|
||||
executor::block_on(
|
||||
output
|
||||
|
@ -67,6 +80,7 @@ impl AudioOutput {
|
|||
sample_rate: f32,
|
||||
wait_for_output: bool,
|
||||
frames_to_buffer: usize,
|
||||
downsample_type: DownsampleType,
|
||||
) -> (Self, AsyncHeapConsumer<[f32; 2]>) {
|
||||
let rb_len = (sample_rate as usize / 60) * frames_to_buffer;
|
||||
|
||||
|
@ -78,6 +92,7 @@ impl AudioOutput {
|
|||
sample_rate,
|
||||
send_rb,
|
||||
wait_for_output,
|
||||
downsample_type,
|
||||
},
|
||||
rx,
|
||||
)
|
||||
|
|
|
@ -59,13 +59,13 @@ impl Apu {
|
|||
div_apu: 0,
|
||||
buffer: vec![],
|
||||
out_buffer: vec![],
|
||||
converter: Downsampler::new(output.sample_rate),
|
||||
converter: Downsampler::new(output.sample_rate, output.downsample_type),
|
||||
output,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_output(&mut self, new: AudioOutput) {
|
||||
self.converter = Downsampler::new(new.sample_rate);
|
||||
self.converter = Downsampler::new(new.sample_rate, new.downsample_type);
|
||||
self.output = new;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::constants::CLOCK_SPEED;
|
||||
use crate::{connect::DownsampleType, constants::CLOCK_SPEED};
|
||||
|
||||
const TIME_PER_CYCLE: f32 = 1. / CLOCK_SPEED as f32;
|
||||
|
||||
|
@ -42,15 +42,18 @@ impl Averager {
|
|||
pub(super) struct Downsampler {
|
||||
ratio: f32,
|
||||
time_accum: f32,
|
||||
average: Averager,
|
||||
average: Option<Averager>,
|
||||
}
|
||||
|
||||
impl Downsampler {
|
||||
pub fn new(sample_rate: f32) -> Self {
|
||||
pub fn new(sample_rate: f32, algo: DownsampleType) -> Self {
|
||||
Self {
|
||||
ratio: 1. / sample_rate,
|
||||
time_accum: 0.,
|
||||
average: Averager::default(),
|
||||
average: match algo {
|
||||
DownsampleType::Linear => Some(Averager::default()),
|
||||
DownsampleType::ZeroOrderHold => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,10 +61,16 @@ impl Downsampler {
|
|||
let mut output = vec![];
|
||||
for ref val in signal {
|
||||
self.time_accum += TIME_PER_CYCLE;
|
||||
self.average.push(val);
|
||||
if let Some(ref mut averager) = self.average {
|
||||
averager.push(val);
|
||||
}
|
||||
if self.time_accum >= self.ratio {
|
||||
self.time_accum = 0.;
|
||||
output.push(self.average.finish());
|
||||
output.push(if let Some(ref mut averager) = self.average {
|
||||
averager.finish()
|
||||
} else {
|
||||
*val
|
||||
});
|
||||
}
|
||||
}
|
||||
output
|
||||
|
|
Loading…
Reference in a new issue