make OSS detect blocking, adjust audio API
authornotaz <notasas@gmail.com>
Sat, 18 Sep 2010 16:40:13 +0000 (16:40 +0000)
committernotaz <notasas@gmail.com>
Sat, 18 Sep 2010 16:40:13 +0000 (16:40 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@898 be3aeb3a-fb24-0410-a615-afba39da0efa

common/emu.c
common/emu.h
gp2x/emu.c
linux/emu.c
linux/sndout_oss.c
linux/sndout_oss.h
pandora/plat.c
psp/emu.c

index 8e5a8d5..822d7aa 100644 (file)
@@ -1350,6 +1350,26 @@ static void mkdir_path(char *path_with_reserve, int pos, const char *name)
                lprintf("failed to create: %s\n", path_with_reserve);\r
 }\r
 \r
+void emu_cmn_forced_frame(int no_scale, int do_emu)\r
+{\r
+       int po_old = PicoOpt;\r
+\r
+       memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4);\r
+\r
+       PicoOpt |= POPT_ACC_SPRITES;\r
+       if (!no_scale)\r
+               PicoOpt |= POPT_EN_SOFTSCALE;\r
+\r
+       PicoDrawSetOutFormat(PDF_RGB555, 1);\r
+       Pico.m.dirtyPal = 1;\r
+       if (do_emu)\r
+               PicoFrame();\r
+       else\r
+               PicoFrameDrawOnly();\r
+\r
+       PicoOpt = po_old;\r
+}\r
+\r
 void emu_init(void)\r
 {\r
        char path[512];\r
index be3e5bf..cfa3527 100644 (file)
@@ -146,6 +146,9 @@ void  emu_get_game_name(char *str150);
 void  emu_set_fastforward(int set_on);
 void  emu_status_msg(const char *format, ...);
 
+/* used by some (but not all) platforms */
+void  emu_cmn_forced_frame(int no_scale, int do_emu);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 659d3a7..4addd46 100644 (file)
@@ -710,18 +710,13 @@ void plat_update_volume(int has_changed, int is_up)
        }\r
 }\r
 \r
-static void updateSound(int len)\r
+static void oss_write_nonblocking(int len)\r
 {\r
-       len <<= 1;\r
-       if (PicoOpt & POPT_EN_STEREO)\r
-               len <<= 1;\r
-\r
+       // sndout_oss_can_write() is not reliable, only use with no_frmlimit\r
        if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len))\r
                return;\r
 \r
-       /* avoid writing audio when lagging behind to prevent audio lag */\r
-       if (PicoSkipFrame != 2)\r
-               sndout_oss_write(PsndOut, len);\r
+       sndout_oss_write_nb(PsndOut, len);\r
 }\r
 \r
 void pemu_sound_start(void)\r
@@ -739,7 +734,7 @@ void pemu_sound_start(void)
 \r
                memset(sndBuffer, 0, sizeof(sndBuffer));\r
                PsndOut = sndBuffer;\r
-               PicoWriteSound = updateSound;\r
+               PicoWriteSound = oss_write_nonblocking;\r
                plat_update_volume(0, 0);\r
 \r
                printf("starting audio: %i len: %i stereo: %i, pal: %i\n",\r
@@ -786,30 +781,16 @@ void pemu_sound_wait(void)
 \r
 void pemu_forced_frame(int no_scale, int do_emu)\r
 {\r
-       int po_old = PicoOpt;\r
-\r
-       PicoOpt &= ~POPT_ALT_RENDERER;\r
-       PicoOpt |= POPT_ACC_SPRITES;\r
-       if (!no_scale)\r
-               PicoOpt |= POPT_EN_SOFTSCALE;\r
-\r
-       memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4);\r
-\r
-       PicoDrawSetOutFormat(PDF_RGB555, 1);\r
+       doing_bg_frame = 1;\r
        PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);\r
        PicoDraw32xSetFrameMode(0, 0);\r
        PicoDrawSetCallbacks(NULL, NULL);\r
        Pico.m.dirtyPal = 1;\r
 \r
-       doing_bg_frame = 1;\r
-       if (do_emu)\r
-               PicoFrame();\r
-       else\r
-               PicoFrameDrawOnly();\r
-       doing_bg_frame = 0;\r
+       emu_cmn_forced_frame(no_scale, do_emu);\r
 \r
        g_menubg_src_ptr = g_screen_ptr;\r
-       PicoOpt = po_old;\r
+       doing_bg_frame = 0;\r
 }\r
 \r
 void plat_debug_cat(char *str)\r
index f5a21c3..aef2197 100644 (file)
@@ -210,47 +210,27 @@ void plat_update_volume(int has_changed, int is_up)
 \r
 void pemu_forced_frame(int no_scale, int do_emu)\r
 {\r
-       int po_old = PicoOpt;\r
-\r
-       memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4);\r
-\r
-       PicoOpt &= ~POPT_ALT_RENDERER;\r
-       PicoOpt |= POPT_ACC_SPRITES;\r
-       if (!no_scale)\r
-               PicoOpt |= POPT_EN_SOFTSCALE;\r
-\r
-       PicoDrawSetOutFormat(PDF_RGB555, 1);\r
        PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);\r
        PicoDraw32xSetFrameMode(0, 0);\r
-\r
+       PicoDrawSetCallbacks(NULL, NULL);\r
        Pico.m.dirtyPal = 1;\r
-       if (do_emu)\r
-               PicoFrame();\r
-       else\r
-               PicoFrameDrawOnly();\r
+\r
+       emu_cmn_forced_frame(no_scale, do_emu);\r
 \r
        g_menubg_src_ptr = g_screen_ptr;\r
-       PicoOpt = po_old;\r
 }\r
 \r
-static void updateSound(int len)\r
+static void oss_write_nonblocking(int len)\r
 {\r
-       len <<= 1;\r
-       if (PicoOpt & POPT_EN_STEREO)\r
-               len <<= 1;\r
-\r
+       // sndout_oss_can_write() is not reliable, only use with no_frmlimit\r
        if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len))\r
                return;\r
 \r
-       /* avoid writing audio when lagging behind to prevent audio lag */\r
-       if (PicoSkipFrame != 2)\r
-               sndout_oss_write(PsndOut, len);\r
+       sndout_oss_write_nb(PsndOut, len);\r
 }\r
 \r
 void pemu_sound_start(void)\r
 {\r
-       int target_fps = Pico.m.pal ? 50 : 60;\r
-\r
        PsndOut = NULL;\r
 \r
        if (currentConfig.EmuOpt & EOPT_EN_SOUND)\r
@@ -263,7 +243,7 @@ void pemu_sound_start(void)
                        PsndRate, PsndLen, is_stereo, Pico.m.pal);\r
                sndout_oss_start(PsndRate, is_stereo, 1);\r
                sndout_oss_setvol(currentConfig.volume, currentConfig.volume);\r
-               PicoWriteSound = updateSound;\r
+               PicoWriteSound = oss_write_nonblocking;\r
                plat_update_volume(0, 0);\r
                memset(sndBuffer, 0, sizeof(sndBuffer));\r
                PsndOut = sndBuffer;\r
index f9cc6c2..2313d3f 100644 (file)
@@ -98,6 +98,42 @@ int sndout_oss_write(const void *buff, int len)
        return write(sounddev, buff, len);
 }
 
+#include "../common/plat.h"
+
+/* not really non-blocking, just detects if blocking occurs
+ * and starts skipping writes in case it does. */
+int sndout_oss_write_nb(const void *buff, int len)
+{
+       static int lag_counter, skip_counter;
+       unsigned int t;
+       int ret;
+
+       if (lag_counter > 2) {
+               // skip writes if audio starts blocking
+               lag_counter = 0;
+               skip_counter = FRAG_COUNT;
+       }
+
+       if (skip_counter > 0) {
+               skip_counter--;
+               return len;
+       }
+
+       t = plat_get_ticks_ms();
+       ret = sndout_oss_write(buff, len);
+       t = plat_get_ticks_ms() - t;
+       if (t > 1) {
+               // this shouldn't really happen, most likely audio is out of sync
+               lag_counter++;
+               if (lag_counter > 2)
+                       printf("audio lag %u\n", t);
+       }
+       else
+               lag_counter = 0;
+
+       return ret;
+}
+
 int sndout_oss_can_write(int bytes)
 {
        audio_buf_info bi;
index cfbd70d..0b3fe6c 100644 (file)
@@ -2,6 +2,7 @@ int  sndout_oss_init(void);
 int  sndout_oss_start(int rate, int stereo, int frames_in_frag);
 void sndout_oss_stop(void);
 int  sndout_oss_write(const void *buff, int len);
+int  sndout_oss_write_nb(const void *buff, int len);
 int  sndout_oss_can_write(int bytes);
 void sndout_oss_sync(void);
 void sndout_oss_setvol(int l, int r);
index a24e3ba..b95334d 100644 (file)
@@ -240,51 +240,22 @@ static void make_bg(int no_scale)
 \r
 void pemu_forced_frame(int no_scale, int do_emu)\r
 {\r
-       int po_old = PicoOpt;\r
-\r
-       memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4);\r
-\r
-       PicoOpt |= POPT_ACC_SPRITES;\r
-       if (!no_scale)\r
-               PicoOpt |= POPT_EN_SOFTSCALE;\r
-\r
-       PicoDrawSetOutFormat(PDF_RGB555, 1);\r
-       Pico.m.dirtyPal = 1;\r
        doing_bg_frame = 1;\r
-       if (do_emu)\r
-               PicoFrame();\r
-       else\r
-               PicoFrameDrawOnly();\r
+       emu_cmn_forced_frame(no_scale, do_emu);\r
        doing_bg_frame = 0;\r
 \r
        // making a copy because enabling the layer clears it's mem\r
        memcpy32((void *)fb_copy, g_screen_ptr, sizeof(fb_copy) / 4);\r
        make_bg(no_scale);\r
-\r
-       PicoOpt = po_old;\r
 }\r
 \r
-static void updateSound(int len)\r
+static void oss_write_nonblocking(int len)\r
 {\r
-       unsigned int t;\r
-\r
-       len <<= 1;\r
-       if (PicoOpt & POPT_EN_STEREO)\r
-               len <<= 1;\r
-\r
-       // sndout_oss_can_write() not reliable..\r
+       // sndout_oss_can_write() is not reliable, only use with no_frmlimit\r
        if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len))\r
                return;\r
 \r
-       /* avoid writing audio when lagging behind to prevent audio lag */\r
-       if (PicoSkipFrame == 2)\r
-               return;\r
-\r
-       t = plat_get_ticks_ms();\r
-       sndout_oss_write(PsndOut, len);\r
-       t = plat_get_ticks_ms() - t;\r
-       if (t > 1)\r
-               printf("audio lag %u\n", t);\r
+       sndout_oss_write_nb(PsndOut, len);\r
 }\r
 \r
 void pemu_sound_start(void)\r
@@ -308,7 +279,7 @@ void pemu_sound_start(void)
                        PsndRate, PsndLen, is_stereo, Pico.m.pal);\r
                sndout_oss_start(PsndRate, is_stereo, 2);\r
                //sndout_oss_setvol(currentConfig.volume, currentConfig.volume);\r
-               PicoWriteSound = updateSound;\r
+               PicoWriteSound = oss_write_nonblocking;\r
                plat_update_volume(0, 0);\r
                memset(sndBuffer, 0, sizeof(sndBuffer));\r
                PsndOut = sndBuffer;\r
index 311a7ec..feab5f5 100644 (file)
--- a/psp/emu.c
+++ b/psp/emu.c
@@ -637,9 +637,8 @@ static void sound_deinit(void)
 static void writeSound(int len)
 {
        int ret;
-       if (PicoOpt&8) len<<=1;
 
-       PsndOut += len;
+       PsndOut += len / 2;
        /*if (PsndOut > sndBuffer_endptr) {
                memcpy32((int *)(void *)sndBuffer, (int *)endptr, (PsndOut - endptr + 1) / 2);
                PsndOut = &sndBuffer[PsndOut - endptr];
@@ -651,7 +650,7 @@ static void writeSound(int len)
                PsndOut = sndBuffer;
 
        // signal the snd thread
-       samples_made += len;
+       samples_made += len / 2;
        if (samples_made - samples_done > samples_block*2) {
                // lprintf("signal, %i/%i\n", samples_done, samples_made);
                ret = sceKernelSignalSema(sound_sem, 1);