change all INT16 mixing/intermediate clamping to floats

also fixes 3 bugs:
1) mpeg right channel volume was always using the left channel volume, too
2) too high MusicVolume setting was not clamped to 0..200
3) too high SoundVolume setting was not clamped to 0..200
This commit is contained in:
toxieainc 2022-11-03 11:49:35 +01:00 committed by trzy
parent 121f81c742
commit 4c727abdc8
10 changed files with 164 additions and 205 deletions

View file

@ -91,7 +91,7 @@ const char* CInput::GetInputGroup()
case Game::INPUT_JOYSTICK1: // Fall through to below
case Game::INPUT_JOYSTICK2: return "4-Way Joysticks";
case Game::INPUT_FIGHTING: return "Fighting Game Buttons";
case Game::INPUT_SPIKEOUT: return "Spikeout Buttons";
case Game::INPUT_SPIKEOUT: return "Spikeout Buttons";
case Game::INPUT_SOCCER: return "Virtua Striker Buttons";
case Game::INPUT_VEHICLE: return "Racing Game Steering Controls";
case Game::INPUT_SHIFT4: return "Racing Game Gear 4-Way Shift";
@ -108,8 +108,8 @@ const char* CInput::GetInputGroup()
case Game::INPUT_ANALOG_GUN2: return "Analog Guns";
case Game::INPUT_SKI: return "Ski Controls";
case Game::INPUT_MAGTRUCK: return "Magical Truck Controls";
case Game::INPUT_FISHING: return "Fishing Controls";
default: return "Misc";
case Game::INPUT_FISHING: return "Fishing Controls";
default: return "Misc";
}
}
@ -138,7 +138,7 @@ void CInput::AppendMapping(const char *mapping)
else
{
// Otherwise, append to mapping string and recreate source from new mapping string
int size = MAX_MAPPING_LENGTH - strlen(m_mapping);
size_t size = MAX_MAPPING_LENGTH - strlen(m_mapping);
strncat(m_mapping, ",", size--);
strncat(m_mapping, mapping, size);
CreateSource();

View file

@ -125,52 +125,31 @@ void CDSBResampler::Reset(void)
pFrac = 1<<8; // previous sample (1.0->0 as x moves p->n)
}
// Mixes 16-bit samples (sign extended in a and b)
static inline INT16 MixAndClip(INT32 a, INT32 b)
{
a += b;
if (a > 32767)
a = 32767;
else if (a < -32768)
a = -32768;
return (INT16) a;
}
// Mixes audio and returns number of samples copied back to start of buffer (ie. offset at which new samples should be written)
int CDSBResampler::UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *inR, UINT8 volumeL, UINT8 volumeR, int sizeOut, int sizeIn, int outRate, int inRate)
int CDSBResampler::UpSampleAndMix(float *outL, float *outR, INT16 *inL, INT16 *inR, UINT8 volumeL, UINT8 volumeR, int sizeOut, int sizeIn, int outRate, int inRate)
{
int delta = (inRate<<8)/outRate; // (1/fout)/(1/fin)=fin/fout, 24.8 fixed point
int outIdx = 0;
int inIdx = 0;
INT32 leftSample, rightSample, leftSoundSample, rightSoundSample;
INT32 v[2], musicVol;
float v[2], musicVol;
// Obtain program volume settings and convert to 24.8 fixed point (0-200 -> 0x00-0x200)
musicVol = m_config["MusicVolume"].ValueAs<int>();
musicVol = (INT32) ((float) 0x100 * (float) musicVol / 100.0f);
// Obtain program volume settings
musicVol = (float)std::max(0,std::min(200,m_config["MusicVolume"].ValueAs<int>()));
musicVol = musicVol * (float) (1.0 / 100.0);
// Scale volume from 0x00-0xFF -> 0x00-0x100 (24.8 fixed point)
v[0] = (INT16) ((float) 0x100 * (float) volumeL / 255.0f);
v[1] = (INT16) ((float) 0x100 * (float) volumeR / 255.0f);
v[0] = musicVol * (float) volumeL * (float) (1.0 / (255.0*256.0)); // 256 is there to correct for fixed point interpolation below
v[1] = musicVol * (float) volumeR * (float) (1.0 / (255.0*256.0));
// Up-sample and mix!
while (outIdx < sizeOut)
{
// nFrac, pFrac will never exceed 1.0 (0x100) (only true if delta does not exceed 1)
leftSample = ((int)inL[inIdx]*pFrac+(int)inL[inIdx+1]*nFrac) >> 8; // left channel
rightSample = ((int)inR[inIdx]*pFrac+(int)inR[inIdx+1]*nFrac) >> 8; // right channel
INT32 leftSample = (int)inL[inIdx]*pFrac+(int)inL[inIdx+1]*nFrac; // left channel
INT32 rightSample = (int)inR[inIdx]*pFrac+(int)inR[inIdx+1]*nFrac; // right channel
// Apply DSB volume and then overall music volume setting
leftSample = (leftSample*v[0]*musicVol) >> 16; // multiplied by two 24.8 numbers, shift back by 16
rightSample = (rightSample*v[0]*musicVol) >> 16;
// Apply sound volume setting
leftSoundSample = outL[outIdx];
rightSoundSample = outR[outIdx];
// Mix and output
outL[outIdx] = MixAndClip(leftSoundSample, leftSample);
outR[outIdx] = MixAndClip(rightSoundSample, rightSample);
// Apply DSB volume+overall music volume setting, and mix into output
outL[outIdx] += (float)leftSample * v[0];
outR[outIdx] += (float)rightSample * v[1];
outIdx++;
// Time step
@ -422,11 +401,8 @@ void CDSB1::SendCommand(UINT8 data)
#endif
}
void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR)
void CDSB1::RunFrame(float *audioL, float *audioR)
{
int cycles;
UINT8 v;
if (!m_config["EmulateDSB"].ValueAs<bool>())
{
// DSB code applies SCSP volume, too, so we must still mix
@ -436,6 +412,7 @@ void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR)
return;
}
int cycles;
// While FIFO not empty, fire interrupts, run for up to one frame
for (cycles = (4000000/60); (cycles > 0) && (fifoIdxR != fifoIdxW); )
{
@ -450,7 +427,7 @@ void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR)
//printf("VOLUME=%02X STEREO=%02X\n", volume, stereo);
// Convert volume from 0x00-0x7F -> 0x00-0xFF
v = (UINT8) ((float) 255.0f * (float) volume /127.0f);
UINT8 v = (UINT8) ((float) volume * (float)(255.0/127.0));
// Decode MPEG for this frame
MpegDec::DecodeAudio(&mpegL[retainedSamples], &mpegR[retainedSamples], 32000 / 60 - retainedSamples + 2);
@ -991,14 +968,14 @@ void CDSB2::SendCommand(UINT8 data)
}
void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR)
void CDSB2::RunFrame(float *audioL, float *audioR)
{
if (!m_config["EmulateDSB"].ValueAs<bool>())
{
// DSB code applies SCSP volume, too, so we must still mix
memset(mpegL, 0, (32000 / 60 + 2) * sizeof(INT16));
memset(mpegR, 0, (32000 / 60 + 2) * sizeof(INT16));
retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, volume[0], volume[1], NUM_SAMPLES_PER_FRAME, 32000 / 60 + 2, 44100, 32000);
memset(mpegL, 0, (32000/60+2) * sizeof(INT16));
memset(mpegR, 0, (32000/60+2) * sizeof(INT16));
retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, 0, 0, NUM_SAMPLES_PER_FRAME, 32000/60+2, 44100, 32000);
return;
}
@ -1069,7 +1046,7 @@ void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR)
break;
}
retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, leftChannelSource, rightChannelSource, volL, volR, NUM_SAMPLES_PER_FRAME, 32000 / 60 + 2, 44100, 32000);
retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, leftChannelSource, rightChannelSource, volL, volR, NUM_SAMPLES_PER_FRAME, 32000/60+2, 44100, 32000);
}
void CDSB2::Reset(void)

View file

@ -71,7 +71,7 @@
class CDSBResampler
{
public:
int UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *inR, UINT8 volumeL, UINT8 volumeR, int sizeOut, int sizeIn, int outRate, int inRate);
int UpSampleAndMix(float *outL, float *outR, INT16 *inL, INT16 *inR, UINT8 volumeL, UINT8 volumeR, int sizeOut, int sizeIn, int outRate, int inRate);
void Reset(void);
CDSBResampler(const Util::Config::Node &config)
: m_config(config)
@ -114,7 +114,7 @@ public:
* audioL Left audio channel, one frame (44 KHz, 1/60th second).
* audioR Right audio channel.
*/
virtual void RunFrame(INT16 *audioL, INT16 *audioR) = 0;
virtual void RunFrame(float *audioL, float *audioR) = 0;
/*
* Reset(void):
@ -187,7 +187,7 @@ public:
// DSB interface (see CDSB definition)
void SendCommand(UINT8 data);
void RunFrame(INT16 *audioL, INT16 *audioR);
void RunFrame(float *audioL, float *audioR);
void Reset(void);
void SaveState(CBlockFile *StateFile);
void LoadState(CBlockFile *StateFile);
@ -264,7 +264,7 @@ public:
// DSB interface (see definition of CDSB)
void SendCommand(UINT8 data);
void RunFrame(INT16 *audioL, INT16 *audioR);
void RunFrame(float *audioL, float *audioR);
void Reset(void);
void SaveState(CBlockFile *StateFile);
void LoadState(CBlockFile *StateFile);

View file

@ -70,11 +70,11 @@ static FILE *soundFP;
// Offsets of memory regions within sound board's pool
#define OFFSET_RAM1 0 // 1 MB SCSP1 RAM
#define OFFSET_RAM2 0x100000 // 1 MB SCSP2 RAM
#define LENGTH_CHANNEL_BUFFER (sizeof(INT16)*NUM_SAMPLES_PER_FRAME) // 1470 bytes (16 bits x 44.1 KHz x 1/60th second)
#define OFFSET_AUDIO_FRONTLEFT 0x200000 // 1470 bytes (16 bits, 44.1 KHz, 1/60th second) left audio channel
#define OFFSET_AUDIO_FRONTRIGHT (OFFSET_AUDIO_FRONTLEFT + LENGTH_CHANNEL_BUFFER) // 1470 bytes right audio channel
#define OFFSET_AUDIO_REARLEFT (OFFSET_AUDIO_FRONTRIGHT + LENGTH_CHANNEL_BUFFER) // 1470 bytes (16 bits, 44.1 KHz, 1/60th second) left audio channel
#define OFFSET_AUDIO_REARRIGHT (OFFSET_AUDIO_REARLEFT + LENGTH_CHANNEL_BUFFER) // 1470 bytes right audio channel
#define LENGTH_CHANNEL_BUFFER (sizeof(float)*NUM_SAMPLES_PER_FRAME) // 2940 bytes (32 bits x 44.1 KHz x 1/60th second)
#define OFFSET_AUDIO_FRONTLEFT 0x200000 // 2940 bytes (32 bits, 44.1 KHz, 1/60th second) left audio channel
#define OFFSET_AUDIO_FRONTRIGHT (OFFSET_AUDIO_FRONTLEFT + LENGTH_CHANNEL_BUFFER) // 2940 bytes right audio channel
#define OFFSET_AUDIO_REARLEFT (OFFSET_AUDIO_FRONTRIGHT + LENGTH_CHANNEL_BUFFER) // 2940 bytes (32 bits, 44.1 KHz, 1/60th second) left audio channel
#define OFFSET_AUDIO_REARRIGHT (OFFSET_AUDIO_REARLEFT + LENGTH_CHANNEL_BUFFER) // 2940 bytes right audio channel
#define MEMORY_POOL_SIZE (0x100000 + 0x100000 + 4*LENGTH_CHANNEL_BUFFER)
@ -351,6 +351,18 @@ void CSoundBoard::WriteMIDIPort(UINT8 data)
DSB->SendCommand(data);
}
static INT16 ClampINT16(float x)
{
INT32 xi = (INT32)x;
if (xi > INT16_MAX) {
xi = INT16_MAX;
}
if (xi < INT16_MIN) {
xi = INT16_MIN;
}
return (INT16)xi;
}
bool CSoundBoard::RunFrame(void)
{
// Run sound board first to generate SCSP audio
@ -369,15 +381,15 @@ bool CSoundBoard::RunFrame(void)
}
// Compute sound volume as
INT32 soundVol = m_config["SoundVolume"].ValueAs<int>();
soundVol = (INT32)((float)0x100 * (float)soundVol / 100.0f);
float soundVol = (float)std::max(0,std::min(200,m_config["SoundVolume"].ValueAs<int>()));
soundVol = soundVol * (float)(1.0 / 100.0);
// Apply sound volume setting to SCSP channels only
for (int i = 0; i < NUM_SAMPLES_PER_FRAME; i++) {
audioFL[i] = (audioFL[i]*soundVol) >> 8;
audioFR[i] = (audioFR[i]*soundVol) >> 8;
audioRL[i] = (audioRL[i]*soundVol) >> 8;
audioRR[i] = (audioRR[i]*soundVol) >> 8;
audioFL[i] *= soundVol;
audioFR[i] *= soundVol;
audioRL[i] *= soundVol;
audioRR[i] *= soundVol;
}
// Run DSB and mix with existing audio, apply music volume
@ -399,9 +411,13 @@ bool CSoundBoard::RunFrame(void)
INT16 s;
for (int i = 0; i < NUM_SAMPLES_PER_FRAME; i++)
{
s = audioL[i];
s = ClampINT16(audioFL[i]);
fwrite(&s, sizeof(INT16), 1, soundFP); // left channel
s = audioR[i];
s = ClampINT16(audioFR[i]);
fwrite(&s, sizeof(INT16), 1, soundFP); // right channel
s = ClampINT16(audioRL[i]);
fwrite(&s, sizeof(INT16), 1, soundFP); // left channel
s = ClampINT16(audioRR[i]);
fwrite(&s, sizeof(INT16), 1, soundFP); // right channel
}
#endif // SUPERMODEL_LOG_AUDIO
@ -496,10 +512,10 @@ bool CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr)
// Set up memory pointers
ram1 = &memoryPool[OFFSET_RAM1];
ram2 = &memoryPool[OFFSET_RAM2];
audioFL = (INT16*)&memoryPool[OFFSET_AUDIO_FRONTLEFT];
audioFR = (INT16*)&memoryPool[OFFSET_AUDIO_FRONTRIGHT];
audioRL = (INT16*)&memoryPool[OFFSET_AUDIO_REARLEFT];
audioRR = (INT16*)&memoryPool[OFFSET_AUDIO_REARRIGHT];
audioFL = (float*)&memoryPool[OFFSET_AUDIO_FRONTLEFT];
audioFR = (float*)&memoryPool[OFFSET_AUDIO_FRONTRIGHT];
audioRL = (float*)&memoryPool[OFFSET_AUDIO_REARLEFT];
audioRR = (float*)&memoryPool[OFFSET_AUDIO_REARRIGHT];
// Initialize 68K core
M68KSetContext(&M68K);

View file

@ -203,8 +203,8 @@ private:
UINT8 ctrlReg; // control register: ROM banking
// Audio
INT16* audioFL, * audioFR; // left and right front audio channels (1/60th second, 44.1 KHz)
INT16* audioRL, * audioRR; // left and right rear audio channels (1/60th second, 44.1 KHz)
float* audioFL, * audioFR; // left and right front audio channels (1/60th second, 44.1 KHz)
float* audioRL, * audioRR; // left and right rear audio channels (1/60th second, 44.1 KHz)
};

View file

@ -51,7 +51,7 @@ extern bool OpenAudio(const Util::Config::Node& config);
*
* Sends a chunk of two-channel audio with the given number of samples to the audio system.
*/
extern bool OutputAudio(unsigned numSamples, INT16* leftFrontBuffer, INT16* rightFrontBuffer, INT16* leftRearBuffer, INT16* rightRearBuffer, bool flipStereo);
extern bool OutputAudio(unsigned numSamples, const float* leftFrontBuffer, const float* rightFrontBuffer, const float* leftRearBuffer, const float* rightRearBuffer, bool flipStereo);
/*
* CloseAudio()

View file

@ -166,6 +166,35 @@ static INT16 MixINT16(INT32 x, INT32 y)
return (INT16)sum;
}
static INT16 MixINT16(float x, float y)
{
INT32 sum = (INT32)((x + y)*0.5f); //!! dither
if (sum > INT16_MAX) {
sum = INT16_MAX;
}
if (sum < INT16_MIN) {
sum = INT16_MIN;
}
return (INT16)sum;
}
static float MixFloat(float x, float y)
{
return (x + y)*0.5f;
}
static INT16 ClampINT16(float x)
{
INT32 xi = (INT32)x;
if (xi > INT16_MAX) {
xi = INT16_MAX;
}
if (xi < INT16_MIN) {
xi = INT16_MIN;
}
return (INT16)xi;
}
static void PlayCallback(void* data, Uint8* stream, int len)
{
//printf("PlayCallback(%d) [writePos = %u, writeWrapped = %s, playPos = %u, audioBufferSize = %u]\n",
@ -271,15 +300,15 @@ static void PlayCallback(void* data, Uint8* stream, int len)
callback(callbackData);
}
static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* rightFrontBuffer, INT16* leftRearBuffer, INT16* rightRearBuffer, void* dest, bool flipStereo)
static void MixChannels(unsigned numSamples, const float* leftFrontBuffer, const float* rightFrontBuffer, const float* leftRearBuffer, const float* rightRearBuffer, void* dest, bool flipStereo)
{
INT16* p = (INT16*)dest;
if (nbHostAudioChannels == 1) {
for (unsigned i = 0; i < numSamples; i++) {
INT16 monovalue = MixINT16(
MixINT16((INT32)(leftFrontBuffer[i] * balanceFactorFrontLeft), (INT32)(rightFrontBuffer[i] * balanceFactorFrontRight)),
MixINT16((INT32)(leftRearBuffer[i] * balanceFactorRearLeft), (INT32)(rightRearBuffer[i] * balanceFactorRearRight)));
MixFloat(leftFrontBuffer[i] * balanceFactorFrontLeft,rightFrontBuffer[i] * balanceFactorFrontRight),
MixFloat(leftRearBuffer[i] * balanceFactorRearLeft, rightRearBuffer[i] * balanceFactorRearRight));
*p++ = monovalue;
}
} else {
@ -295,8 +324,8 @@ static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* righ
// Now order channels according to audio type
if (nbHostAudioChannels == 2) {
for (unsigned i = 0; i < numSamples; i++) {
INT16 leftvalue = MixINT16((INT32)(leftFrontBuffer[i] * balanceFactorFrontLeft), (INT32)(leftRearBuffer[i] * balanceFactorRearLeft));
INT16 rightvalue = MixINT16((INT32)(rightFrontBuffer[i]*balanceFactorFrontRight), (INT32)(rightRearBuffer[i]*balanceFactorRearRight));
INT16 leftvalue = MixINT16(leftFrontBuffer[i] * balanceFactorFrontLeft, leftRearBuffer[i] * balanceFactorRearLeft);
INT16 rightvalue = MixINT16(rightFrontBuffer[i]*balanceFactorFrontRight, rightRearBuffer[i]*balanceFactorRearRight);
if (flipStereo) // swap left and right channels
{
*p++ = rightvalue;
@ -308,15 +337,15 @@ static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* righ
}
} else if (nbHostAudioChannels == 4) {
for (unsigned i = 0; i < numSamples; i++) {
INT16 frontLeftValue = (INT16)(leftFrontBuffer[i]*balanceFactorFrontLeft);
INT16 frontRightValue = (INT16)(rightFrontBuffer[i]*balanceFactorFrontRight);
INT16 rearLeftValue = (INT16)(leftRearBuffer[i]*balanceFactorRearLeft);
INT16 rearRightValue = (INT16)(rightRearBuffer[i]*balanceFactorRearRight);
float frontLeftValue = leftFrontBuffer[i]*balanceFactorFrontLeft;
float frontRightValue = rightFrontBuffer[i]*balanceFactorFrontRight;
float rearLeftValue = leftRearBuffer[i]*balanceFactorRearLeft;
float rearRightValue = rightRearBuffer[i]*balanceFactorRearRight;
// Check game audio type
switch (AudioType) {
case Game::MONO: {
INT16 monovalue = MixINT16(MixINT16(frontLeftValue, frontRightValue), MixINT16(rearLeftValue, rearRightValue));
INT16 monovalue = MixINT16(MixFloat(frontLeftValue, frontRightValue), MixFloat(rearLeftValue, rearRightValue));
*p++ = monovalue;
*p++ = monovalue;
*p++ = monovalue;
@ -346,15 +375,15 @@ static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* righ
// Normal channels Front Left/Right then Rear Left/Right
if (flipStereo) // swap left and right channels
{
*p++ = frontRightValue;
*p++ = frontLeftValue;
*p++ = rearRightValue;
*p++ = rearLeftValue;
*p++ = ClampINT16(frontRightValue);
*p++ = ClampINT16(frontLeftValue);
*p++ = ClampINT16(rearRightValue);
*p++ = ClampINT16(rearLeftValue);
} else {
*p++ = frontLeftValue;
*p++ = frontRightValue;
*p++ = rearLeftValue;
*p++ = rearRightValue;
*p++ = ClampINT16(frontLeftValue);
*p++ = ClampINT16(frontRightValue);
*p++ = ClampINT16(rearLeftValue);
*p++ = ClampINT16(rearRightValue);
}
} break;
@ -363,15 +392,15 @@ static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* righ
// Reversed channels Front/Rear Left then Front/Rear Right
if (flipStereo) // swap left and right channels
{
*p++ = rearRightValue;
*p++ = rearLeftValue;
*p++ = frontRightValue;
*p++ = frontLeftValue;
*p++ = ClampINT16(rearRightValue);
*p++ = ClampINT16(rearLeftValue);
*p++ = ClampINT16(frontRightValue);
*p++ = ClampINT16(frontLeftValue);
} else {
*p++ = rearLeftValue;
*p++ = rearRightValue;
*p++ = frontLeftValue;
*p++ = frontRightValue;
*p++ = ClampINT16(rearLeftValue);
*p++ = ClampINT16(rearRightValue);
*p++ = ClampINT16(frontLeftValue);
*p++ = ClampINT16(frontRightValue);
}
break;
@ -440,19 +469,11 @@ bool OpenAudio(const Util::Config::Node& config)
break;
}
// Mixer Balance
float balancelr = (float)s_config->Get("BalanceLeftRight").ValueAs<float>();
if (balancelr < -100.0f)
balancelr = -100.0f;
else if (balancelr > 100.0f)
balancelr = 100.0f;
float balancelr = std::max(-100.f, std::min(100.f, s_config->Get("BalanceLeftRight").ValueAs<float>()));
balancelr *= 0.01f;
BalanceLeftRight = balancelr;
float balancefr = (float)s_config->Get("BalanceFrontRear").ValueAs<float>();
if (balancefr < -100.0f)
balancefr = -100.0f;
else if (balancefr > 100.0f)
balancefr = 100.0f;
float balancefr = std::max(-100.f, std::min(100.f, s_config->Get("BalanceFrontRear").ValueAs<float>()));
balancefr *= 0.01f;
BalanceFrontRear = balancefr;
@ -462,8 +483,7 @@ bool OpenAudio(const Util::Config::Node& config)
balanceFactorRearRight = (BalanceLeftRight > 0.f ? 1.f - BalanceLeftRight : 1.f) * (BalanceFrontRear > 0 ? 1.f - BalanceFrontRear : 1.f);
// Set up audio specification
SDL_AudioSpec desired;
memset(&desired, 0, sizeof(SDL_AudioSpec));
SDL_AudioSpec desired{};
desired.freq = SAMPLE_RATE_M3;
// Number of host channels to use (choice limited to 1,2,4)
desired.channels = nbHostAudioChannels;
@ -533,7 +553,7 @@ bool OpenAudio(const Util::Config::Node& config)
return OKAY;
}
bool OutputAudio(unsigned numSamples, INT16* leftFrontBuffer, INT16* rightFrontBuffer, INT16* leftRearBuffer, INT16* rightRearBuffer, bool flipStereo)
bool OutputAudio(unsigned numSamples, const float* leftFrontBuffer, const float* rightFrontBuffer, const float* leftRearBuffer, const float* rightRearBuffer, bool flipStereo)
{
//printf("OutputAudio(%u) [writePos = %u, writeWrapped = %s, playPos = %u, audioBufferSize = %u]\n",
// numSamples, writePos, (writeWrapped ? "true" : "false"), playPos, audioBufferSize);
@ -559,7 +579,7 @@ bool OutputAudio(unsigned numSamples, INT16* leftFrontBuffer, INT16* rightFrontB
// Get end of current play region (writing must occur past this point)
UINT32 playEndPos = playPos + bytes_per_frame_host;
// Undo any wrap-around of the write position that may have occured to create following ordering: playPos < playEndPos < writePos
// Undo any wrap-around of the write position that may have occurred to create following ordering: playPos < playEndPos < writePos
if (playEndPos > writePos && writeWrapped)
writePos += audioBufferSize;
@ -619,9 +639,9 @@ bool OutputAudio(unsigned numSamples, INT16* leftFrontBuffer, INT16* rightFrontB
bufferFull = true;
// Discard current chunk of data
goto Finish;
}
else
{
src = mixBuffer;
INT8* dst1;
INT8* dst2;
@ -641,9 +661,9 @@ bool OutputAudio(unsigned numSamples, INT16* leftFrontBuffer, INT16* rightFrontB
{
// Otherwise, just copy whole region
dst1 = audioBuffer + writePos;
dst2 = 0;
dst2 = NULL;
len1 = numBytes;
len2 = 0;
len2 = NULL;
}
// Copy chunk to write position in buffer
@ -672,8 +692,8 @@ bool OutputAudio(unsigned numSamples, INT16* leftFrontBuffer, INT16* rightFrontB
writePos -= audioBufferSize;
writeWrapped = true;
}
}
Finish:
// Unlock SDL audio callback
SDL_UnlockAudio();

View file

@ -117,7 +117,7 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *
float yRes = float(*yResPtr);
if (keepAspectRatio)
{
float model3Ratio = 496.0f/384.0f;
float model3Ratio = 496.0/384.0;
if (yRes < (xRes/model3Ratio))
xRes = yRes*model3Ratio;
if (xRes < (yRes*model3Ratio))
@ -153,7 +153,7 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *
*xResPtr = (unsigned) xRes;
*yResPtr = (unsigned) yRes;
UINT32 correction = (UINT32)(((yRes / 384.f) * 2) + 0.5f);
UINT32 correction = (UINT32)(((yRes / 384.f) * 2.f) + 0.5f);
glEnable(GL_SCISSOR_TEST);
@ -1384,7 +1384,7 @@ static void PrintGameList(const std::string &xml_file, const std::map<std::strin
{
const Game &game = v.second;
printf(" %s", game.name.c_str());
for (int i = game.name.length(); i < 9; i++) // pad for alignment (no game ID should be more than 9 letters)
for (size_t i = game.name.length(); i < 9; i++) // pad for alignment (no game ID should be more than 9 letters)
printf(" ");
if (!game.version.empty())
printf(" %s (%s)\n", game.title.c_str(), game.version.c_str());
@ -1425,9 +1425,9 @@ static Util::Config::Node DefaultConfig()
config.Set("FragmentShader2D", "");
// CSoundBoard
config.Set("EmulateSound", true);
config.Set("Balance", "0");
config.Set("BalanceLeftRight", "0");
config.Set("BalanceFrontRear", "0");
config.Set("Balance", "0.0");
config.Set("BalanceLeftRight", "0.0");
config.Set("BalanceFrontRear", "0.0");
config.Set("NbSoundChannels", "4");
config.Set("SoundFreq", "57.6"); // 60.0f? 57.524160f?
// CDSB

View file

@ -87,23 +87,19 @@ bool legacySound; // For LegacySound (SCSP DSP) config option.
// These globals control the operation of the SCSP, they are no longer extern and are set through SCSP_SetBuffers(). --Bart
float SoundClock; // Originally titled SysFPS; seems to be for the sound CPU.
const float Freq = 76;
signed short* bufferfl;
signed short* bufferfr;
signed short* bufferrl;
signed short* bufferrr;
int length;
int cnts;
static double SoundClock; // Originally titled SysFPS; seems to be for the sound CPU.
static const double Freq = 76;
static float* bufferfl;
static float* bufferfr;
static float* bufferrl;
static float* bufferrr;
static int length;
signed int* buffertmpfl, * buffertmpfr; // these are allocated inside this file
signed int* buffertmprl, * buffertmprr; // these are allocated inside this file
unsigned int srate=44100;
static const double srate=44100;
#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)
#define ICLIP18(x) (x<-131072)?-131072:((x>131071)?131071:x)
#define ICLIP16(x) (((x)<-32768)?-32768:(((x)>32767)?32767:(x)))
#define ICLIP18(x) (((x)<-131072)?-131072:(((x)>131071)?131071:(x)))
@ -740,7 +736,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
t=ARTimes[i]; //In ms
if(t!=0.0)
{
step=(1023*1000.0)/((float) srate*t);
step=(1023*1000.0)/(srate*t);
scale=(double) (1<<EG_SHIFT);
ARTABLE[i]=(int) (step*scale);
}
@ -748,7 +744,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
ARTABLE[i]=1024<<EG_SHIFT;
t=DRTimes[i]; //In ms
step=(1023*1000.0)/((float) srate*t);
step=(1023*1000.0)/(srate*t);
scale=(double) (1<<EG_SHIFT);
DRTABLE[i]=(int) (step*scale);
}
@ -762,34 +758,7 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
#endif
LFO_Init();
buffertmpfl = NULL;
buffertmpfr = NULL;
buffertmprl = NULL;
buffertmprr = NULL;
buffertmpfl=(signed int*) malloc(44100*sizeof(signed int));
if (NULL == buffertmpfl)
return ErrorLog("Insufficient memory for internal SCSP buffers.");
buffertmpfr=(signed int*) malloc(44100*sizeof(signed int));
if (NULL == buffertmpfr)
{
free(buffertmpfl);
return ErrorLog("Insufficient memory for internal SCSP buffers.");
}
buffertmprl=(signed int*)malloc(44100*sizeof(signed int));
if (NULL == buffertmprl)
return ErrorLog("Insufficient memory for internal SCSP buffers.");
buffertmprr=(signed int*)malloc(44100*sizeof(signed int));
if (NULL == buffertmprr)
{
free(buffertmprl);
return ErrorLog("Insufficient memory for internal SCSP buffers.");
}
memset(buffertmpfl, 0, 44100*sizeof(signed int));
memset(buffertmpfr, 0, 44100*sizeof(signed int));
memset(buffertmprl, 0, 44100*sizeof(signed int));
memset(buffertmprr, 0, 44100*sizeof(signed int));
SCSPs->data[0x20 / 2] = 0;
TimCnt[0] = 0xffff;
TimCnt[1] = 0xffff;
@ -799,10 +768,6 @@ bool SCSP_Init(const Util::Config::Node &config, int n)
MIDILock = CThread::CreateMutex();
if (NULL == MIDILock)
{
free(buffertmpfl);
free(buffertmpfr);
free(buffertmprl);
free(buffertmprr);
return ErrorLog("Unable to create MIDI mutex!");
}
@ -1547,7 +1512,7 @@ void SCSP_CpuRunScanline()
void SCSP_DoMasterSamples(int nsamples)
{
int slice = (int)(12000000 / (SoundClock*nsamples)); // 68K cycles/sample
int slice = (int)(12000000. / (SoundClock*nsamples)); // 68K cycles/sample
static int lastdiff = 0;
/*
@ -1556,33 +1521,25 @@ void SCSP_DoMasterSamples(int nsamples)
* When one SCSP is fully attenuated, the other's samples will be multiplied
* by 2.
*/
float balance = (float)s_config->Get("Balance").ValueAs<float>();
if (balance < -100.0f)
balance = -100.0f;
else if (balance > 100.0f)
balance = 100.0f;
balance /= 100.0f;
float balance = std::max(-100.f,std::min(100.f,s_config->Get("Balance").ValueAs<float>()));
balance *= 0.01f;
float masterBalance = 1.0f + balance;
float slaveBalance = 1.0f - balance;
signed short* buffl, * buffr;
signed short* bufrl, * bufrr;
INT32 sl, s, i;
buffl = bufferfl;
buffr = bufferfr;
bufrl = bufferrl;
bufrr = bufferrr;
float* buffl = bufferfl;
float* buffr = bufferfr;
float* bufrl = bufferrl;
float* bufrr = bufferrr;
/*
* Generate samples
*/
for (s = 0; s < nsamples; ++s)
for (INT32 s = 0; s < nsamples; ++s)
{
signed int smpfl = 0, smpfr = 0;
signed int smprl = 0, smprr = 0;
for (sl = 0; sl < 32; ++sl)
for (INT32 sl = 0; sl < 32; ++sl)
{
#if FM_DELAY
RBUFDST = SCSPs[0].DELAYBUF + SCSPs[0].DELAYPTR;
@ -1596,8 +1553,6 @@ void SCSP_DoMasterSamples(int nsamples)
signed int sample = (int)(masterBalance*(float)SCSP_UpdateSlot(slot));
Enc = ((TL(slot)) << 0x0) | ((IMXL(slot)) << 0xd);
SCSPDSP_SetSample(&SCSPs[0].DSP, (sample*LPANTABLE[Enc]) >> (SHIFT - 2), ISEL(slot), IMXL(slot));
Enc = ((TL(slot)) << 0x0) | ((DIPAN(slot)) << 0x8) | ((DISDL(slot)) << 0xd);
@ -1666,7 +1621,7 @@ void SCSP_DoMasterSamples(int nsamples)
// smpl=0;
// smpr=0;
for (i = 0; i < 16; ++i)
for (INT32 i = 0; i < 16; ++i)
{
_SLOT *slot = SCSPs[0].Slots + i;
if (legacySound == true) {
@ -1718,8 +1673,8 @@ void SCSP_DoMasterSamples(int nsamples)
smpfl = ICLIP16(smpfl >> 2);
smpfr = ICLIP16(smpfr >> 2);
}
*buffl++ = ICLIP16(smpfl);
*buffr++ = ICLIP16(smpfr);
*buffl++ = (float)smpfl;
*buffr++ = (float)smpfr;
if (HasSlaveSCSP)
{
@ -1734,8 +1689,8 @@ void SCSP_DoMasterSamples(int nsamples)
smprr = ICLIP16(smprr >> 2);
}
}
*bufrl++ = ICLIP16(smprl);
*bufrr++ = ICLIP16(smprr);
*bufrl++ = (float)smprl;
*bufrr++ = (float)smprr;
SCSP_TimersAddTicks(1);
CheckPendingIRQ();
@ -2146,16 +2101,15 @@ void SCSP_LoadState(CBlockFile *StateFile)
}
}
void SCSP_SetBuffers(INT16 *leftBufferPtr, INT16 *rightBufferPtr, INT16* leftRearBufferPtr, INT16* rightRearBufferPtr, int bufferLength)
void SCSP_SetBuffers(float *leftBufferPtr, float *rightBufferPtr, float* leftRearBufferPtr, float* rightRearBufferPtr, int bufferLength)
{
SoundClock = 76;
SoundClock = Freq;
bufferfl = leftBufferPtr;
bufferfr = rightBufferPtr;
bufferrl = leftRearBufferPtr;
bufferrr = rightRearBufferPtr;
length = bufferLength;
cnts = 0; // what is this for? seems unimportant but need to find out
}
void SCSP_Deinit(void)
@ -2163,14 +2117,6 @@ void SCSP_Deinit(void)
#ifdef USEDSP
free(SCSP->MIXBuf);
#endif
free(buffertmpfl);
free(buffertmpfr);
free(buffertmprl);
free(buffertmprr);
delete MIDILock;
buffertmpfl = NULL;
buffertmpfr = NULL;
buffertmprl = NULL;
buffertmprr = NULL;
MIDILock = NULL;
}

View file

@ -83,7 +83,7 @@ UINT32 SCSP_Slave_r32(UINT32 addr);
// Supermodel interface functions
void SCSP_SaveState(CBlockFile *StateFile);
void SCSP_LoadState(CBlockFile *StateFile);
void SCSP_SetBuffers(INT16 *leftBufferPtr, INT16 *rightBufferPtr, INT16* leftRearBufferPtr, INT16* rightRearBufferPtr, int bufferLength);
void SCSP_SetBuffers(float *leftBufferPtr, float *rightBufferPtr, float* leftRearBufferPtr, float* rightRearBufferPtr, int bufferLength);
void SCSP_Deinit(void);