diff --git a/Config/Games.xml b/Config/Games.xml index 180ae98..062bc20 100644 --- a/Config/Games.xml +++ b/Config/Games.xml @@ -1123,6 +1123,7 @@ Sega Model 3 1.5 + @@ -1197,6 +1198,7 @@ Sega Model 3 1.5 + diff --git a/Src/Model3/DSB.cpp b/Src/Model3/DSB.cpp index 30a42ad..ff64da0 100644 --- a/Src/Model3/DSB.cpp +++ b/Src/Model3/DSB.cpp @@ -147,9 +147,7 @@ int CDSBResampler::UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *i // Obtain program volume settings and convert to 24.8 fixed point (0-200 -> 0x00-0x200) musicVol = m_config["MusicVolume"].ValueAs(); - soundVol = m_config["SoundVolume"].ValueAs(); musicVol = (INT32) ((float) 0x100 * (float) musicVol / 100.0f); - soundVol = (INT32) ((float) 0x100 * (float) soundVol / 100.0f); // Scale volume from 0x00-0xFF -> 0x00-0x100 (24.8 fixed point) v[0] = (INT16) ((float) 0x100 * (float) volumeL / 255.0f); @@ -167,8 +165,8 @@ int CDSBResampler::UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *i rightSample = (rightSample*v[0]*musicVol) >> 16; // Apply sound volume setting - leftSoundSample = (outL[outIdx]*soundVol) >> 8; - rightSoundSample = (outR[outIdx]*soundVol) >> 8; + leftSoundSample = outL[outIdx]; + rightSoundSample = outR[outIdx]; // Mix and output outL[outIdx] = MixAndClip(leftSoundSample, leftSample); @@ -185,7 +183,6 @@ int CDSBResampler::UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *i pFrac += (1<<8); nFrac -= (1<<8); inIdx++; // advance samples (for upsampling only; downsampling may advance by more than one -- add delta every loop iteration) - } } @@ -435,7 +432,7 @@ void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR) // 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, 0, 0, 44100/60, 32000/60+2, 44100, 32000); + retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, 0, 0, NUM_SAMPLES_PER_FRAME, 32000/60+2, 44100, 32000); return; } @@ -457,7 +454,7 @@ void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR) // Decode MPEG for this frame MpegDec::DecodeAudio(&mpegL[retainedSamples], &mpegR[retainedSamples], 32000 / 60 - retainedSamples + 2); - retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, v, v, 44100/60, 32000/60+2, 44100, 32000); + retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, v, v, NUM_SAMPLES_PER_FRAME, 32000/60+2, 44100, 32000); } void CDSB1::Reset(void) @@ -1001,7 +998,7 @@ void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR) // 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], 44100 / 60, 32000 / 60 + 2, 44100, 32000); + retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, volume[0], volume[1], NUM_SAMPLES_PER_FRAME, 32000 / 60 + 2, 44100, 32000); return; } @@ -1072,7 +1069,7 @@ void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR) break; } - retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, leftChannelSource, rightChannelSource, volL, volR, 44100 / 60, 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) diff --git a/Src/Model3/DSB.h b/Src/Model3/DSB.h index f39789b..2c71111 100644 --- a/Src/Model3/DSB.h +++ b/Src/Model3/DSB.h @@ -41,6 +41,8 @@ #define FIFO_STACK_SIZE 0x100 #define FIFO_STACK_SIZE_MASK (FIFO_STACK_SIZE - 1) +#define NUM_SAMPLES_PER_FRAME (44100/60) + /****************************************************************************** Resampling diff --git a/Src/Model3/SoundBoard.cpp b/Src/Model3/SoundBoard.cpp index 2ae6cff..d02eb3c 100644 --- a/Src/Model3/SoundBoard.cpp +++ b/Src/Model3/SoundBoard.cpp @@ -67,6 +67,18 @@ static FILE *soundFP; #endif +// 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 MEMORY_POOL_SIZE (0x100000 + 0x100000 + 4*LENGTH_CHANNEL_BUFFER) + + /****************************************************************************** 68K Address Space Handlers ******************************************************************************/ @@ -350,13 +362,25 @@ bool CSoundBoard::RunFrame(void) } else { - memset(audioFL, 0, 44100/60*sizeof(INT16)); - memset(audioFR, 0, 44100/60*sizeof(INT16)); - memset(audioRL, 0, 44100/60*sizeof(INT16)); - memset(audioRR, 0, 44100/60*sizeof(INT16)); + memset(audioFL, 0, LENGTH_CHANNEL_BUFFER); + memset(audioFR, 0, LENGTH_CHANNEL_BUFFER); + memset(audioRL, 0, LENGTH_CHANNEL_BUFFER); + memset(audioRR, 0, LENGTH_CHANNEL_BUFFER); } - - // Run DSB and mix with existing audio + + // Compute sound volume as + INT32 soundVol = m_config["SoundVolume"].ValueAs(); + soundVol = (INT32)((float)0x100 * (float)soundVol / 100.0f); + + // 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; + } + + // Run DSB and mix with existing audio, apply music volume if (NULL != DSB) { // Will need to mix with proper front, rear channels or both (game specific) bool mixDSBWithFront = true; // Everything to front channels for now @@ -368,12 +392,12 @@ bool CSoundBoard::RunFrame(void) } // Output the audio buffers - bool bufferFull = OutputAudio(44100/60, audioFL, audioFR, audioRL, audioRR, m_config["FlipStereo"].ValueAs()); + bool bufferFull = OutputAudio(NUM_SAMPLES_PER_FRAME, audioFL, audioFR, audioRL, audioRR, m_config["FlipStereo"].ValueAs()); #ifdef SUPERMODEL_LOG_AUDIO // Output to binary file INT16 s; - for (int i = 0; i < 44100/60; i++) + for (int i = 0; i < NUM_SAMPLES_PER_FRAME; i++) { s = audioL[i]; fwrite(&s, sizeof(INT16), 1, soundFP); // left channel @@ -452,16 +476,6 @@ void CSoundBoard::AttachDSB(CDSB *DSBPtr) DebugLog("Sound Board connected to DSB\n"); } -// 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 0x5BE -#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 MEMORY_POOL_SIZE (0x100000 + 0x100000 + 4*LENGTH_CHANNEL_BUFFER) bool CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr) { @@ -495,7 +509,7 @@ bool CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr) M68KGetContext(&M68K); // Initialize SCSPs - SCSP_SetBuffers(audioFL, audioFR, audioRL, audioRR, 44100/60); + SCSP_SetBuffers(audioFL, audioFR, audioRL, audioRR, NUM_SAMPLES_PER_FRAME); SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback); if (OKAY != SCSP_Init(m_config, 2)) return FAIL; diff --git a/Src/OSD/SDL/Audio.cpp b/Src/OSD/SDL/Audio.cpp index b8b71cc..073dc2e 100755 --- a/Src/OSD/SDL/Audio.cpp +++ b/Src/OSD/SDL/Audio.cpp @@ -154,6 +154,18 @@ static INT16 AddAndClampINT16(INT32 x, INT32 y) return (INT16)sum; } +static INT16 MixINT16(INT32 x, INT32 y) +{ + INT32 sum = (x + y)>>1; + if (sum > INT16_MAX) { + sum = INT16_MAX; + } + if (sum < INT16_MIN) { + sum = INT16_MIN; + } + return (INT16)sum; +} + static void PlayCallback(void* data, Uint8* stream, int len) { //printf("PlayCallback(%d) [writePos = %u, writeWrapped = %s, playPos = %u, audioBufferSize = %u]\n", @@ -265,9 +277,9 @@ static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* righ if (nbHostAudioChannels == 1) { for (unsigned i = 0; i < numSamples; i++) { - INT16 monovalue = AddAndClampINT16( - (INT32)(leftFrontBuffer[i] * balanceFactorFrontLeft) + (INT32)(rightFrontBuffer[i] * balanceFactorFrontRight), - (INT32)(leftRearBuffer[i] * balanceFactorRearLeft) + (INT32)(rightRearBuffer[i] * balanceFactorRearRight)); + INT16 monovalue = MixINT16( + MixINT16((INT32)(leftFrontBuffer[i] * balanceFactorFrontLeft), (INT32)(rightFrontBuffer[i] * balanceFactorFrontRight)), + MixINT16((INT32)(leftRearBuffer[i] * balanceFactorRearLeft), (INT32)(rightRearBuffer[i] * balanceFactorRearRight))); *p++ = monovalue; } } else { @@ -283,8 +295,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 = AddAndClampINT16((INT32)(leftFrontBuffer[i] * balanceFactorFrontLeft), (INT32)(leftRearBuffer[i] * balanceFactorRearLeft)); - INT16 rightvalue = AddAndClampINT16((INT32)(rightFrontBuffer[i]*balanceFactorFrontRight), (INT32)(rightRearBuffer[i]*balanceFactorRearRight)); + INT16 leftvalue = MixINT16((INT32)(leftFrontBuffer[i] * balanceFactorFrontLeft), (INT32)(leftRearBuffer[i] * balanceFactorRearLeft)); + INT16 rightvalue = MixINT16((INT32)(rightFrontBuffer[i]*balanceFactorFrontRight), (INT32)(rightRearBuffer[i]*balanceFactorRearRight)); if (flipStereo) // swap left and right channels { *p++ = rightvalue; @@ -304,7 +316,7 @@ static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* righ // Check game audio type switch (AudioType) { case Game::MONO: { - INT16 monovalue = AddAndClampINT16(AddAndClampINT16(frontLeftValue, frontRightValue), AddAndClampINT16(rearLeftValue, rearRightValue)); + INT16 monovalue = MixINT16(MixINT16(frontLeftValue, frontRightValue), MixINT16(rearLeftValue, rearRightValue)); *p++ = monovalue; *p++ = monovalue; *p++ = monovalue; @@ -313,8 +325,8 @@ static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* righ case Game::STEREO_LR: case Game::STEREO_RL: { - INT16 leftvalue = AddAndClampINT16(frontLeftValue, frontRightValue); - INT16 rightvalue = AddAndClampINT16(rearLeftValue, rearRightValue); + INT16 leftvalue = MixINT16(frontLeftValue, frontRightValue); + INT16 rightvalue = MixINT16(rearLeftValue, rearRightValue); if (flipStereo) // swap left and right channels { *p++ = rightvalue; @@ -366,10 +378,10 @@ static void MixChannels(unsigned numSamples, INT16* leftFrontBuffer, INT16* righ case Game::QUAD_1_LR_2_FR_MIX: // Split mix: one goes to left/right, other front/rear (mono) // =>Remix all! - INT16 newfrontLeftValue = AddAndClampINT16(frontLeftValue, rearLeftValue); - INT16 newfrontRightValue = AddAndClampINT16(frontLeftValue, rearRightValue); - INT16 newrearLeftValue = AddAndClampINT16(frontRightValue, rearLeftValue); - INT16 newrearRightValue = AddAndClampINT16(frontRightValue, rearRightValue); + INT16 newfrontLeftValue = MixINT16(frontLeftValue, rearLeftValue); + INT16 newfrontRightValue = MixINT16(frontLeftValue, rearRightValue); + INT16 newrearLeftValue = MixINT16(frontRightValue, rearLeftValue); + INT16 newrearRightValue = MixINT16(frontRightValue, rearRightValue); if (flipStereo) // swap left and right channels { diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index 67d6fbc..b66fc01 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -859,11 +859,13 @@ static void SuperSleepUntil(uint64_t target) } // Spin until requested time - uint64_t now; + volatile uint64_t now; + int32_t remain; do { now = SDL_GetPerformanceCounter(); - } while (now < target); + remain = int32_t((target - now)); + } while (remain>0); } @@ -1251,8 +1253,8 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In // Refresh rate (frame limiting) if (paused || s_runtime_config["Throttle"].ValueAs()) { - SuperSleepUntil(nextTime); - nextTime = SDL_GetPerformanceCounter() + perfCountPerFrame; + SuperSleepUntil(nextTime); + nextTime = SDL_GetPerformanceCounter() + perfCountPerFrame; } // Measure frame rate @@ -1729,8 +1731,7 @@ static ParsedCommandLine ParseCommandLine(int argc, char **argv) { std::vector parts = Util::Format(arg).Split('='); if (parts.size() != 2) - { - ErrorLog("'-res' requires both a width and height (e.g., '-res=496,384')."); + {ErrorLog("'-res' requires both a width and height (e.g., '-res=496,384')."); cmd_line.error = true; } else diff --git a/Src/Sound/SCSP.cpp b/Src/Sound/SCSP.cpp index a463861..eb0ee29 100644 --- a/Src/Sound/SCSP.cpp +++ b/Src/Sound/SCSP.cpp @@ -639,15 +639,15 @@ bool SCSP_Init(const Util::Config::Node &config, int n) for(int i=0;i<0x400;++i) { - float fcent=(double) 1200.0*log2((double)(((double) 1024.0+(double)i)/(double)1024.0)); + double fcent=(double) 1200.0*log2((double)(((double) 1024.0+(double)i)/(double)1024.0)); //float fcent=1.0+(float) i/1024.0; fcent=(double) 44100.0*pow(2.0,fcent/1200.0); - FNS_Table[i]=(float) (1<>(10-SHIFT))|(1<phase_step = (unsigned int)((float)(1 << LFO_SHIFT)*step); if (ALFO) {