- // advance "stopped" channels that can cause irqs
- // (all chans are always playing on the real thing..)
- if(!bIRQReturn && (spuCtrl&CTRL_IRQ))
- for(ch=0;ch<MAXCHAN;ch++)
- {
- if(!(silentch&(1<<ch))) continue; // already handled
- if(dwChannelDead&(1<<ch)) continue;
- if(s_chan[ch].pCurr > pSpuIrq && s_chan[ch].pLoop > pSpuIrq)
- continue;
-
- s_chan[ch].spos += s_chan[ch].sinc * NSSIZE;
- 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);
- if(start == s_chan[ch].pCurr)
- {
- // looping on self
- dwChannelDead |= 1<<ch;
- s_chan[ch].spos = 0;
- break;
- }
-
- s_chan[ch].spos -= 28 * 0x10000;
- }
- }
+ if (s_chan[ch].bFMod == 2) // fmod freq channel
+ memcpy(iFMod, &ChanBuf, ns_to * sizeof(iFMod[0]));
+ if (s_chan[ch].bRVBActive)
+ mix_chan_rvb(0, ns_to, s_chan[ch].iLeftVolume, s_chan[ch].iRightVolume, spu.sRVBStart);
+ else
+ mix_chan(0, ns_to, s_chan[ch].iLeftVolume, s_chan[ch].iRightVolume);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// MAIN SPU FUNCTION
+// here is the main job handler...
+////////////////////////////////////////////////////////////////////////
+
+void do_samples_finish(int ns_to, int silentch);
+
+void do_samples(unsigned int cycles_to)
+{
+ unsigned int mask;
+ int ch, ns_to;
+ int silentch;
+ int cycle_diff;
+
+ cycle_diff = cycles_to - spu.cycles_played;
+ if (cycle_diff < -2*1048576 || cycle_diff > 2*1048576)
+ {
+ //xprintf("desync %u %d\n", cycles_to, cycle_diff);
+ spu.cycles_played = cycles_to;
+ return;
+ }
+
+ if (cycle_diff < 2 * 768)
+ return;
+
+ ns_to = (cycle_diff / 768 + 1) & ~1;
+ if (ns_to > NSSIZE) {
+ // should never happen
+ //xprintf("ns_to oflow %d %d\n", ns_to, NSSIZE);
+ ns_to = NSSIZE;
+ }