X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=plugins%2Fdfsound%2Fspu.c;h=8f6ed1395ed27c5d7d88f044d9ee8aefd78d26d8;hp=24665698dacc476ac34959ff7a303ab505837791;hb=e391d21cdbf06afd68d137537b7e82585ecffa1a;hpb=665f33e1e8ce2e40a7939a33075c3bce1c90790c diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 24665698..8f6ed139 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -444,24 +444,30 @@ static int decode_block(int ch) { unsigned char *start; int predict_nr,shift_factor,flags; + int stop = 0; int ret = 0; - start=s_chan[ch].pCurr; // set up the current pos + start = s_chan[ch].pCurr; // set up the current pos + if(start == spuMemC) // ? + stop = 1; if(s_chan[ch].prevflags&1) // 1: stop/loop { if(!(s_chan[ch].prevflags&2)) - { - dwChannelOn&=~(1< turn everything off - s_chan[ch].bStop=1; - s_chan[ch].ADSRX.EnvelopeVol=0; - } + stop = 1; start = s_chan[ch].pLoop; } else ret = check_irq(ch, start); // hack, see check_irq below.. + if(stop) + { + dwChannelOn &= ~(1< turn everything off + s_chan[ch].bStop = 1; + s_chan[ch].ADSRX.EnvelopeVol = 0; + } + predict_nr=(int)start[0]; shift_factor=predict_nr&0xf; predict_nr >>= 4; @@ -665,12 +671,13 @@ static void noinline do_decode_bufs(int which, int start, int count) { const int *src = ChanBuf + start; unsigned short *dst = &spuMem[0x800/2 + which*0x400/2]; - int cursor = decode_pos; + int cursor = decode_pos + start; while (count-- > 0) { + cursor &= 0x1ff; dst[cursor] = *src++; - cursor = (cursor + 1) & 0x1ff; + cursor++; } // decode_pos is updated and irqs are checked later, after voice loop @@ -685,30 +692,21 @@ static void noinline do_decode_bufs(int which, int start, int count) static int do_samples(int forced_updates) { int volmult = iVolume; - int ns,ns_from,ns_to; + int ns,ns_from,ns_to,ns_len; int ch,d,silentch; int bIRQReturn=0; - while(1) - { - // ok, at the beginning we are looking if there is - // enuff free place in the dsound/oss buffer to - // fill in new data, or if there is a new channel to start. - // if not, we wait (thread) or return (timer/spuasync) - // until enuff free place is available/a new channel gets - // started - - if(!forced_updates && out_current->busy()) // still enuff data in sound buffer? - { - return 0; - } + // ok, at the beginning we are looking if there is + // enuff free place in the dsound/oss buffer to + // fill in new data, or if there is a new channel to start. + // if not, we return until enuff free place is available + // /a new channel gets started - cycles_since_update = 0; - if(forced_updates > 0) - forced_updates--; - - //--------------------------------------------------// continue from irq handling in timer mode? + if(!forced_updates && out_current->busy()) // still enuff data in sound buffer? + return 0; + while(!bIRQReturn) + { ns_from=0; ns_to=NSSIZE; ch=0; @@ -742,21 +740,22 @@ static int do_samples(int forced_updates) lastch=ch; lastns=ns_to=d; } + ns_len = ns_to - ns_from; MixADSR(ch, ns_from, ns_to); if(ch==1 || ch==3) { - do_decode_bufs(ch/2, ns_from, ns_to-ns_from); + do_decode_bufs(ch/2, ns_from, ns_len); decode_dirty_ch |= 1< 16/FRAG_MSECS) + if (iCycle++ >= 16/FRAG_MSECS) { - out_current->feed(pSpuBuffer, - ((unsigned char *)pS) - ((unsigned char *)pSpuBuffer)); + out_current->feed(pSpuBuffer, (unsigned char *)pS - pSpuBuffer); pS = (short *)pSpuBuffer; iCycle = 0; + + if(!forced_updates && out_current->busy()) + break; + } + + if(forced_updates > 0) + { + forced_updates--; + if(forced_updates == 0 && out_current->busy()) + break; } + + if(cycles_since_update <= -PSXCLK/60 / 4) + break; } + // this may cause desync, but help audio when the emu can't keep up.. + if(cycles_since_update < 0) + cycles_since_update = 0; + return 0; } @@ -890,7 +908,6 @@ static int do_samples(int forced_updates) void CALLBACK SPUasync(unsigned long cycle) { - static int old_ctrl; int forced_updates = 0; int do_update = 0; @@ -905,16 +922,8 @@ void CALLBACK SPUasync(unsigned long cycle) had_dma = 0; } - if((spuCtrl&CTRL_IRQ) && (((spuCtrl^old_ctrl)&CTRL_IRQ) // irq was enabled - || cycles_since_update > PSXCLK/60 / 4)) { + if(cycles_since_update > PSXCLK/60 * 5/4) do_update = 1; - forced_updates = cycles_since_update / (PSXCLK/44100) / NSSIZE; - } - // with no irqs, once per frame should be fine (using a bit more because of BIAS) - else if(cycles_since_update > PSXCLK/60 * 5/4) - do_update = 1; - - old_ctrl = spuCtrl; if(do_update) do_samples(forced_updates);