mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-26 15:45:41 +00:00
Various SCSP improvements and code cleanup:
- Ported MAME's implementation - Corrected FM sound for songs in VF3 that use it - Music tempo now closer to real hardware thanks to emulating two SCSP chips. - Add LegacySoundDSP config option for games with SCSP DSP glitches (ex. engine noises in Sega Rally 2, and loud garbage on Bahn's stage in Fighting Vipers 2) - Renamed SysFPS to "SoundClock" (since raising this appears to adjust the sound frequency). (Submitted by Paul Prosser)
This commit is contained in:
parent
cf64375371
commit
816d541b98
|
@ -1371,6 +1371,8 @@ static Util::Config::Node DefaultConfig()
|
||||||
config.Set("EmulateDSB", true);
|
config.Set("EmulateDSB", true);
|
||||||
config.Set("SoundVolume", "100");
|
config.Set("SoundVolume", "100");
|
||||||
config.Set("MusicVolume", "100");
|
config.Set("MusicVolume", "100");
|
||||||
|
// Other sound options
|
||||||
|
config.Set("LegacySoundDSP", false); // New config option for games that do not play correctly with MAME's SCSP sound core.
|
||||||
// CDriveBoard
|
// CDriveBoard
|
||||||
#ifdef SUPERMODEL_WIN32
|
#ifdef SUPERMODEL_WIN32
|
||||||
config.Set("ForceFeedback", false);
|
config.Set("ForceFeedback", false);
|
||||||
|
@ -1469,6 +1471,8 @@ static void Help(void)
|
||||||
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)");
|
||||||
|
puts(" -legacy-sound Enable ElSemi's legacy SCSP DSP emulator from 0.2a. Recommended for Sega Rally 2 as engine sound does not work with MAME's implementation.");
|
||||||
|
puts(" -no-legacy-sound Disable ElSemi's legacy SCSP DSP emulator and use MAME's implementation instead");
|
||||||
puts("");
|
puts("");
|
||||||
#ifdef NET_BOARD
|
#ifdef NET_BOARD
|
||||||
puts("Net Options:");
|
puts("Net Options:");
|
||||||
|
|
1897
Src/Sound/SCSP.cpp
1897
Src/Sound/SCSP.cpp
File diff suppressed because it is too large
Load diff
|
@ -24,7 +24,7 @@
|
||||||
*
|
*
|
||||||
* Header file defining for SCSP emulation.
|
* Header file defining for SCSP emulation.
|
||||||
*/
|
*/
|
||||||
|
#define MAX_SCSP 2
|
||||||
#ifndef INCLUDED_SCSP_H
|
#ifndef INCLUDED_SCSP_H
|
||||||
#define INCLUDED_SCSP_H
|
#define INCLUDED_SCSP_H
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -38,6 +38,7 @@ struct _SCSPDSP
|
||||||
{
|
{
|
||||||
//Config
|
//Config
|
||||||
UINT16 *SCSPRAM;
|
UINT16 *SCSPRAM;
|
||||||
|
UINT32 SCSPRAM_LENGTH;
|
||||||
unsigned int RBP; //Ring buf pointer
|
unsigned int RBP; //Ring buf pointer
|
||||||
unsigned int RBL; //Delay ram (Ring buffer) size in words
|
unsigned int RBL; //Delay ram (Ring buffer) size in words
|
||||||
|
|
||||||
|
|
|
@ -33,146 +33,146 @@
|
||||||
|
|
||||||
struct _LFO
|
struct _LFO
|
||||||
{
|
{
|
||||||
unsigned short phase;
|
unsigned short phase;
|
||||||
DWORD phase_step;
|
UINT32 phase_step;
|
||||||
int *table;
|
int *table;
|
||||||
int *scale;
|
int *scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))
|
#define LFIX(v) ((unsigned int) ((float) (1<<LFO_SHIFT)*(v)))
|
||||||
|
|
||||||
//Convert DB to multiply amplitude
|
//Convert DB to multiply amplitude
|
||||||
#define DB(v) LFIX(pow(10.0,(float) (v)/20.0))
|
#define DB(v) LFIX(pow(10.0,v/20.0))
|
||||||
|
|
||||||
//Convert cents to step increment
|
//Convert cents to step increment
|
||||||
#define CENTS(v) LFIX(pow(2.0,(float) (v)/1200.0))
|
#define CENTS(v) LFIX(pow(2.0,v/1200.0))
|
||||||
|
|
||||||
static int PLFO_TRI[256],PLFO_SQR[256],PLFO_SAW[256],PLFO_NOI[256];
|
static int PLFO_TRI[256], PLFO_SQR[256], PLFO_SAW[256], PLFO_NOI[256];
|
||||||
static int ALFO_TRI[256],ALFO_SQR[256],ALFO_SAW[256],ALFO_NOI[256];
|
static int ALFO_TRI[256], ALFO_SQR[256], ALFO_SAW[256], ALFO_NOI[256];
|
||||||
static float LFOFreq[32]={0.17f,0.19f,0.23f,0.27f,0.34f,0.39f,0.45f,0.55f,0.68f,0.78f,0.92f,1.10f,1.39f,1.60f,1.87f,2.27f,
|
static float LFOFreq[32] = { 0.17,0.19,0.23,0.27,0.34,0.39,0.45,0.55,0.68,0.78,0.92,1.10,1.39,1.60,1.87,2.27,
|
||||||
2.87f,3.31f,3.92f,4.79f,6.15f,7.18f,8.60f,10.8f,14.4f,17.2f,21.5f,28.7f,43.1f,57.4f,86.1f,172.3f};
|
2.87,3.31,3.92,4.79,6.15,7.18,8.60,10.8,14.4,17.2,21.5,28.7,43.1,57.4,86.1,172.3 };
|
||||||
static float ASCALE[8]={0.0f,0.4f,0.8f,1.5f,3.0f,6.0f,12.0f,24.0f};
|
static float ASCALE[8] = { 0.0,0.4,0.8,1.5,3.0,6.0,12.0,24.0 };
|
||||||
static float PSCALE[8]={0.0f,7.0f,13.5f,27.0f,55.0f,112.0f,230.0f,494.0f};
|
static float PSCALE[8] = { 0.0,7.0,13.5,27.0,55.0,112.0,230.0,494 };
|
||||||
static int PSCALES[8][256];
|
static int PSCALES[8][256];
|
||||||
static int ASCALES[8][256];
|
static int ASCALES[8][256];
|
||||||
|
|
||||||
void LFO_Init()
|
void LFO_Init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i, s;
|
||||||
for(i=0;i<256;++i)
|
for (i = 0; i < 256; ++i)
|
||||||
{
|
{
|
||||||
int a,p;
|
int a, p;
|
||||||
float TL;
|
// float TL;
|
||||||
//Saw
|
//Saw
|
||||||
a=255-i;
|
a = 255 - i;
|
||||||
if(i<128)
|
if (i < 128)
|
||||||
p=i;
|
p = i;
|
||||||
else
|
else
|
||||||
p=255-i;
|
p = i - 256;
|
||||||
ALFO_SAW[i]=a;
|
ALFO_SAW[i] = a;
|
||||||
PLFO_SAW[i]=p;
|
PLFO_SAW[i] = p;
|
||||||
|
|
||||||
//Square
|
//Square
|
||||||
if(i<128)
|
if (i < 128)
|
||||||
{
|
{
|
||||||
a=255;
|
a = 255;
|
||||||
p=127;
|
p = 127;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
a=0;
|
a = 0;
|
||||||
p=-128;
|
p = -128;
|
||||||
}
|
}
|
||||||
ALFO_SQR[i]=a;
|
ALFO_SQR[i] = a;
|
||||||
PLFO_SQR[i]=p;
|
PLFO_SQR[i] = p;
|
||||||
|
|
||||||
//Tri
|
//Tri
|
||||||
if(i<128)
|
if (i < 128)
|
||||||
a=255-(i*2);
|
a = 255 - (i * 2);
|
||||||
else
|
else
|
||||||
a=(i*2)-256;
|
a = (i * 2) - 256;
|
||||||
if(i<64)
|
if (i < 64)
|
||||||
p=i*2;
|
p = i * 2;
|
||||||
else if(i<128)
|
else if (i < 128)
|
||||||
p=255-i*2;
|
p = 255 - i * 2;
|
||||||
else if(i<192)
|
else if (i < 192)
|
||||||
p=256-i*2;
|
p = 256 - i * 2;
|
||||||
else
|
else
|
||||||
p=i*2-511;
|
p = i * 2 - 511;
|
||||||
ALFO_TRI[i]=a;
|
ALFO_TRI[i] = a;
|
||||||
PLFO_TRI[i]=p;
|
PLFO_TRI[i] = p;
|
||||||
|
|
||||||
//noise
|
//noise
|
||||||
//a=lfo_noise[i];
|
//a=lfo_noise[i];
|
||||||
a=rand()&0xff;
|
a = rand() & 0xff;
|
||||||
p=128-a;
|
p = 128 - a;
|
||||||
ALFO_NOI[i]=a;
|
ALFO_NOI[i] = a;
|
||||||
PLFO_NOI[i]=p;
|
PLFO_NOI[i] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int s=0;s<8;++s)
|
for (s = 0; s < 8; ++s)
|
||||||
{
|
{
|
||||||
float limit=PSCALE[s];
|
float limit = PSCALE[s];
|
||||||
for(i=-128;i<128;++i)
|
for (i = -128; i < 128; ++i)
|
||||||
{
|
{
|
||||||
PSCALES[s][i+128]=CENTS(((limit*((float) i))/128.0));
|
PSCALES[s][i + 128] = CENTS(((limit*(float)i) / 128.0));
|
||||||
}
|
}
|
||||||
limit=-ASCALE[s];
|
limit = -ASCALE[s];
|
||||||
for(i=0;i<256;++i)
|
for (i = 0; i < 256; ++i)
|
||||||
{
|
{
|
||||||
ASCALES[s][i]=DB(((limit*(float) i)/256.0));
|
ASCALES[s][i] = DB(((limit*(float)i) / 256.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signed int inline PLFO_Step(_LFO *LFO)
|
signed int INLINE PLFO_Step(struct _LFO *LFO)
|
||||||
{
|
{
|
||||||
int p;
|
int p;
|
||||||
LFO->phase+=LFO->phase_step;
|
LFO->phase += LFO->phase_step;
|
||||||
#if LFO_SHIFT!=8
|
#if LFO_SHIFT!=8
|
||||||
LFO->phase&=(1<<(LFO_SHIFT+8))-1;
|
LFO->phase &= (1 << (LFO_SHIFT + 8)) - 1;
|
||||||
#endif
|
#endif
|
||||||
p=LFO->table[LFO->phase>>LFO_SHIFT];
|
p = LFO->table[LFO->phase >> LFO_SHIFT];
|
||||||
p=LFO->scale[p+128];
|
p = LFO->scale[p + 128];
|
||||||
return p<<(SHIFT-LFO_SHIFT);
|
return p << (SHIFT - LFO_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
signed int inline ALFO_Step(_LFO *LFO)
|
signed int INLINE ALFO_Step(struct _LFO *LFO)
|
||||||
{
|
{
|
||||||
int p;
|
int p;
|
||||||
LFO->phase+=LFO->phase_step;
|
LFO->phase += LFO->phase_step;
|
||||||
#if LFO_SHIFT!=8
|
#if LFO_SHIFT!=8
|
||||||
LFO->phase&=(1<<(LFO_SHIFT+8))-1;
|
LFO->phase &= (1 << (LFO_SHIFT + 8)) - 1;
|
||||||
#endif
|
#endif
|
||||||
p=LFO->table[LFO->phase>>LFO_SHIFT];
|
p = LFO->table[LFO->phase >> LFO_SHIFT];
|
||||||
p=LFO->scale[p];
|
p = LFO->scale[p];
|
||||||
return p<<(SHIFT-LFO_SHIFT);
|
return p << (SHIFT - LFO_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LFO_ComputeStep(_LFO *LFO,DWORD LFOF,DWORD LFOWS,DWORD LFOS,int ALFO)
|
void LFO_ComputeStep(struct _LFO *LFO, UINT32 LFOF, UINT32 LFOWS, UINT32 LFOS, int ALFO)
|
||||||
{
|
{
|
||||||
float step=(float) LFOFreq[LFOF]*256.0f/(float) srate;
|
float step = (float)LFOFreq[LFOF] * 256.0 / (float)44100.0;
|
||||||
LFO->phase_step=(unsigned int) ((float) (1<<LFO_SHIFT)*step);
|
LFO->phase_step = (unsigned int)((float)(1 << LFO_SHIFT)*step);
|
||||||
if(ALFO)
|
if (ALFO)
|
||||||
{
|
{
|
||||||
switch(LFOWS)
|
switch (LFOWS)
|
||||||
{
|
{
|
||||||
case 0: LFO->table=ALFO_SAW; break;
|
case 0: LFO->table = ALFO_SAW; break;
|
||||||
case 1: LFO->table=ALFO_SQR; break;
|
case 1: LFO->table = ALFO_SQR; break;
|
||||||
case 2: LFO->table=ALFO_TRI; break;
|
case 2: LFO->table = ALFO_TRI; break;
|
||||||
case 3: LFO->table=ALFO_NOI; break;
|
case 3: LFO->table = ALFO_NOI; break;
|
||||||
}
|
}
|
||||||
LFO->scale=ASCALES[LFOS];
|
LFO->scale = ASCALES[LFOS];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch(LFOWS)
|
switch (LFOWS)
|
||||||
{
|
{
|
||||||
case 0: LFO->table=PLFO_SAW; break;
|
case 0: LFO->table = PLFO_SAW; break;
|
||||||
case 1: LFO->table=PLFO_SQR; break;
|
case 1: LFO->table = PLFO_SQR; break;
|
||||||
case 2: LFO->table=PLFO_TRI; break;
|
case 2: LFO->table = PLFO_TRI; break;
|
||||||
case 3: LFO->table=PLFO_NOI; break;
|
case 3: LFO->table = PLFO_NOI; break;
|
||||||
}
|
}
|
||||||
LFO->scale=PSCALES[LFOS];
|
LFO->scale = PSCALES[LFOS];
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue