#define PERIOD_MIN 1
#define PERIOD_MIN_NONCE 60
#define PERIOD_MIN_LOOP 16
+#define PERIOD_MIN_LOOP_COUNT 64
#define PERIOD_LOW 124
int dmaofftime_active;
int dmaofftime_cpu_cnt;
uaecptr dmaofftime_pc;
+ int minperloop;
int volcntbufcnt;
float volcntbuf[VOLCNT_BUFFER_SIZE];
};
static int audio_work_to_do;
-static void zerostate (int nr)
+static void zerostate(int nr, bool reset)
{
struct audio_channel_data *cdp = audio_channel + nr;
#if DEBUG_AUDIO > 0
cdp->state = 0;
cdp->irqcheck = 0;
cdp->evtime = MAX_EV;
- cdp->intreq2 = false;
+ if (!currprefs.cpu_memory_cycle_exact || reset) {
+ cdp->intreq2 = false;
+ }
cdp->dmaenstore = false;
cdp->dmaofftime_active = 0;
cdp->volcnt = 0;
cdp->volcntbufcnt = 0;
+ cdp->minperloop = 0;
memset(cdp->volcntbuf, 0, sizeof(cdp->volcntbuf));
#if TEST_AUDIO > 0
cdp->have_dat = false;
last_cycles = get_cycles ();
next_sample_evtime = scaled_sample_evtime;
- for (i = 0; i < AUDIO_CHANNELS_PAULA; i++)
- zerostate (i);
- for (i = 0; i < audio_total_extra_streams; i++)
+ for (i = 0; i < AUDIO_CHANNELS_PAULA; i++) {
+ zerostate(i, true);
+ }
+ for (i = 0; i < audio_total_extra_streams; i++) {
audio_stream[i].evtime = MAX_EV;
+ }
schedule_audio ();
events_schedule ();
samplecnt = 0;
cdp->dmaenstore = chan_ena;
if (currprefs.produce_sound == 0) {
- zerostate (nr);
+ zerostate (nr, true);
return true;
}
audio_activate ();
write_log(_T("%d: INSTADMAOFF\n"), nr, M68K_GETPC);
#endif
newsample(nr, (cdp->dat2 >> 0) & 0xff);
- zerostate(nr);
+ zerostate(nr, true);
} else {
if (warned >= 0) {
warned--;
static int warned = 100;
// make sure audio.device AUDxDAT startup returns to idle state before DMA is enabled
newsample(nr, (cdp->dat2 >> 0) & 0xff);
- zerostate(nr);
+ zerostate(nr, true);
if (warned > 0) {
write_log(_T("AUD%d: forced idle state PER=%d PC=%08x\n"), nr, cdp->per, M68K_GETPC);
warned--;
audio_state_channel2(nr, false);
}
} else {
- zerostate(nr);
+ zerostate(nr, false);
}
break;
case 1:
cdp->evtime = MAX_EV;
if (!chan_ena) {
- zerostate(nr);
+ zerostate(nr, false);
return true;
}
if (!cdp->dat_written)
case 5:
cdp->evtime = MAX_EV;
if (!chan_ena) {
- zerostate(nr);
+ zerostate(nr, false);
return true;
}
if (!cdp->dat_written)
cdp->state = 2;
loadper(nr);
cdp->pbufldl = true;
- cdp->intreq2 = false;
+ if (!currprefs.cpu_memory_cycle_exact) {
+ cdp->intreq2 = false;
+ }
cdp->volcnt = 0;
audio_state_channel2(nr, false);
break;
if (audap)
loaddat(nr, true);
if (chan_ena) {
- if (audap)
+ if (audap) {
setdr(nr, false);
- if (cdp->intreq2 && audap)
+ }
+ if (cdp->intreq2 && audap) {
setirq(nr, 21);
+ cdp->intreq2 = false;
+ }
} else {
- if (audap)
+ if (audap) {
setirq(nr, 22);
+ }
}
cdp->pbufldl = true;
cdp->irqcheck = 0;
if (chan_ena) {
loaddat (nr);
- if (napnav)
+ if (napnav) {
setdr(nr, false);
- if (cdp->intreq2 && napnav)
+ }
+ if (cdp->intreq2 && napnav) {
setirq(nr, 31);
+ cdp->intreq2 = false;
+ }
} else {
- if (napnav)
+ if (napnav) {
setirq(nr, 32);
+ }
// cycle-accurate period check was not needed, do delayed check
if (!cdp->irqcheck) {
cdp->irqcheck = isirq(nr);
if (debugchannel (nr))
write_log(_T("%d: IDLE\n"), nr);
#endif
- zerostate(nr);
+ zerostate(nr, false);
return true;
}
loaddat(nr);
}
- cdp->intreq2 = false;
cdp->pbufldl = true;
cdp->state = 2;
audio_state_channel2(nr, false);
cdp->wlen = cdp->len;
// if very low period sample repeats, set higher period value to not cause huge performance drop
if (cdp->per < PERIOD_MIN_LOOP * CYCLE_UNIT) {
- cdp->per = PERIOD_MIN_LOOP * CYCLE_UNIT;
+ cdp->minperloop++;
+ if (cdp->minperloop >= PERIOD_MIN_LOOP_COUNT) {
+ cdp->per = PERIOD_MIN_LOOP * CYCLE_UNIT;
+ }
+ }
+ if (!(v & 0x80000000)) {
+ cdp->intreq2 = true;
}
- cdp->intreq2 = true;
if (sampleripper_enabled)
do_samplerip(cdp);
#if DEBUG_AUDIO > 0
int cyc = 0;
if (chan_ena) {
// AUDxLEN is processed after 1 CCK delay
- cyc = 1 * CYCLE_UNIT;
+ if ((cdp->state & 15) == 2 || (cdp->state & 15) == 3) {
+ cyc = 1 * CYCLE_UNIT;
+ // But INTREQ2 is set immediately
+ if (cdp->wlen == 1) {
+ cdp->intreq2 = true;
+ }
+ vv |= 0x80000000;
+ }
}
if (cyc > 0) {
event2_newevent_xx(-1, cyc, vv, event_audxdat_func);
{
struct audio_channel_data *acd = audio_channel + nr;
- zerostate (nr);
+ zerostate(nr, true);
acd->state = restore_u8 ();
acd->data.audvol = restore_u8 ();
acd->intreq2 = restore_u8 () ? true : false;