Added front/rear speaker balance (actually the master/slave SCSP balance). Balance setting is stored in CSoundBoardConfig and can be set on the command line (-balance) or config file (Balance). Valid range is 100 (front speaker volume doubled, rear muted) to -100. The default is 0, both sets at full volume. Balance is applied in the SCSP core before overall sound and music volume settings.

This commit is contained in:
Bart Trzynadlowski 2012-02-09 07:58:07 +00:00
parent 6814ef1ed8
commit c5d0cb0d97
4 changed files with 87 additions and 18 deletions

View file

@ -53,7 +53,7 @@ public:
bool emulateDSB; // DSB emulation (enabled if true) bool emulateDSB; // DSB emulation (enabled if true)
// Sound (SCSP) volume (0-200, 100 being full amplitude) // Sound (SCSP) volume (0-200, 100 being full amplitude)
inline void SetSoundVolume(unsigned vol) inline void SetSoundVolume(int vol)
{ {
if (vol > 200) if (vol > 200)
{ {
@ -61,7 +61,13 @@ public:
vol = 100; vol = 100;
} }
soundVol = vol; if (vol < 0)
{
ErrorLog("Sound volume cannot be negative; setting to 0%%.\n");
vol = 0;
}
soundVol = (unsigned) vol;
} }
inline unsigned GetSoundVolume(void) inline unsigned GetSoundVolume(void)
@ -70,7 +76,7 @@ public:
} }
// Music (DSB MPEG) volume (0-200) // Music (DSB MPEG) volume (0-200)
inline void SetMusicVolume(unsigned vol) inline void SetMusicVolume(int vol)
{ {
if (vol > 200) if (vol > 200)
{ {
@ -78,7 +84,13 @@ public:
vol = 100; vol = 100;
} }
musicVol = vol; if (vol < 0)
{
ErrorLog("Music volume cannot be negative; setting to 0%%.\n");
vol = 0;
}
musicVol = (unsigned) vol;
} }
inline unsigned GetMusicVolume(void) inline unsigned GetMusicVolume(void)

View file

@ -43,11 +43,38 @@ class CSoundBoardConfig
public: public:
bool emulateSound; // sound board emulation (enabled if true) bool emulateSound; // sound board emulation (enabled if true)
// Master/slave SCSP relative balance (0-100, with 100 meaning master volume doubled, slave silenced)
inline void SetSCSPBalance(int bal)
{
if (bal > 100)
{
ErrorLog("Front/rear balance cannot exceed 100%%; setting to 100%%.\n");
bal = 100;
}
if (bal < -100)
{
ErrorLog("Front/rear balance cannot be less than -100%%; setting to -100%%.\n");
bal = -100;
}
scspBalance = bal;
}
inline int GetSCSPBalance(void)
{
return scspBalance;
}
// Defaults // Defaults
CSoundBoardConfig(void) CSoundBoardConfig(void)
{ {
emulateSound = true; emulateSound = true;
scspBalance = 50;
} }
private:
int scspBalance;
}; };
/* /*

View file

@ -355,6 +355,7 @@ static bool ConfigureInputs(CInputs *Inputs, bool configure)
static void ApplySettings(CINIFile *INI, const char *section) static void ApplySettings(CINIFile *INI, const char *section)
{ {
unsigned x; unsigned x;
int y;
string String; string String;
// Model 3 // Model 3
@ -374,6 +375,8 @@ static void ApplySettings(CINIFile *INI, const char *section)
g_Config.SetSoundVolume(x); g_Config.SetSoundVolume(x);
if (OKAY == INI->Get(section, "MusicVolume", x)) if (OKAY == INI->Get(section, "MusicVolume", x))
g_Config.SetMusicVolume(x); g_Config.SetMusicVolume(x);
if (OKAY == INI->Get(section, "Balance", y))
g_Config.SetSCSPBalance(y);
if (OKAY == INI->Get(section, "EmulateSound", x)) if (OKAY == INI->Get(section, "EmulateSound", x))
g_Config.emulateSound = x ? true : false; g_Config.emulateSound = x ? true : false;
if (OKAY == INI->Get(section, "EmulateDSB", x)) if (OKAY == INI->Get(section, "EmulateDSB", x))
@ -464,6 +467,7 @@ static void LogConfig(void)
// CSoundBoardConfig // CSoundBoardConfig
InfoLog("\tEmulateSound = %d", g_Config.emulateSound); InfoLog("\tEmulateSound = %d", g_Config.emulateSound);
InfoLog("\tBalance = %d", g_Config.GetSCSPBalance());
// CDSBConfig // CDSBConfig
InfoLog("\tEmulateDSB = %d", g_Config.emulateDSB); InfoLog("\tEmulateDSB = %d", g_Config.emulateDSB);
@ -1205,7 +1209,7 @@ static void Help(void)
puts(" -print-games List supported games and quit"); puts(" -print-games List supported games and quit");
puts(""); puts("");
puts("Core Options:"); puts("Core Options:");
printf(" -ppc-frequency=<f> PowerPC frequency in MHz [Default: %d]\n", g_Config.GetPowerPCFrequency()); printf(" -ppc-frequency=<freq> PowerPC frequency in MHz [Default: %d]\n", g_Config.GetPowerPCFrequency());
puts(" -no-threads Disable multi-threading"); puts(" -no-threads Disable multi-threading");
puts(""); puts("");
puts("Video Options:"); puts("Video Options:");
@ -1218,8 +1222,9 @@ static void Help(void)
puts(" -print-gl-info Print OpenGL driver information and quit"); puts(" -print-gl-info Print OpenGL driver information and quit");
puts(""); puts("");
puts("Audio Options:"); puts("Audio Options:");
puts(" -sound-volume=<v> Volume of sound effects in % [Default: 100]"); puts(" -sound-volume=<vol> Volume of sound effects in % [Default: 100]");
puts(" -music-volume=<v> Volume of MPEG music in % [Default: 100]"); puts(" -music-volume=<vol> Volume of MPEG music in % [Default: 100]");
puts(" -balance=<bal> Relative front/rear balance in % front [Default: 0]");
puts(" -flip-stereo Swap left and right audio channels"); puts(" -flip-stereo Swap left and right audio channels");
puts(" -no-sound Disable sound board emulation (sound effects)"); puts(" -no-sound Disable sound board emulation (sound effects)");
puts(" -no-dsb Disable Digital Sound Board (MPEG music)"); puts(" -no-dsb Disable Digital Sound Board (MPEG music)");
@ -1277,6 +1282,7 @@ int main(int argc, char **argv)
#endif // SUPERMODEL_DEBUGGER #endif // SUPERMODEL_DEBUGGER
char *inputSystem = NULL; // use default input system char *inputSystem = NULL; // use default input system
unsigned n; unsigned n;
int m;
UINT32 addr; UINT32 addr;
Title(); Title();
@ -1358,6 +1364,14 @@ int main(int argc, char **argv)
else else
CmdLine.Set("Global", "MusicVolume", n); CmdLine.Set("Global", "MusicVolume", n);
} }
else if (!strncmp(argv[i],"-balance",8))
{
ret = sscanf(&argv[i][8],"=%d",&m);
if (ret != 1)
ErrorLog("'-balance' requires a front/rear balance setting.");
else
CmdLine.Set("Global", "Balance", m);
}
else if (!strcmp(argv[i], "-flip-stereo")) else if (!strcmp(argv[i], "-flip-stereo"))
{ {
n = 1; n = 1;

View file

@ -968,7 +968,7 @@ void SCSP_w8(unsigned int addr,unsigned char val)
int slot=addr/0x20; int slot=addr/0x20;
addr&=0x1f; addr&=0x1f;
//DebugLog("Slot %02X Reg %02X write byte %04X\n",slot,addr^1,val); //DebugLog("Slot %02X Reg %02X write byte %04X\n",slot,addr^1,val);
//printf("Slot %02X Reg %02X write byte %04X\n",slot,addr^1,val); //printf("\tSlot %02X Reg %02X write byte %04X\n",slot,addr^1,val);
*(unsigned char *) &(SCSP->Slots[slot].datab[addr^1]) = val; *(unsigned char *) &(SCSP->Slots[slot].datab[addr^1]) = val;
SCSP_UpdateSlotReg(slot,(addr^1)&0x1f); SCSP_UpdateSlotReg(slot,(addr^1)&0x1f);
} }
@ -1008,7 +1008,7 @@ void SCSP_w16(unsigned int addr,unsigned short val)
int slot=addr/0x20; int slot=addr/0x20;
addr&=0x1f; addr&=0x1f;
//DebugLog("Slot %02X Reg %02X write word %04X\n",slot,addr,val); //DebugLog("Slot %02X Reg %02X write word %04X\n",slot,addr,val);
//printf("Slot %02X Reg %02X write word %04X\n",slot,addr,val); //printf("\tSlot %02X Reg %02X write word %04X\n",slot,addr,val);
*(unsigned short *) &(SCSP->Slots[slot].datab[addr]) = val; *(unsigned short *) &(SCSP->Slots[slot].datab[addr]) = val;
SCSP_UpdateSlotReg(slot,addr&0x1f); SCSP_UpdateSlotReg(slot,addr&0x1f);
} }
@ -1042,13 +1042,12 @@ void SCSP_w16(unsigned int addr,unsigned short val)
void SCSP_w32(unsigned int addr,unsigned int val) void SCSP_w32(unsigned int addr,unsigned int val)
{ {
addr&=0xffff; addr&=0xffff;
if(addr<0x400) if(addr<0x400)
{ {
int slot=addr/0x20; int slot=addr/0x20;
addr&=0x1f; addr&=0x1f;
//DebugLog("Slot %02X Reg %02X write dword %08X\n",slot,addr,val); //DebugLog("Slot %02X Reg %02X write dword %08X\n",slot,addr,val);
//printf("Slot %02X Reg %02X write dword %08X\n",slot,addr,val); //printf("\tSlot %02X Reg %02X write dword %08X\n",slot,addr,val);
rotl(val, 16); rotl(val, 16);
*(unsigned int *) &(SCSP->Slots[slot].datab[addr]) = val; *(unsigned int *) &(SCSP->Slots[slot].datab[addr]) = val;
@ -1765,6 +1764,19 @@ void SCSP_DoMasterSamples(int nsamples)
int slice=12000000/(SysFPS*nsamples); // 68K cycles/sample int slice=12000000/(SysFPS*nsamples); // 68K cycles/sample
static int lastdiff=0; static int lastdiff=0;
/*
* Compute relative master/slave SCSP balance (note: master is often used
* for the front speakers). Equal balance is a 1.0 scale factor for both.
* When one SCSP is fully attenuated, the other's samples will be multiplied
* by 2.
*/
float balance = (float) g_Config.GetSCSPBalance() / 100.0f;
float masterBalance = 1.0f+balance;
float slaveBalance = 1.0f-balance;
/*
* Generate samples
*/
for(int s=0;s<nsamples;++s) for(int s=0;s<nsamples;++s)
{ {
signed int smpl=0; signed int smpl=0;
@ -1778,12 +1790,12 @@ void SCSP_DoMasterSamples(int nsamples)
unsigned short Enc=((TL(slot))<<0x8)|((DIPAN(slot))<<0x0)|((DISDL(slot))<<0x5); unsigned short Enc=((TL(slot))<<0x8)|((DIPAN(slot))<<0x0)|((DISDL(slot))<<0x5);
RBUFDST=SCSPs[0].RINGBUF+SCSPs[0].BUFPTR; RBUFDST=SCSPs[0].RINGBUF+SCSPs[0].BUFPTR;
signed int sample; signed int sample;
//signed int sample=SCSP_UpdateSlot(slot); //signed int sample=(int) (masterBalance*(float)SCSP_UpdateSlot(slot));
//if(SA(slot)!=0x2ccf4) //if(SA(slot)!=0x2ccf4)
/*if(SA(slot)!=0x1c77e) /*if(SA(slot)!=0x1c77e)
sample=0; sample=0;
else*/ else*/
sample=SCSP_UpdateSlot(slot); sample= (int) (masterBalance*(float)SCSP_UpdateSlot(slot));
/*unsigned char ef=EFSDL(slot); /*unsigned char ef=EFSDL(slot);
@ -1816,7 +1828,7 @@ void SCSP_DoMasterSamples(int nsamples)
_SLOT *slot=SCSPs[1].Slots+sl; _SLOT *slot=SCSPs[1].Slots+sl;
unsigned short Enc=((TL(slot))<<0x8)|((DIPAN(slot))<<0x0)|((DISDL(slot))<<0x5); unsigned short Enc=((TL(slot))<<0x8)|((DIPAN(slot))<<0x0)|((DISDL(slot))<<0x5);
RBUFDST=SCSPs[1].RINGBUF+SCSPs[1].BUFPTR; RBUFDST=SCSPs[1].RINGBUF+SCSPs[1].BUFPTR;
signed int sample=SCSP_UpdateSlot(slot); signed int sample=(int) (slaveBalance*(float)SCSP_UpdateSlot(slot));
#ifdef USEDSP #ifdef USEDSP
SCSPDSP_SetSample(&SCSPs[1].DSP,(sample*LPANTABLE[(Enc|0xE0)&0xFFE0])>>(SHIFT+3),ISEL(slot),IMXL(slot)); SCSPDSP_SetSample(&SCSPs[1].DSP,(sample*LPANTABLE[(Enc|0xE0)&0xFFE0])>>(SHIFT+3),ISEL(slot),IMXL(slot));
#endif #endif
@ -1847,8 +1859,10 @@ void SCSP_DoMasterSamples(int nsamples)
if(ef) if(ef)
{ {
unsigned short Enc=0|((EFPAN(slot))<<0x0)|((EFSDL(slot))<<0x5); unsigned short Enc=0|((EFPAN(slot))<<0x0)|((EFSDL(slot))<<0x5);
smpl+=(SCSPs[0].DSP.EFREG[i]*LPANTABLE[Enc])>>SHIFT; signed int leftSample = (int) (masterBalance*(float)((SCSPs[0].DSP.EFREG[i]*LPANTABLE[Enc])>>SHIFT));
smpr+=(SCSPs[0].DSP.EFREG[i]*RPANTABLE[Enc])>>SHIFT; signed int rightSample = (int) (masterBalance*(float)((SCSPs[0].DSP.EFREG[i]*RPANTABLE[Enc])>>SHIFT));
smpl+=leftSample;
smpr+=rightSample;
} }
if(HasSlaveSCSP) if(HasSlaveSCSP)
{ {
@ -1857,8 +1871,10 @@ void SCSP_DoMasterSamples(int nsamples)
if(ef) if(ef)
{ {
unsigned short Enc=0|((EFPAN(slot))<<0x0)|((EFSDL(slot))<<0x5); unsigned short Enc=0|((EFPAN(slot))<<0x0)|((EFSDL(slot))<<0x5);
smpl+=(SCSPs[1].DSP.EFREG[i]*LPANTABLE[Enc])>>SHIFT; signed int leftSample = (int) (slaveBalance*(float)((SCSPs[1].DSP.EFREG[i]*LPANTABLE[Enc])>>SHIFT));
smpr+=(SCSPs[1].DSP.EFREG[i]*RPANTABLE[Enc])>>SHIFT; signed int rightSample = (int) (slaveBalance*(float)((SCSPs[1].DSP.EFREG[i]*RPANTABLE[Enc])>>SHIFT));
smpl+=leftSample;
smpr+=rightSample;
} }
} }
} }