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:
Ian Curtis 2020-08-22 20:41:47 +00:00
parent cf64375371
commit 816d541b98
6 changed files with 1267 additions and 2127 deletions

View file

@ -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:");

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -29,150 +29,150 @@
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#define LFO_SHIFT 8 #define LFO_SHIFT 8
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];
} }
} }