+ added 3-Band Audio Equalizer support

This commit is contained in:
ekeeke31 2009-05-26 16:40:35 +00:00
parent 05014756ca
commit adcd65f2f4
7 changed files with 376 additions and 95 deletions

View File

@ -68,9 +68,11 @@ void config_default(void)
/* sound options */
config.psg_preamp = 150;
config.fm_preamp = 100;
config.boost = 1;
config.hq_fm = 1;
config.filter = 1;
config.lg = 1.0;
config.mg = 1.0;
config.hg = 1.0;
/* system options */
config.region_detect = 0;
@ -84,30 +86,34 @@ void config_default(void)
config.yscale = 0;
config.aspect = 1;
config.overscan = 1;
config.render = VIDEO_HaveComponentCable() ? 2 : 0;
if (VIDEO_HaveComponentCable())
config.render = 2;
else
config.render = 0;
config.ntsc = 0;
config.bilinear = 1;
/* controllers options */
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_GAMEPAD;
gx_input_SetDefault();
config.gun_cursor[0] = 1;
config.gun_cursor[1] = 1;
config.invert_mouse = 0;
gx_input_SetDefault();
/* menu options */
#ifdef HW_RVL
config.sram_auto = 0; /* let's assume we always have a FAT device by default */
/* let's assume we always have a FAT device by default */
config.sram_auto = 0;
#else
config.sram_auto = -1;
#endif
config.state_auto = -1;
config.bg_color = 0;
config.bgm_volume = 100.0;
config.sfx_volume = 100.0;
config.screen_w = 658;
config.ask_confirm = 0;
config.bgm_volume = 100.0;
config.sfx_volume = 100.0;
/* restore saved configuration */
config_load();

View File

@ -31,11 +31,13 @@
typedef struct
{
char version[16];
uint8 hq_fm;
int32 psg_preamp;
int32 fm_preamp;
uint8 boost;
uint8 filter;
uint8 hq_fm;
float lg;
float mg;
float hg;
uint8 region_detect;
uint8 force_dtack;
uint8 bios_enabled;
@ -54,13 +56,13 @@ typedef struct
uint16 pad_keymap[4][MAX_KEYS];
uint32 wpad_keymap[4*3][MAX_KEYS];
t_input_config input[MAX_INPUTS];
int8 bg_color;
float bgm_volume;
float sfx_volume;
int8 sram_auto;
int8 state_auto;
int8 bg_color;
int16 screen_w;
uint8 ask_confirm;
float bgm_volume;
float sfx_volume;
} t_config;
/* Global data */

View File

@ -217,13 +217,15 @@ static gui_item items_options[5] =
};
/* Audio options menu */
static gui_item items_audio[5] =
static gui_item items_audio[7] =
{
{NULL,NULL,"PSG Volume: 2.50", "Adjust PSG output level", 52,132,276,48},
{NULL,NULL,"FM Volume: 1.00", "Adjust FM output level", 52,132,276,48},
{NULL,NULL,"Volume Boost: 1x", "Adjust general output level", 52,132,276,48},
{NULL,NULL,"LowPass Filter: OFF","Enable/disable sound filtering", 52,132,276,48},
{NULL,NULL,"HQ YM2612: LINEAR", "Enable/disable FM chip interpolation",52,132,276,48}
{NULL,NULL,"High-Quality FM: LINEAR", "Setup YM2612 resampling", 52,132,276,48},
{NULL,NULL,"PSG Volume: 2.50", "Adjust SN76489 output level", 52,132,276,48},
{NULL,NULL,"FM Volume: 1.00", "Adjust YM2612 output level", 52,132,276,48},
{NULL,NULL,"Filtering: 3-BAND EQ", "Setup Audio filtering", 52,132,276,48},
{NULL,NULL,"Low Gain: 1.00", "Adjust EQ Low Gain", 52,132,276,48},
{NULL,NULL,"Middle Gain: 1.00", "Adjust EQ Middle Gain", 52,132,276,48},
{NULL,NULL,"High Gain: 1.00", "Adjust EQ High Gain", 52,132,276,48},
};
/* System options menu */
@ -434,7 +436,7 @@ static gui_menu menu_audio =
{
"Audio Settings",
0,0,
5,4,6,
7,4,6,
items_audio,
buttons_list,
bg_list,
@ -696,15 +698,25 @@ static void soundmenu ()
float psg_volume = (double)config.psg_preamp/100.0;
float fm_volume = (double)config.fm_preamp/100.0;
sprintf (items[0].text, "PSG Volume: %1.2f", psg_volume);
sprintf (items[1].text, "FM Volume: %1.2f", fm_volume);
sprintf (items[2].text, "Volume Boost: %dX", config.boost);
sprintf (items[3].text, "LowPass Filter: %s", config.filter ? " ON":"OFF");
if (config.hq_fm == 0) sprintf (items[4].text, "HQ YM2612: OFF");
else if (config.hq_fm == 1) sprintf (items[4].text, "HQ YM2612: LINEAR");
else sprintf (items[4].text, "HQ YM2612: SINC");
if (config.hq_fm == 0) sprintf (items[0].text, "High-Quality FM: OFF");
else if (config.hq_fm == 1) sprintf (items[0].text, "High-Quality FM: LINEAR");
else sprintf (items[0].text, "High-Quality FM: SINC");
sprintf (items[1].text, "PSG Volume: %1.2f", psg_volume);
sprintf (items[2].text, "FM Volume: %1.2f", (double)config.fm_preamp/100.0);
if (config.filter == 2) sprintf (items[3].text, "Filtering: 3-BAND EQ");
else if (config.filter == 1) sprintf (items[3].text, "Filtering: LOW PASS");
else sprintf (items[3].text, "Filtering: OFF");
sprintf (items[4].text, "Low Gain: %1.2f", config.lg);
sprintf (items[5].text, "Low Gain: %1.2f", config.mg);
sprintf (items[6].text, "Low Gain: %1.2f", config.hg);
GUI_InitMenu(m);
if (config.filter < 2)
m->max_items = 4;
else
m->max_items = 7;
GUI_SlideMenuTitle(m,strlen("Audio "));
while (quit == 0)
@ -714,34 +726,11 @@ static void soundmenu ()
switch (ret)
{
case 0:
GUI_OptionBox(m,0,"PSG Volume",(void *)&psg_volume,0.01,0.0,5.0,0);
sprintf (items[0].text, "PSG Volume: %1.2f", psg_volume);
config.psg_preamp = (int)(psg_volume * 100.0);
break;
case 1:
GUI_OptionBox(m,0,"FM Volume",(void *)&fm_volume,0.01,0.0,5.0,0);
sprintf (items[1].text, "FM Volume: %1.2f", (double)config.fm_preamp/100.0);
config.fm_preamp = (int)(fm_volume * 100.0);
break;
case 2:
config.boost ++;
if (config.boost > 4) config.boost = 0;
sprintf (items[2].text, "Volume Boost: %dX", config.boost);
break;
case 3:
config.filter ^= 1;
sprintf (items[3].text, "LowPass Filter: %s", config.filter ? " ON":"OFF");
break;
case 4:
config.hq_fm ++;
if (config.hq_fm > 2) config.hq_fm = 0;
if (config.hq_fm == 0) sprintf (items[4].text, "HQ YM2612: OFF");
else if (config.hq_fm == 1) sprintf (items[4].text, "HQ YM2612: LINEAR");
else sprintf (items[4].text, "HQ YM2612: SINC");
if (config.hq_fm == 0) sprintf (items[0].text, "High-Quality FM: OFF");
else if (config.hq_fm == 1) sprintf (items[0].text, "High-Quality FM: LINEAR");
else sprintf (items[0].text, "High-Quality FM: SINC");
if (genromsize)
{
unsigned char *temp = memalign(32,YM2612GetContextSize());
@ -755,12 +744,70 @@ static void soundmenu ()
}
break;
case 1:
GUI_OptionBox(m,0,"PSG Volume",(void *)&psg_volume,0.01,0.0,5.0,0);
sprintf (items[1].text, "PSG Volume: %1.2f", psg_volume);
config.psg_preamp = (int)(psg_volume * 100.0);
break;
case 2:
GUI_OptionBox(m,0,"FM Volume",(void *)&fm_volume,0.01,0.0,5.0,0);
sprintf (items[2].text, "FM Volume: %1.2f", (double)config.fm_preamp/100.0);
config.fm_preamp = (int)(fm_volume * 100.0);
break;
case 3:
config.filter ++;
if (config.filter > 2) config.filter = 0;
if (config.filter == 2)
sprintf (items[3].text, "Filtering: 3-BAND EQ");
else if (config.filter == 1)
sprintf (items[3].text, "Filtering: LOW PASS");
else
sprintf (items[3].text, "Filtering: OFF");
if (config.filter < 2)
{
/* reset menu selection */
m->offset = 0;
m->selected = 3;
m->max_items = 4;
}
else
{
/* enable items */
m->max_items = 7;
/* intialize EQ */
audio_init_equalizer();
}
break;
case 4:
GUI_OptionBox(m,0,"Low Gain",(void *)&config.lg,0.01,0.0,2.0,0);
sprintf (items[4].text, "Low Gain: %1.2f", config.lg);
audio_set_equalizer();
break;
case 5:
GUI_OptionBox(m,0,"Middle Gain",(void *)&config.mg,0.01,0.0,2.0,0);
sprintf (items[5].text, "Low Gain: %1.2f", config.mg);
audio_set_equalizer();
break;
case 6:
GUI_OptionBox(m,0,"High Gain",(void *)&config.hg,0.01,0.0,2.0,0);
sprintf (items[6].text, "Low Gain: %1.2f", config.hg);
audio_set_equalizer();
break;
case -1:
quit = 1;
break;
}
}
m->max_items = 7;
GUI_DeleteMenu(m);
}
@ -881,6 +928,12 @@ static void videomenu ()
else sprintf (items[5].text, "Aspect: FIT SCREEN");
GUI_InitMenu(m);
if (config.aspect)
m->max_items = 7;
else
m->max_items = 8;
GUI_SlideMenuTitle(m,strlen("Video "));
while (quit == 0)
@ -944,40 +997,40 @@ static void videomenu ()
if (config.aspect == 1) sprintf (items[5].text,"Aspect: ORIGINAL (4:3)");
else if (config.aspect == 2) sprintf (items[5].text, "Aspect: ORIGINAL (16:9)");
else sprintf (items[5].text, "Aspect: FIT SCREEN");
if (config.aspect)
{
/* disable items */
m->max_items = 7;
/* reset menu selection */
if (m->offset > 3)
{
m->offset = 3;
m->selected = 2;
}
}
else
{
/* enable items */
m->max_items = 8;
}
break;
/* case 6:
case -8:
if (ret<0) config.xshift --;
else config.xshift ++;
case 6:
break;
case 7:
case -9:
if (ret<0) config.yshift --;
else config.yshift ++;
break;
case 8:
case -10:
if (config.aspect) break;
if (ret<0) config.xscale --;
else config.xscale ++;
break;
case 9:
case -11:
if (config.aspect) break;
if (ret<0) config.yscale --;
else config.yscale ++;
break;
*/
case -1:
quit = 1;
break;
}
}
m->max_items = 8;
GUI_DeleteMenu(m);
}

129
source/sound/eq.c Normal file
View File

@ -0,0 +1,129 @@
//----------------------------------------------------------------------------
//
// 3 Band EQ :)
//
// EQ.C - Main Source file for 3 band EQ
//
// (c) Neil C / Etanza Systems / 2K6
//
// Shouts / Loves / Moans = etanza at lycos dot co dot uk
//
// This work is hereby placed in the public domain for all purposes, including
// use in commercial applications.
//
// The author assumes NO RESPONSIBILITY for any problems caused by the use of
// this software.
//
//----------------------------------------------------------------------------
// NOTES :
//
// - Original filter code by Paul Kellet (musicdsp.pdf)
//
// - Uses 4 first order filters in series, should give 24dB per octave
//
// - Now with P4 Denormal fix :)
//----------------------------------------------------------------------------
// ----------
//| Includes |
// ----------
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "eq.h"
// -----------
//| Constants |
// -----------
static double vsa = (1.0 / 4294967295.0); // Very small amount (Denormal Fix)
// ---------------
//| Initialise EQ |
// ---------------
// Recommended frequencies are ...
//
// lowfreq = 880 Hz
// highfreq = 5000 Hz
//
// Set mixfreq to whatever rate your system is using (eg 48Khz)
void init_3band_state(EQSTATE * es, int lowfreq, int highfreq, int mixfreq)
{
// Clear state
memset(es, 0, sizeof(EQSTATE));
// Set Low/Mid/High gains to unity
es->lg = 1.0;
es->mg = 1.0;
es->hg = 1.0;
// Calculate filter cutoff frequencies
es->lf = 2 * sin(M_PI * ((double) lowfreq / (double) mixfreq));
es->hf = 2 * sin(M_PI * ((double) highfreq / (double) mixfreq));
}
// ---------------
//| EQ one sample |
// ---------------
// - sample can be any range you like :)
//
// Note that the output will depend on the gain settings for each band
// (especially the bass) so may require clipping before output, but you
// knew that anyway :)
double do_3band(EQSTATE * es, int sample)
{
// Locals
double l, m, h; // Low / Mid / High - Sample Values
// Filter #1 (lowpass)
es->f1p0 += (es->lf * ((double) sample - es->f1p0)) + vsa;
es->f1p1 += (es->lf * (es->f1p0 - es->f1p1));
es->f1p2 += (es->lf * (es->f1p1 - es->f1p2));
es->f1p3 += (es->lf * (es->f1p2 - es->f1p3));
l = es->f1p3;
// Filter #2 (highpass)
es->f2p0 += (es->hf * ((double) sample - es->f2p0)) + vsa;
es->f2p1 += (es->hf * (es->f2p0 - es->f2p1));
es->f2p2 += (es->hf * (es->f2p1 - es->f2p2));
es->f2p3 += (es->hf * (es->f2p2 - es->f2p3));
h = es->sdm3 - es->f2p3;
// Calculate midrange (signal - (low + high))
m = es->sdm3 - (h + l);
// Scale, Combine and store
l *= es->lg;
m *= es->mg;
h *= es->hg;
// Shuffle history buffer
es->sdm3 = es->sdm2;
es->sdm2 = es->sdm1;
es->sdm1 = sample;
// Return result
return (int) (l + m + h);
}

67
source/sound/eq.h Normal file
View File

@ -0,0 +1,67 @@
//---------------------------------------------------------------------------
//
// 3 Band EQ :)
//
// EQ.H - Header file for 3 band EQ
//
// (c) Neil C / Etanza Systems / 2K6
//
// Shouts / Loves / Moans = etanza at lycos dot co dot uk
//
// This work is hereby placed in the public domain for all purposes, including
// use in commercial applications.
//
// The author assumes NO RESPONSIBILITY for any problems caused by the use of
// this software.
//
//----------------------------------------------------------------------------
#ifndef __EQ3BAND__
#define __EQ3BAND__
// ------------
//| Structures |
// ------------
typedef struct {
// Filter #1 (Low band)
double lf; // Frequency
double f1p0; // Poles ...
double f1p1;
double f1p2;
double f1p3;
// Filter #2 (High band)
double hf; // Frequency
double f2p0; // Poles ...
double f2p1;
double f2p2;
double f2p3;
// Sample history buffer
double sdm1; // Sample data minus 1
double sdm2; // 2
double sdm3; // 3
// Gain Controls
double lg; // low gain
double mg; // mid gain
double hg; // high gain
} EQSTATE;
// ---------
//| Exports |
// ---------
extern void init_3band_state(EQSTATE * es, int lowfreq, int highfreq,
int mixfreq);
extern double do_3band(EQSTATE * es, int sample);
#endif // #ifndef __EQ3BAND__

View File

@ -23,6 +23,7 @@
#include "shared.h"
#include "samplerate.h"
#include "eq.h"
#define SND_SIZE (snd.buffer_size * sizeof(int16))
@ -37,21 +38,36 @@ uint32 line_z80;
int32 current_z80;
uint8 system_hw;
/* SRC */
static SRC_DATA src_data;
/****************************************************************
* AUDIO equalizer
****************************************************************/
static EQSTATE eq;
static int ll, rr;
void audio_init_equalizer(void)
{
init_3band_state(&eq,880,5000,snd.sample_rate);
audio_set_equalizer();
}
void audio_set_equalizer(void)
{
eq.lg = (double)(config.lg);
eq.mg = (double)(config.mg);
eq.hg = (double)(config.hg);
}
/****************************************************************
* AUDIO stream update
****************************************************************/
static int ll, rr;
static SRC_DATA src_data;
void audio_update (int size)
{
int i;
int l, r;
int psg_preamp = config.psg_preamp;
int fm_preamp = config.fm_preamp;
int boost = config.boost;
int filter = config.filter;
#ifndef DOS
@ -109,18 +125,21 @@ void audio_update (int size)
*fm_r++ = 0;
}
/* single-pole low-pass filter (6 dB/octave) */
if (filter)
/* filtering */
if (filter & 1)
{
/* single-pole low-pass filter (6 dB/octave) */
l = (ll + l) >> 1;
r = (rr + r) >> 1;
ll = l;
rr = r;
}
/* boost volume if asked*/
l = l * boost;
r = r * boost;
else if (filter & 2)
{
/* 3 Band EQ */
l = do_3band(&eq,l);
r = do_3band(&eq,r);
}
/* clipping */
if (l > 32767) l = 32767;
@ -200,6 +219,9 @@ int audio_init (int rate)
snd.psg.buffer = (int16 *)malloc (SND_SIZE);
if (!snd.psg.buffer) return (-1);
/* 3 band EQ */
audio_init_equalizer();
/* Set audio enable flag */
snd.enabled = 1;

View File

@ -91,13 +91,15 @@ extern int32 current_z80;
extern uint8 system_hw;
/* Function prototypes */
extern void audio_init_equalizer(void);
extern void audio_set_equalizer(void);
extern int audio_init (int rate);
extern void audio_shutdown (void);
extern void audio_update (int len);
extern void system_init (void);
extern void system_reset (void);
extern void system_shutdown (void);
extern int system_frame(int skip);
extern int audio_init (int rate);
extern void audio_shutdown (void);
extern void audio_update (int len);
#endif /* _SYSTEM_H_ */