diff --git a/source/gx/config.c b/source/gx/config.c index 5fcae7e..0c15f16 100644 --- a/source/gx/config.c +++ b/source/gx/config.c @@ -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; + input.system[0] = SYSTEM_GAMEPAD; + input.system[1] = SYSTEM_GAMEPAD; + config.gun_cursor[0] = 1; + config.gun_cursor[1] = 1; + config.invert_mouse = 0; gx_input_SetDefault(); - config.gun_cursor[0] = 1; - config.gun_cursor[1] = 1; - config.invert_mouse = 0; /* 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; + 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.state_auto = -1; + config.bg_color = 0; + config.screen_w = 658; + config.ask_confirm = 0; + config.bgm_volume = 100.0; + config.sfx_volume = 100.0; /* restore saved configuration */ config_load(); diff --git a/source/gx/config.h b/source/gx/config.h index c955d8c..652cc7d 100644 --- a/source/gx/config.h +++ b/source/gx/config.h @@ -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 */ diff --git a/source/gx/gui/menu.c b/source/gx/gui/menu.c index 31e0003..34524cf 100644 --- a/source/gx/gui/menu.c +++ b/source/gx/gui/menu.c @@ -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 > 2) config.hq_fm = 0; + 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); } diff --git a/source/sound/eq.c b/source/sound/eq.c new file mode 100644 index 0000000..586072d --- /dev/null +++ b/source/sound/eq.c @@ -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 +#include +#include +#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); +} diff --git a/source/sound/eq.h b/source/sound/eq.h new file mode 100644 index 0000000..08d738e --- /dev/null +++ b/source/sound/eq.h @@ -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__ diff --git a/source/system.c b/source/system.c index de92081..62bc12b 100644 --- a/source/system.c +++ b/source/system.c @@ -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; diff --git a/source/system.h b/source/system.h index aece9e5..6e15e5c 100644 --- a/source/system.h +++ b/source/system.h @@ -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_ */