From a33164fffe6463cd0aa698fac2bcc1fc213af18e Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 18 Sep 2010 16:40:13 +0000 Subject: [PATCH] make OSS detect blocking, adjust audio API git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@898 be3aeb3a-fb24-0410-a615-afba39da0efa --- common/emu.c | 20 ++++++++++++++++++++ common/emu.h | 3 +++ gp2x/emu.c | 33 +++++++-------------------------- linux/emu.c | 34 +++++++--------------------------- linux/sndout_oss.c | 36 ++++++++++++++++++++++++++++++++++++ linux/sndout_oss.h | 1 + pandora/plat.c | 39 +++++---------------------------------- psp/emu.c | 5 ++--- 8 files changed, 81 insertions(+), 90 deletions(-) diff --git a/common/emu.c b/common/emu.c index 8e5a8d5..822d7aa 100644 --- a/common/emu.c +++ b/common/emu.c @@ -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); } +void emu_cmn_forced_frame(int no_scale, int do_emu) +{ + int po_old = PicoOpt; + + memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4); + + PicoOpt |= POPT_ACC_SPRITES; + if (!no_scale) + PicoOpt |= POPT_EN_SOFTSCALE; + + PicoDrawSetOutFormat(PDF_RGB555, 1); + Pico.m.dirtyPal = 1; + if (do_emu) + PicoFrame(); + else + PicoFrameDrawOnly(); + + PicoOpt = po_old; +} + void emu_init(void) { char path[512]; diff --git a/common/emu.h b/common/emu.h index be3e5bf..cfa3527 100644 --- a/common/emu.h +++ b/common/emu.h @@ -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 diff --git a/gp2x/emu.c b/gp2x/emu.c index 659d3a7..4addd46 100644 --- a/gp2x/emu.c +++ b/gp2x/emu.c @@ -710,18 +710,13 @@ void plat_update_volume(int has_changed, int is_up) } } -static void updateSound(int len) +static void oss_write_nonblocking(int len) { - len <<= 1; - if (PicoOpt & POPT_EN_STEREO) - len <<= 1; - + // sndout_oss_can_write() is not reliable, only use with no_frmlimit if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len)) return; - /* avoid writing audio when lagging behind to prevent audio lag */ - if (PicoSkipFrame != 2) - sndout_oss_write(PsndOut, len); + sndout_oss_write_nb(PsndOut, len); } void pemu_sound_start(void) @@ -739,7 +734,7 @@ void pemu_sound_start(void) memset(sndBuffer, 0, sizeof(sndBuffer)); PsndOut = sndBuffer; - PicoWriteSound = updateSound; + PicoWriteSound = oss_write_nonblocking; plat_update_volume(0, 0); printf("starting audio: %i len: %i stereo: %i, pal: %i\n", @@ -786,30 +781,16 @@ void pemu_sound_wait(void) void pemu_forced_frame(int no_scale, int do_emu) { - int po_old = PicoOpt; - - PicoOpt &= ~POPT_ALT_RENDERER; - PicoOpt |= POPT_ACC_SPRITES; - if (!no_scale) - PicoOpt |= POPT_EN_SOFTSCALE; - - memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4); - - PicoDrawSetOutFormat(PDF_RGB555, 1); + doing_bg_frame = 1; PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2); PicoDraw32xSetFrameMode(0, 0); PicoDrawSetCallbacks(NULL, NULL); Pico.m.dirtyPal = 1; - doing_bg_frame = 1; - if (do_emu) - PicoFrame(); - else - PicoFrameDrawOnly(); - doing_bg_frame = 0; + emu_cmn_forced_frame(no_scale, do_emu); g_menubg_src_ptr = g_screen_ptr; - PicoOpt = po_old; + doing_bg_frame = 0; } void plat_debug_cat(char *str) diff --git a/linux/emu.c b/linux/emu.c index f5a21c3..aef2197 100644 --- a/linux/emu.c +++ b/linux/emu.c @@ -210,47 +210,27 @@ void plat_update_volume(int has_changed, int is_up) void pemu_forced_frame(int no_scale, int do_emu) { - int po_old = PicoOpt; - - memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4); - - PicoOpt &= ~POPT_ALT_RENDERER; - PicoOpt |= POPT_ACC_SPRITES; - if (!no_scale) - PicoOpt |= POPT_EN_SOFTSCALE; - - PicoDrawSetOutFormat(PDF_RGB555, 1); PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2); PicoDraw32xSetFrameMode(0, 0); - + PicoDrawSetCallbacks(NULL, NULL); Pico.m.dirtyPal = 1; - if (do_emu) - PicoFrame(); - else - PicoFrameDrawOnly(); + + emu_cmn_forced_frame(no_scale, do_emu); g_menubg_src_ptr = g_screen_ptr; - PicoOpt = po_old; } -static void updateSound(int len) +static void oss_write_nonblocking(int len) { - len <<= 1; - if (PicoOpt & POPT_EN_STEREO) - len <<= 1; - + // sndout_oss_can_write() is not reliable, only use with no_frmlimit if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len)) return; - /* avoid writing audio when lagging behind to prevent audio lag */ - if (PicoSkipFrame != 2) - sndout_oss_write(PsndOut, len); + sndout_oss_write_nb(PsndOut, len); } void pemu_sound_start(void) { - int target_fps = Pico.m.pal ? 50 : 60; - PsndOut = NULL; if (currentConfig.EmuOpt & EOPT_EN_SOUND) @@ -263,7 +243,7 @@ void pemu_sound_start(void) PsndRate, PsndLen, is_stereo, Pico.m.pal); sndout_oss_start(PsndRate, is_stereo, 1); sndout_oss_setvol(currentConfig.volume, currentConfig.volume); - PicoWriteSound = updateSound; + PicoWriteSound = oss_write_nonblocking; plat_update_volume(0, 0); memset(sndBuffer, 0, sizeof(sndBuffer)); PsndOut = sndBuffer; diff --git a/linux/sndout_oss.c b/linux/sndout_oss.c index f9cc6c2..2313d3f 100644 --- a/linux/sndout_oss.c +++ b/linux/sndout_oss.c @@ -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; diff --git a/linux/sndout_oss.h b/linux/sndout_oss.h index cfbd70d..0b3fe6c 100644 --- a/linux/sndout_oss.h +++ b/linux/sndout_oss.h @@ -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); diff --git a/pandora/plat.c b/pandora/plat.c index a24e3ba..b95334d 100644 --- a/pandora/plat.c +++ b/pandora/plat.c @@ -240,51 +240,22 @@ static void make_bg(int no_scale) void pemu_forced_frame(int no_scale, int do_emu) { - int po_old = PicoOpt; - - memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4); - - PicoOpt |= POPT_ACC_SPRITES; - if (!no_scale) - PicoOpt |= POPT_EN_SOFTSCALE; - - PicoDrawSetOutFormat(PDF_RGB555, 1); - Pico.m.dirtyPal = 1; doing_bg_frame = 1; - if (do_emu) - PicoFrame(); - else - PicoFrameDrawOnly(); + emu_cmn_forced_frame(no_scale, do_emu); doing_bg_frame = 0; // making a copy because enabling the layer clears it's mem memcpy32((void *)fb_copy, g_screen_ptr, sizeof(fb_copy) / 4); make_bg(no_scale); - - PicoOpt = po_old; } -static void updateSound(int len) +static void oss_write_nonblocking(int len) { - unsigned int t; - - len <<= 1; - if (PicoOpt & POPT_EN_STEREO) - len <<= 1; - - // sndout_oss_can_write() not reliable.. + // sndout_oss_can_write() is not reliable, only use with no_frmlimit if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len)) return; - /* avoid writing audio when lagging behind to prevent audio lag */ - if (PicoSkipFrame == 2) - return; - - t = plat_get_ticks_ms(); - sndout_oss_write(PsndOut, len); - t = plat_get_ticks_ms() - t; - if (t > 1) - printf("audio lag %u\n", t); + sndout_oss_write_nb(PsndOut, len); } void pemu_sound_start(void) @@ -308,7 +279,7 @@ void pemu_sound_start(void) PsndRate, PsndLen, is_stereo, Pico.m.pal); sndout_oss_start(PsndRate, is_stereo, 2); //sndout_oss_setvol(currentConfig.volume, currentConfig.volume); - PicoWriteSound = updateSound; + PicoWriteSound = oss_write_nonblocking; plat_update_volume(0, 0); memset(sndBuffer, 0, sizeof(sndBuffer)); PsndOut = sndBuffer; diff --git a/psp/emu.c b/psp/emu.c index 311a7ec..feab5f5 100644 --- 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); -- 2.39.2