X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=plugins%2Fdfsound%2Fspu.c;h=4759f3fc2c8ed1592f6c141a8b9fa549d05d1885;hp=f5aab9f1f925bb6f6a8f45685d6f090a28003579;hb=f2aec10aa8e3befe7e89070e8559d070835cc23e;hpb=6d75977b13fede33db381324c610561c6e723a8b diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index f5aab9f1..4759f3fc 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -46,6 +46,8 @@ } while (0) #endif +#define PSXCLK 33868800 /* 33.8688 MHz */ + /* #if defined (USEMACOSX) static char * libraryName = N_("Mac OS X Sound"); @@ -79,9 +81,6 @@ unsigned char * pMixIrq=0; int iVolume=768; // 1024 is 1.0 int iXAPitch=1; -int iSPUIRQWait=1; -int iDebugMode=0; -int iRecordMode=0; int iUseReverb=2; int iUseInterpolation=2; @@ -92,7 +91,6 @@ REVERBInfo rvb; unsigned int dwNoiseVal; // global noise generator unsigned int dwNoiseCount; -int iSpuAsyncWait=0; unsigned short spuCtrl=0; // some vars to store psx reg infos unsigned short spuStat=0; @@ -122,9 +120,10 @@ int iFMod[NSSIZE]; int iCycle = 0; short * pS; +int had_dma; int lastch=-1; // last channel processed on spu irq in timer mode static int lastns=0; // last ns pos -static int iSecureStart=0; // secure start counter +static int cycles_since_update; #define CDDA_BUFFER_SIZE (16384 * sizeof(uint32_t)) // must be power of 2 @@ -533,7 +532,7 @@ static int do_samples_##name(int ch, int ns, int ns_to) \ { \ sbpos = 0; \ d = decode_block(ch); \ - if(d && iSPUIRQWait) \ + if(d) \ { \ ret = ns; \ goto out; \ @@ -666,7 +665,7 @@ static void mix_chan_rvb(int start, int count, int lv, int rv) // basically the whole sound processing is done in this fat func! //////////////////////////////////////////////////////////////////////// -static int do_samples(void) +static int do_samples(int forced_updates) { int volmult = iVolume; int ns,ns_from,ns_to; @@ -682,19 +681,15 @@ static int do_samples(void) // until enuff free place is available/a new channel gets // started - if(dwNewChannel) // new channel should start immedately? - { // (at least one bit 0 ... MAXCHANNEL is set?) - iSecureStart++; // -> set iSecure - if(iSecureStart>5) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) - } - else iSecureStart=0; // 0: no new channel should start - - if(!iSecureStart && // no new start? - (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? + if(!forced_updates && SoundGetBytesBuffered()) // still enuff data in sound buffer? { return 0; } + cycles_since_update = 0; + if(forced_updates > 0) + forced_updates--; + //--------------------------------------------------// continue from irq handling in timer mode? ns_from=0; @@ -746,7 +741,7 @@ static int do_samples(void) // advance "stopped" channels that can cause irqs // (all chans are always playing on the real thing..) - if(!bIRQReturn && (spuCtrl&CTRL_IRQ)) + if(spuCtrl&CTRL_IRQ) for(ch=0;ch pSpuIrq && s_chan[ch].pLoop > pSpuIrq) continue; - s_chan[ch].spos += s_chan[ch].sinc * NSSIZE; + s_chan[ch].spos += s_chan[ch].sinc * (ns_to - ns_from); while(s_chan[ch].spos >= 28 * 0x10000) { unsigned char *start = s_chan[ch].pCurr; // no need for bIRQReturn since the channel is silent - iSpuAsyncWait |= skip_block(ch); + skip_block(ch); if(start == s_chan[ch].pCurr) { // looping on self @@ -773,12 +768,8 @@ static int do_samples(void) } } - if(bIRQReturn && iSPUIRQWait) // special return for "spu irq - wait for cpu action" - { - iSpuAsyncWait=1; - bIRQReturn=0; + if(bIRQReturn) // special return for "spu irq - wait for cpu action" return 0; - } //---------------------------------------------------// @@ -872,21 +863,26 @@ static int do_samples(void) void CALLBACK SPUasync(unsigned long cycle) { - if(iSpuAsyncWait) - { - iSpuAsyncWait++; - if(iSpuAsyncWait<=16/FRAG_MSECS) return; - iSpuAsyncWait=0; - } + int forced_updates = 0; + int do_update = 0; if(!bSpuInit) return; // -> no init, no call - do_samples(); + cycles_since_update += cycle; + + if(dwNewChannel || had_dma) + { + forced_updates = 1; + do_update = 1; + had_dma = 0; + } + + // once per frame should be fine (using a bit more because of BIAS) + if(cycles_since_update > PSXCLK/60 * 5/4) + do_update = 1; - // abuse iSpuAsyncWait mechanism to reduce calls to above function - // to make it do larger chunks - // note: doing it less often than once per frame causes skips - iSpuAsyncWait=1; + if(do_update) + do_samples(forced_updates); } // SPU UPDATE... new epsxe func @@ -1002,7 +998,6 @@ long CALLBACK SPUinit(void) pMixIrq = 0; memset((void *)s_chan, 0, (MAXCHAN + 1) * sizeof(SPUCHAN)); pSpuIrq = 0; - //iSPUIRQWait = 0; lastch = -1; SetupStreams(); // prepare streaming