diff --git a/plugins/spu2ghz/SoundTouch/FIRFilter.cpp b/plugins/spu2ghz/SoundTouch/FIRFilter.cpp index 5c3c3a58fa..10a0bb0299 100644 --- a/plugins/spu2ghz/SoundTouch/FIRFilter.cpp +++ b/plugins/spu2ghz/SoundTouch/FIRFilter.cpp @@ -180,7 +180,7 @@ void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint u #ifdef INTEGER_SAMPLES resultDivider = (SAMPLETYPE)(1< 0 ) + buff1end = 0xfffff; + { - u32 nexta = Cores[core].TDA >> 3; - u32 flagbitmask = 1ul << ( nexta & 31 ); + u32 nexta = Cores[core].TDA >> 3; // next address in 8 word blocks + const u32 leftsidebit = nexta & 31; + u32 rightsidebit; // assigned later nexta >>= 5; - // Traverse from start to finish in 8 word blocks, - // and clear the pcm cache flag for each block. - u32 stmp = ( size + 7 ) >> 3; // round up - for( i=0; i>= (3+5); // 8 words per block, 32 blocks per int. + memset( &pcm_cache_flags[nexta], 0, sizeof( u32 ) * (buff1end-nexta) ); + + if( buff2end > 0 ) + { + // second branch needs cleared: + // It starts at the beginning of memory and moves forward to buff2end + + const u32 endpt2 = buff2end >> (3+5); // 8 words per block, 32 blocks per int. + memset( pcm_cache_flags, 0, sizeof( u32 ) * endpt2 ); + + for(Cores[core].TDA=0; Cores[core].TDA<(u32)buff2end; ++Cores[core].TDA, ++pMem) + *GetMemPtr( Cores[core].TDA ) = *pMem; + + rightsidebit = ( buff2end >> 3 ); + nexta = endpt2; + } + else + { + rightsidebit = (Cores[core].TDA >> 3); + nexta = buff1end; + } + + // clear the right-side remainder: + pcm_cache_flags[nexta] &= ~((1ul << (32-(rightsidebit&31)))-1); } i=Cores[core].TSA; diff --git a/plugins/spu2ghz/sndout.cpp b/plugins/spu2ghz/sndout.cpp index 334456e045..ea89d65115 100644 --- a/plugins/spu2ghz/sndout.cpp +++ b/plugins/spu2ghz/sndout.cpp @@ -19,6 +19,8 @@ #include "SoundTouch/SoundTouch.h" #include "SoundTouch/WavFile.h" +#include + static int ts_stats_stretchblocks = 0; static int ts_stats_normalblocks = 0; static int ts_stats_logcounter = 0; @@ -432,11 +434,6 @@ s32* sndTempBuffer=NULL; s32 sndTempProgress=NULL; s16* sndTempBuffer16=NULL; -void ResetTempoChange() -{ - pSoundTouch->setTempo(1); -} - void UpdateTempoChange() { if( --freezeTempo > 0 ) @@ -581,49 +578,71 @@ void UpdateTempoChange() } -void soundtouchInit() { +void soundtouchInit() +{ pSoundTouch = new soundtouch::SoundTouch(); pSoundTouch->setSampleRate(SampleRate); pSoundTouch->setChannels(2); pSoundTouch->setSetting(SETTING_USE_QUICKSEEK, 0); pSoundTouch->setSetting(SETTING_USE_AA_FILTER, 0); -} + pSoundTouch->setTempo(1); -s32 SndInit() -{ - if( mods[OutputModule] == NULL ) - { - // force us to the NullOut module if nothing assigned. - OutputModule = FindOutputModuleById( NullOut.GetIdent() ); - } - - // initialize sound buffer - // Buffer actually attempts to run ~50%, so allocate near double what - // the requested latency is: - - sndBuffer = new SndBufferImpl( SndOutLatencyMS * (timeStretchEnabled ? 2.0 : 1.5) ); - sndTempProgress = 0; - sndTempBuffer = new s32[SndOutPacketSize]; - sndTempBuffer16 = new s16[SndOutPacketSize]; - - // clear buffers! - // Fixes loopy sounds on emu resets. - memset( sndTempBuffer, 0, sizeof(s32) * SndOutPacketSize ); - memset( sndTempBuffer16, 0, sizeof(s16) * SndOutPacketSize ); + // some timestretch management vars: cTempo = 1.0; eTempo = 1.0; - lastPct = 0; lastEmergencyAdj = 0; // just freeze tempo changes for a while at startup. // the driver buffers are bogus anyway. freezeTempo = 8; - soundtouchInit(); +} - ResetTempoChange(); +static void _sndInitFail() +{ + // If a failure occurs, just initialize the NoSound driver. This'll allow + // the game to emulate properly (hopefully), albeit without sound. + OutputModule = FindOutputModuleById( NullOut.GetIdent() ); + mods[OutputModule]->Init( sndBuffer ); +} + +s32 SndInit() +{ + if( mods[OutputModule] == NULL ) + { + _sndInitFail(); + return 0; + } + + // initialize sound buffer + // Buffer actually attempts to run ~50%, so allocate near double what + // the requested latency is: + + try + { + sndBuffer = new SndBufferImpl( SndOutLatencyMS * (timeStretchEnabled ? 2.0 : 1.5) ); + sndTempBuffer = new s32[SndOutPacketSize]; + sndTempBuffer16 = new s16[SndOutPacketSize]; + } + catch( std::bad_alloc& ) + { + // out of memory exception (most likely) + + SysMessage( "Out of memory error occured while initializing SPU2." ); + _sndInitFail(); + return 0; + } + + // clear buffers! + // Fixes loopy sounds on emu resets. + memset( sndTempBuffer, 0, sizeof(s32) * SndOutPacketSize ); + memset( sndTempBuffer16, 0, sizeof(s16) * SndOutPacketSize ); + + sndTempProgress = 0; + + soundtouchInit(); // initializes the timestretching if(LimitMode!=0) { @@ -636,9 +655,9 @@ s32 SndInit() // initialize module if( mods[OutputModule]->Init(sndBuffer) == -1 ) { - OutputModule = FindOutputModuleById( NullOut.GetIdent() ); - return mods[OutputModule]->Init( sndBuffer ); + _sndInitFail(); } + return 0; } @@ -685,8 +704,6 @@ s32 SndWrite(s32 ValL, s32 ValR) if(mods[OutputModule] == &NullOut) // null output doesn't need buffering or stretching! :p return 0; - //inputSamples+=2; - sndTempBuffer[sndTempProgress++] = ValL; sndTempBuffer[sndTempProgress++] = ValR; diff --git a/plugins/spu2ghz/spu2.cpp b/plugins/spu2ghz/spu2.cpp index c43b9342fa..56a509748e 100644 --- a/plugins/spu2ghz/spu2.cpp +++ b/plugins/spu2ghz/spu2.cpp @@ -413,7 +413,7 @@ s32 CALLBACK SPU2open(void *pDsp) }*/ spu2open=1; - if (!SndInit()) + if (!SndInit()) { srate_pv=(double)SampleRate/48000.0; diff --git a/plugins/spu2ghz/xaudio2out.cpp b/plugins/spu2ghz/xaudio2out.cpp index d16216f1a8..730bf218a3 100644 --- a/plugins/spu2ghz/xaudio2out.cpp +++ b/plugins/spu2ghz/xaudio2out.cpp @@ -24,9 +24,6 @@ #include #include -// turn off warning C4355: 'this' : used in base member initializer list -#pragma warning( disable: 4355 ) - class XAudio2Mod: public SndOutModule { private: @@ -133,7 +130,7 @@ public: // Create an XAudio2 voice to stream this wave // if( FAILED(hr = pXAudio2->CreateSourceVoice( &pSourceVoice, &wfx, - XAUDIO2_VOICE_NOSRC, 1.0f, &voiceContext ) ) ) + XAUDIO2_VOICE_NOPITCH, 1.0f, &voiceContext ) ) ) { SysMessage( "Error %#X creating source voice\n", hr ); SAFE_RELEASE( pXAudio2 ); @@ -183,7 +180,7 @@ public: pSourceVoice = NULL; } - Sleep(50); + Sleep(50); // give the engine some time to stop voices // // Cleanup XAudio2