StartADSR(ch);
StartREVERB(ch);
- s_chan->prevflags=2;
- s_chan->iSBPos=27;
- s_chan->spos=0;
+ s_chan->prevflags = 2;
+ s_chan->iSBPos = 27;
+ s_chan->spos = 0;
+ s_chan->bStarting = 1;
s_chan->pCurr = spu.spuMemC + ((regAreaGetCh(ch, 6) & ~1) << 3);
int ret = 0;
start = s_chan->pCurr; // set up the current pos
- if (start == spu.spuMemC) // ?
+ if (start - spu.spuMemC < 0x1000) { // ?
+ //log_unhandled("ch%02d plays decode bufs @%05lx\n",
+ // ch, (long)(start - spu.spuMemC));
ret = 1;
+ }
if (s_chan->prevflags & 1) // 1: stop/loop
{
s_chan->pCurr = start; // store values for next cycle
s_chan->prevflags = flags;
+ s_chan->bStarting = 0;
return ret;
}
s_chan->pCurr = start;
s_chan->prevflags = flags;
+ s_chan->bStarting = 0;
return ret;
}
pos = s_chan->spos;
sinc = s_chan->sinc;
end = pos + *upd_samples * sinc;
+ if (s_chan->prevflags & 1) // 1: stop/loop
+ block = s_chan->pLoop;
pos += (28 - s_chan->iSBPos) << 16;
while (pos < end)
d = do_samples_default(decode_block, NULL, ch, ns_to,
SB, sinc, &s_chan->spos, &s_chan->iSBPos);
- d = MixADSR(&s_chan->ADSRX, d);
- if (d < ns_to) {
- spu.dwChannelsAudible &= ~(1 << ch);
- s_chan->ADSRX.State = ADSR_RELEASE;
- s_chan->ADSRX.EnvelopeVol = 0;
- memset(&ChanBuf[d], 0, (ns_to - d) * sizeof(ChanBuf[0]));
+ if (!s_chan->bStarting) {
+ d = MixADSR(&s_chan->ADSRX, d);
+ if (d < ns_to) {
+ spu.dwChannelsAudible &= ~(1 << ch);
+ s_chan->ADSRX.State = ADSR_RELEASE;
+ s_chan->ADSRX.EnvelopeVol = 0;
+ memset(&ChanBuf[d], 0, (ns_to - d) * sizeof(ChanBuf[0]));
+ }
}
if (ch == 1 || ch == 3)
mix_chan(spu.SSumLR, ns_to, s_chan->iLeftVolume, s_chan->iRightVolume);
}
+ MixXA(spu.SSumLR, RVB, ns_to, spu.decode_pos);
+
if (spu.rvb->StartAddr) {
if (do_rvb)
REVERBDo(spu.SSumLR, RVB, ns_to, spu.rvb->CurrAddr);
d = do_samples_skip(ch, ns_to);
work->ch[ch].ns_to = d;
- // note: d is not accurate on skip
- d = SkipADSR(&s_chan->ADSRX, d);
- if (d < ns_to) {
- spu.dwChannelsAudible &= ~(1 << ch);
- s_chan->ADSRX.State = ADSR_RELEASE;
- s_chan->ADSRX.EnvelopeVol = 0;
+ if (!s_chan->bStarting) {
+ // note: d is not accurate on skip
+ d = SkipADSR(&s_chan->ADSRX, d);
+ if (d < ns_to) {
+ spu.dwChannelsAudible &= ~(1 << ch);
+ s_chan->ADSRX.State = ADSR_RELEASE;
+ s_chan->ADSRX.EnvelopeVol = 0;
+ }
}
s_chan->bNewPitch = 0;
}
work = &worker->i[worker->i_reaped & WORK_I_MASK];
thread_work_wait_sync(work, force);
+ MixXA(work->SSumLR, RVB, work->ns_to, work->decode_pos);
do_samples_finish(work->SSumLR, work->ns_to,
work->channels_silent, work->decode_pos);
do_irq();
}
}
- check_irq_io(spu.spuAddr);
+ if (!spu.cycles_dma_end || (int)(spu.cycles_dma_end - cycles_to) < 0) {
+ spu.cycles_dma_end = 0;
+ check_irq_io(spu.spuAddr);
+ }
if (unlikely(spu.rvb->dirty))
REVERBPrep();
spu.cycles_played += ns_to * 768;
spu.decode_pos = (spu.decode_pos + ns_to) & 0x1ff;
+#if 0
+ static int ccount; static time_t ctime; ccount++;
+ if (time(NULL) != ctime)
+ { printf("%d\n", ccount); ccount = 0; ctime = time(NULL); }
+#endif
}
static void do_samples_finish(int *SSumLR, int ns_to,
spu.decode_dirty_ch &= ~(1<<3);
}
- MixXA(SSumLR, ns_to, decode_pos);
-
vol_l = vol_l * spu_config.iVolume >> 10;
vol_r = vol_r * spu_config.iVolume >> 10;
- if (!(spu.spuCtrl & 0x4000) || !(vol_l | vol_r))
+ if (!(spu.spuCtrl & CTRL_MUTE) || !(vol_l | vol_r))
{
// muted? (rare)
memset(spu.pS, 0, ns_to * 2 * sizeof(spu.pS[0]));
{
int i;
+ memset(&spu, 0, sizeof(spu));
spu.spuMemC = calloc(1, 512 * 1024);
InitADSR();
return 0;
}
-// SPUTEST: we don't test, we are always fine ;)
-long CALLBACK SPUtest(void)
-{
- return 0;
-}
-
-// SPUCONFIGURE: call config dialog
-long CALLBACK SPUconfigure(void)
-{
-#ifdef _MACOSX
- DoConfiguration();
-#else
-// StartCfgTool("CFG");
-#endif
- return 0;
-}
-
-// SPUABOUT: show about window
-void CALLBACK SPUabout(void)
-{
-#ifdef _MACOSX
- DoAbout();
-#else
-// StartCfgTool("ABOUT");
-#endif
-}
-
// SETUP CALLBACKS
// this functions will be called once,
// passes a callback that should be called on SPU-IRQ/cdda volume change