Implemented dynamic low-pass filter for SB16/AWE32 DSP playback.
This commit is contained in:
parent
0e7c28261d
commit
75ec50cfd7
3 changed files with 77 additions and 7 deletions
|
|
@ -345,3 +345,33 @@ static inline float dac_iir(int i, float NewSample) {
|
||||||
|
|
||||||
return y[i][0];
|
return y[i][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define SB16_NCoef 51
|
||||||
|
|
||||||
|
extern float low_fir_sb16_coef[SB16_NCoef];
|
||||||
|
|
||||||
|
static inline float low_fir_sb16(int i, float NewSample)
|
||||||
|
{
|
||||||
|
static float x[2][SB16_NCoef+1]; //input samples
|
||||||
|
static int pos = 0;
|
||||||
|
float out = 0.0;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
//Calculate the new output
|
||||||
|
x[i][pos] = NewSample;
|
||||||
|
|
||||||
|
for (n = 0; n < ((SB16_NCoef+1)-pos); n++)
|
||||||
|
out += low_fir_sb16_coef[n] * x[i][n+pos];
|
||||||
|
for (; n < SB16_NCoef; n++)
|
||||||
|
out += low_fir_sb16_coef[n] * x[i][(n+pos) - (SB16_NCoef+1)];
|
||||||
|
|
||||||
|
if (i == 1)
|
||||||
|
{
|
||||||
|
pos++;
|
||||||
|
if (pos > SB16_NCoef)
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -261,9 +261,8 @@ static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p)
|
||||||
in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0;
|
in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0;
|
||||||
in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0;
|
in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0;
|
||||||
|
|
||||||
/*TODO: CT1745 features dynamic filtering. https://www.vogons.org/viewtopic.php?f=62&t=51514 */
|
out_l += ((int32_t)(low_fir_sb16(0, (float)sb->dsp.buffer[c]) * mixer->voice_l) / 3) >> 15;
|
||||||
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 15;
|
out_r += ((int32_t)(low_fir_sb16(1, (float)sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3) >> 15;
|
||||||
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 15;
|
|
||||||
|
|
||||||
out_l = (out_l * mixer->master_l) >> 15;
|
out_l = (out_l * mixer->master_l) >> 15;
|
||||||
out_r = (out_r * mixer->master_r) >> 15;
|
out_r = (out_r * mixer->master_r) >> 15;
|
||||||
|
|
@ -341,10 +340,8 @@ static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p)
|
||||||
in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0;
|
in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0;
|
||||||
in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0;
|
in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0;
|
||||||
|
|
||||||
|
out_l += ((int32_t)(low_fir_sb16(0, (float)sb->dsp.buffer[c]) * mixer->voice_l) / 3) >> 15;
|
||||||
/*TODO: CT1745 features dynamic filtering. https://www.vogons.org/viewtopic.php?f=62&t=51514 */
|
out_r += ((int32_t)(low_fir_sb16(1, (float)sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3) >> 15;
|
||||||
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 15;
|
|
||||||
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 15;
|
|
||||||
|
|
||||||
out_l = (out_l * mixer->master_l) >> 15;
|
out_l = (out_l * mixer->master_l) >> 15;
|
||||||
out_r = (out_r * mixer->master_r) >> 15;
|
out_r = (out_r * mixer->master_r) >> 15;
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,12 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
#include "ibm.h"
|
#include "ibm.h"
|
||||||
|
|
||||||
|
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
|
#include "filters.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
|
@ -108,6 +110,42 @@ uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x
|
||||||
252, 0, 252, 0
|
252, 0, 252, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float low_fir_sb16_coef[SB16_NCoef];
|
||||||
|
|
||||||
|
static inline double sinc(double x)
|
||||||
|
{
|
||||||
|
return sin(M_PI * x) / (M_PI * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recalc_sb16_filter(int playback_freq)
|
||||||
|
{
|
||||||
|
/*Cutoff frequency = playback / 2*/
|
||||||
|
float fC = ((float)playback_freq / 2.0) / 48000.0;
|
||||||
|
float gain;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < SB16_NCoef; n++)
|
||||||
|
{
|
||||||
|
/*Blackman window*/
|
||||||
|
double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(SB16_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(SB16_NCoef-1)));
|
||||||
|
/*Sinc filter*/
|
||||||
|
double h = sinc(2.0 * fC * ((double)n - ((double)(SB16_NCoef-1) / 2.0)));
|
||||||
|
|
||||||
|
/*Create windowed-sinc filter*/
|
||||||
|
low_fir_sb16_coef[n] = w * h;
|
||||||
|
}
|
||||||
|
|
||||||
|
low_fir_sb16_coef[(SB16_NCoef - 1) / 2] = 1.0;
|
||||||
|
|
||||||
|
gain = 0.0;
|
||||||
|
for (n = 0; n < SB16_NCoef; n++)
|
||||||
|
gain += low_fir_sb16_coef[n];
|
||||||
|
|
||||||
|
/*Normalise filter, to produce unity gain*/
|
||||||
|
for (n = 0; n < SB16_NCoef; n++)
|
||||||
|
low_fir_sb16_coef[n] /= gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void sb_irq(sb_dsp_t *dsp, int irq8)
|
void sb_irq(sb_dsp_t *dsp, int irq8)
|
||||||
|
|
@ -399,6 +437,8 @@ void sb_exec_command(sb_dsp_t *dsp)
|
||||||
temp = 256 - dsp->sb_data[0];
|
temp = 256 - dsp->sb_data[0];
|
||||||
temp = 1000000 / temp;
|
temp = 1000000 / temp;
|
||||||
// pclog("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho);
|
// pclog("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho);
|
||||||
|
if (dsp->sb_freq != temp && dsp->sb_type >= SB16)
|
||||||
|
recalc_sb16_filter(temp);
|
||||||
dsp->sb_freq = temp;
|
dsp->sb_freq = temp;
|
||||||
break;
|
break;
|
||||||
case 0x41: /*Set output sampling rate*/
|
case 0x41: /*Set output sampling rate*/
|
||||||
|
|
@ -406,10 +446,13 @@ void sb_exec_command(sb_dsp_t *dsp)
|
||||||
if (dsp->sb_type < SB16) break;
|
if (dsp->sb_type < SB16) break;
|
||||||
dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8))));
|
dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8))));
|
||||||
// pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho);
|
// pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho);
|
||||||
|
temp = dsp->sb_freq;
|
||||||
dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8);
|
dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8);
|
||||||
dsp->sb_timeo = 256 + dsp->sb_freq;
|
dsp->sb_timeo = 256 + dsp->sb_freq;
|
||||||
dsp->sblatchi = dsp->sblatcho;
|
dsp->sblatchi = dsp->sblatcho;
|
||||||
dsp->sb_timei = dsp->sb_timeo;
|
dsp->sb_timei = dsp->sb_timeo;
|
||||||
|
if (dsp->sb_freq != temp && dsp->sb_type >= SB16)
|
||||||
|
recalc_sb16_filter(dsp->sb_freq);
|
||||||
break;
|
break;
|
||||||
case 0x48: /*Set DSP block transfer size*/
|
case 0x48: /*Set DSP block transfer size*/
|
||||||
dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
|
dsp->sb_8_autolen = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue