Add optional low pass audio filter

This commit is contained in:
jdgleaver
2018-11-22 14:58:34 +00:00
parent c64747fd2b
commit f4007769c2
3 changed files with 60 additions and 0 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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)