diff --git a/Src/Model3/DSB.h b/Src/Model3/DSB.h index e846cce..09ab60b 100644 --- a/Src/Model3/DSB.h +++ b/Src/Model3/DSB.h @@ -53,7 +53,7 @@ public: bool emulateDSB; // DSB emulation (enabled if true) // Sound (SCSP) volume (0-200, 100 being full amplitude) - inline void SetSoundVolume(unsigned vol) + inline void SetSoundVolume(int vol) { if (vol > 200) { @@ -61,7 +61,13 @@ public: 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) @@ -70,7 +76,7 @@ public: } // Music (DSB MPEG) volume (0-200) - inline void SetMusicVolume(unsigned vol) + inline void SetMusicVolume(int vol) { if (vol > 200) { @@ -78,7 +84,13 @@ public: 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) diff --git a/Src/Model3/SoundBoard.h b/Src/Model3/SoundBoard.h index 8692834..6c9d3a9 100644 --- a/Src/Model3/SoundBoard.h +++ b/Src/Model3/SoundBoard.h @@ -43,11 +43,38 @@ class CSoundBoardConfig public: 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 CSoundBoardConfig(void) { emulateSound = true; + scspBalance = 50; } + +private: + int scspBalance; }; /* diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index dbca5e4..7161b6d 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -355,6 +355,7 @@ static bool ConfigureInputs(CInputs *Inputs, bool configure) static void ApplySettings(CINIFile *INI, const char *section) { unsigned x; + int y; string String; // Model 3 @@ -374,6 +375,8 @@ static void ApplySettings(CINIFile *INI, const char *section) g_Config.SetSoundVolume(x); if (OKAY == INI->Get(section, "MusicVolume", x)) g_Config.SetMusicVolume(x); + if (OKAY == INI->Get(section, "Balance", y)) + g_Config.SetSCSPBalance(y); if (OKAY == INI->Get(section, "EmulateSound", x)) g_Config.emulateSound = x ? true : false; if (OKAY == INI->Get(section, "EmulateDSB", x)) @@ -464,6 +467,7 @@ static void LogConfig(void) // CSoundBoardConfig InfoLog("\tEmulateSound = %d", g_Config.emulateSound); + InfoLog("\tBalance = %d", g_Config.GetSCSPBalance()); // CDSBConfig InfoLog("\tEmulateDSB = %d", g_Config.emulateDSB); @@ -1205,7 +1209,7 @@ static void Help(void) puts(" -print-games List supported games and quit"); puts(""); puts("Core Options:"); - printf(" -ppc-frequency= PowerPC frequency in MHz [Default: %d]\n", g_Config.GetPowerPCFrequency()); + printf(" -ppc-frequency= PowerPC frequency in MHz [Default: %d]\n", g_Config.GetPowerPCFrequency()); puts(" -no-threads Disable multi-threading"); puts(""); puts("Video Options:"); @@ -1218,8 +1222,9 @@ static void Help(void) puts(" -print-gl-info Print OpenGL driver information and quit"); puts(""); puts("Audio Options:"); - puts(" -sound-volume= Volume of sound effects in % [Default: 100]"); - puts(" -music-volume= Volume of MPEG music in % [Default: 100]"); + puts(" -sound-volume= Volume of sound effects in % [Default: 100]"); + puts(" -music-volume= Volume of MPEG music in % [Default: 100]"); + puts(" -balance= Relative front/rear balance in % front [Default: 0]"); puts(" -flip-stereo Swap left and right audio channels"); puts(" -no-sound Disable sound board emulation (sound effects)"); puts(" -no-dsb Disable Digital Sound Board (MPEG music)"); @@ -1277,6 +1282,7 @@ int main(int argc, char **argv) #endif // SUPERMODEL_DEBUGGER char *inputSystem = NULL; // use default input system unsigned n; + int m; UINT32 addr; Title(); @@ -1358,6 +1364,14 @@ int main(int argc, char **argv) else 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")) { n = 1; diff --git a/Src/Sound/SCSP.cpp b/Src/Sound/SCSP.cpp index 8922f6e..c6f0ff1 100644 --- a/Src/Sound/SCSP.cpp +++ b/Src/Sound/SCSP.cpp @@ -968,7 +968,7 @@ void SCSP_w8(unsigned int addr,unsigned char val) int slot=addr/0x20; addr&=0x1f; //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; SCSP_UpdateSlotReg(slot,(addr^1)&0x1f); } @@ -1008,7 +1008,7 @@ void SCSP_w16(unsigned int addr,unsigned short val) int slot=addr/0x20; addr&=0x1f; //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; 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) { addr&=0xffff; - if(addr<0x400) { int slot=addr/0x20; addr&=0x1f; //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); *(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 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>(SHIFT+3),ISEL(slot),IMXL(slot)); #endif @@ -1847,8 +1859,10 @@ void SCSP_DoMasterSamples(int nsamples) if(ef) { unsigned short Enc=0|((EFPAN(slot))<<0x0)|((EFSDL(slot))<<0x5); - smpl+=(SCSPs[0].DSP.EFREG[i]*LPANTABLE[Enc])>>SHIFT; - smpr+=(SCSPs[0].DSP.EFREG[i]*RPANTABLE[Enc])>>SHIFT; + signed int leftSample = (int) (masterBalance*(float)((SCSPs[0].DSP.EFREG[i]*LPANTABLE[Enc])>>SHIFT)); + signed int rightSample = (int) (masterBalance*(float)((SCSPs[0].DSP.EFREG[i]*RPANTABLE[Enc])>>SHIFT)); + smpl+=leftSample; + smpr+=rightSample; } if(HasSlaveSCSP) { @@ -1857,8 +1871,10 @@ void SCSP_DoMasterSamples(int nsamples) if(ef) { unsigned short Enc=0|((EFPAN(slot))<<0x0)|((EFSDL(slot))<<0x5); - smpl+=(SCSPs[1].DSP.EFREG[i]*LPANTABLE[Enc])>>SHIFT; - smpr+=(SCSPs[1].DSP.EFREG[i]*RPANTABLE[Enc])>>SHIFT; + signed int leftSample = (int) (slaveBalance*(float)((SCSPs[1].DSP.EFREG[i]*LPANTABLE[Enc])>>SHIFT)); + signed int rightSample = (int) (slaveBalance*(float)((SCSPs[1].DSP.EFREG[i]*RPANTABLE[Enc])>>SHIFT)); + smpl+=leftSample; + smpr+=rightSample; } } }