]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Audio event priority change, intreq2 handling changes, small period hack modified.
authorToni Wilen <twilen@winuae.net>
Tue, 23 Apr 2024 18:09:10 +0000 (21:09 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 23 Apr 2024 18:09:10 +0000 (21:09 +0300)
audio.cpp
include/events.h

index 6c7fbf153577c26d89970ec02c8e6876f9d35de3..20340148d0b592f7ab2af65128850d9b5ea0b232 100644 (file)
--- a/audio.cpp
+++ b/audio.cpp
@@ -57,6 +57,7 @@
 #define PERIOD_MIN 1
 #define PERIOD_MIN_NONCE 60
 #define PERIOD_MIN_LOOP 16
+#define PERIOD_MIN_LOOP_COUNT 64
 
 #define PERIOD_LOW 124
 
@@ -154,6 +155,7 @@ struct audio_channel_data
        int dmaofftime_active;
        int dmaofftime_cpu_cnt;
        uaecptr dmaofftime_pc;
+       int minperloop;
        int volcntbufcnt;
        float volcntbuf[VOLCNT_BUFFER_SIZE];
 };
@@ -1395,7 +1397,7 @@ static void sample16si_rh_handler (void)
 
 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
@@ -1405,11 +1407,14 @@ static void zerostate (int nr)
        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;
@@ -1451,10 +1456,12 @@ static void audio_event_reset (void)
 
        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;
@@ -1715,7 +1722,7 @@ static bool audio_state_channel2 (int nr, bool perfin)
        cdp->dmaenstore = chan_ena;
 
        if (currprefs.produce_sound == 0) {
-               zerostate (nr);
+               zerostate (nr, true);
                return true;
        }
        audio_activate ();
@@ -1745,7 +1752,7 @@ static bool audio_state_channel2 (int nr, bool perfin)
                                        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--;
@@ -1793,7 +1800,7 @@ static bool audio_state_channel2 (int nr, bool perfin)
                                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--;
@@ -1803,13 +1810,13 @@ static bool audio_state_channel2 (int nr, bool perfin)
                                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)
@@ -1831,7 +1838,7 @@ static bool audio_state_channel2 (int nr, bool perfin)
        case 5:
                cdp->evtime = MAX_EV;
                if (!chan_ena) {
-                       zerostate(nr);
+                       zerostate(nr, false);
                        return true;
                }
                if (!cdp->dat_written)
@@ -1850,7 +1857,9 @@ static bool audio_state_channel2 (int nr, bool perfin)
                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;
@@ -1883,13 +1892,17 @@ static bool audio_state_channel2 (int nr, bool perfin)
                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;
@@ -1942,13 +1955,17 @@ static bool audio_state_channel2 (int nr, bool perfin)
 
                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);
@@ -1958,12 +1975,11 @@ static bool audio_state_channel2 (int nr, bool perfin)
                                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);
@@ -2482,9 +2498,14 @@ void event_audxdat_func(uae_u32 v)
                                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
@@ -2551,7 +2572,14 @@ void AUDxDAT(int nr, uae_u16 v, uaecptr addr)
                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);
@@ -2777,7 +2805,7 @@ uae_u8 *restore_audio (int nr, uae_u8 *src)
 {
        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;
index cc04dfb6ed708539dc3c2f7bbc818a35ed6f6921..ea61af090723c0371921f3a4b2cf142a062ba77e 100644 (file)
@@ -64,7 +64,8 @@ struct ev2
 
 // hsync handlers must have priority over misc
 enum {
-       ev_cia, ev_audio, ev_hsync, ev_hsynch, ev_misc,
+       ev_cia, ev_hsync, ev_hsynch, ev_misc,
+       ev_audio,
        ev_max
 };