mirror of
https://github.com/FunKey-Project/picodrive-irixxxx.git
synced 2026-09-16 12:22:16 +02:00
Add optional low pass audio filter
This commit is contained in:
@@ -99,6 +99,8 @@ typedef struct
|
||||
unsigned short overclockM68k; // overclock the emulated 68k, in %
|
||||
|
||||
int sndRate; // rate in Hz
|
||||
unsigned short sndFilter; // Set low pass sound filter 0: off, 1: on (use integer in case we want to add other filter types later)
|
||||
int32_t sndFilterRange; // Low pass sound filter range [0, 65536]
|
||||
short *sndOut; // PCM output buffer
|
||||
void (*writeSound)(int len); // write .sndOut callback, called once per frame
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ short cdda_out_buffer[2*1152];
|
||||
// sn76496
|
||||
extern int *sn76496_regs;
|
||||
|
||||
// Low pass filter 'previous' samples
|
||||
static int32_t lpf_lp;
|
||||
static int32_t lpf_rp;
|
||||
|
||||
static void dac_recalculate(void)
|
||||
{
|
||||
@@ -86,6 +89,10 @@ PICO_INTERNAL void PsndReset(void)
|
||||
// PsndRerate calls YM2612Init, which also resets
|
||||
PsndRerate(0);
|
||||
timers_reset();
|
||||
|
||||
// Reset low pass filter
|
||||
lpf_lp = 0;
|
||||
lpf_rp = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -318,6 +325,40 @@ static int PsndRender(int offset, int length)
|
||||
if ((PicoIn.AHW & PAHW_32X) && (PicoIn.opt & POPT_EN_PWM))
|
||||
p32x_pwm_update(buf32, length, stereo);
|
||||
|
||||
// Apply low pass filter, if required
|
||||
if (PicoIn.sndFilter == 1)
|
||||
{
|
||||
int samples = length;
|
||||
int *out32 = buf32;
|
||||
// Restore previous samples
|
||||
int32_t lpf_l = lpf_lp;
|
||||
int32_t lpf_r = lpf_rp;
|
||||
|
||||
// Single-pole low-pass filter (6 dB/octave)
|
||||
int32_t factor_a = PicoIn.sndFilterRange;
|
||||
int32_t factor_b = 0x10000 - factor_a;
|
||||
|
||||
do
|
||||
{
|
||||
// Apply low-pass filter
|
||||
lpf_l = (lpf_l * factor_a) + (out32[0] * factor_b);
|
||||
lpf_r = (lpf_r * factor_a) + (out32[1] * factor_b);
|
||||
|
||||
// 16.16 fixed point
|
||||
lpf_l >>= 16;
|
||||
lpf_r >>= 16;
|
||||
|
||||
// Update sound buffer
|
||||
*out32++ = lpf_l;
|
||||
*out32++ = lpf_r;
|
||||
}
|
||||
while (--samples);
|
||||
|
||||
// Save last samples for next frame
|
||||
lpf_lp = lpf_l;
|
||||
lpf_rp = lpf_r;
|
||||
}
|
||||
|
||||
// convert + limit to normal 16bit output
|
||||
PsndMix_32_to_16l(PicoIn.sndOut+offset, buf32, length);
|
||||
|
||||
|
||||
@@ -541,6 +541,8 @@ void retro_set_environment(retro_environment_t cb)
|
||||
#ifdef DRC_SH2
|
||||
{ "picodrive_drc", "Dynamic recompilers; enabled|disabled" },
|
||||
#endif
|
||||
{ "picodrive_audio_filter", "Audio filter; disabled|low-pass" },
|
||||
{ "picodrive_lowpass_range", "Low-pass filter %; 60|65|70|75|80|85|90|95|5|10|15|20|25|30|35|40|45|50|55"},
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
@@ -1337,6 +1339,21 @@ static void update_variables(void)
|
||||
if(!ctr_svchack_successful)
|
||||
PicoIn.opt &= ~POPT_EN_DRC;
|
||||
#endif
|
||||
|
||||
var.value = NULL;
|
||||
var.key = "picodrive_audio_filter";
|
||||
PicoIn.sndFilter = 0;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "low-pass") == 0)
|
||||
PicoIn.sndFilter = 1;
|
||||
}
|
||||
|
||||
var.value = NULL;
|
||||
var.key = "picodrive_lowpass_range";
|
||||
PicoIn.sndFilterRange = (60 * 65536) / 100;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
PicoIn.sndFilterRange = (atoi(var.value) * 65536) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
void retro_run(void)
|
||||
|
||||
Reference in New Issue
Block a user