From b3ea40df1fbd2e2a638eae688e8b11f847ec3205 Mon Sep 17 00:00:00 2001 From: Dimitris Panokostas Date: Sun, 11 Dec 2016 21:42:59 +0100 Subject: [PATCH] Recover CD32 audio after audio improvements --- src/sd-pandora/sound.h | 6 +- src/sd-sdl/sound_sdl_new.cpp | 275 +++++++++++++++++++---------------- 2 files changed, 154 insertions(+), 127 deletions(-) diff --git a/src/sd-pandora/sound.h b/src/sd-pandora/sound.h index 865f034c..ae20a30a 100644 --- a/src/sd-pandora/sound.h +++ b/src/sd-pandora/sound.h @@ -61,8 +61,8 @@ STATIC_INLINE void clear_sound_buffers (void) #define FILTER_SOUND_TYPE_A1200 1 -#define CDAUDIO_BUFFERS 32 -#define CDAUDIO_BUFFER_LEN 2048 +#define CDAUDIO_BUFFERS 64 +#define CDAUDIO_BUFFER_LEN 256 extern uae_u16 cdaudio_buffer[CDAUDIO_BUFFERS][(CDAUDIO_BUFFER_LEN + 32) * 2]; extern uae_u16 *cdbufpt; extern uae_u16 *render_cdbuff; @@ -73,7 +73,7 @@ extern bool cdaudio_active; STATIC_INLINE void clear_cdaudio_buffers (void) { - memset (cdaudio_buffer, 0, CDAUDIO_BUFFERS * (CDAUDIO_BUFFER_LEN + 32) * 2); + memset (cdaudio_buffer, 0, sizeof(cdaudio_buffer)); } #define PUT_CDAUDIO_WORD_STEREO(l,r) do { *((uae_u32 *)cdbufpt) = (r << 16) | (l & 0xffff); cdbufpt = cdbufpt + 2; } while (0) diff --git a/src/sd-sdl/sound_sdl_new.cpp b/src/sd-sdl/sound_sdl_new.cpp index 5167fc14..dfa8e59e 100644 --- a/src/sd-sdl/sound_sdl_new.cpp +++ b/src/sd-sdl/sound_sdl_new.cpp @@ -28,17 +28,20 @@ #include #endif +// "consumer" means the actual SDL sound output, as opposed to +#define SOUND_CONSUMER_BUFFER_LENGTH (SNDBUFFER_LEN * SOUND_BUFFERS_COUNT / 4) + extern unsigned long next_sample_evtime; int produce_sound=0; int changed_produce_sound=0; -#define SOUND_USE_SEMAPHORES -uae_u16 sndbuffer[SOUND_BUFFERS_COUNT][(SNDBUFFER_LEN+32)*DEFAULT_SOUND_CHANNELS]; +//#define SOUND_USE_SEMAPHORES +uae_u16 sndbuffer[SOUND_BUFFERS_COUNT][(SNDBUFFER_LEN + 32)*DEFAULT_SOUND_CHANNELS]; unsigned n_callback_sndbuff, n_render_sndbuff; uae_u16 *sndbufpt = sndbuffer[0]; uae_u16 *render_sndbuff = sndbuffer[0]; -uae_u16 *finish_sndbuff = sndbuffer[0] + SNDBUFFER_LEN*2; +uae_u16 *finish_sndbuff = sndbuffer[0] + SNDBUFFER_LEN * 2; uae_u16 cdaudio_buffer[CDAUDIO_BUFFERS][(CDAUDIO_BUFFER_LEN + 32) * 2]; uae_u16 *cdbufpt = cdaudio_buffer[0]; @@ -101,61 +104,84 @@ static int sound_thread_active = 0, sound_thread_exit = 0; static sem_t sound_sem, callback_sem; #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) -static int cnt = 0; +static int rdcnt = 0; static int wrcnt = 0; -static void sound_thread_mixer(void *ud, Uint8 *stream, int len) +static void sound_copy_produced_block(void *ud, Uint8 *stream, int len) { - if (sound_thread_exit) return; - int sem_val; - sound_thread_active = 1; - - #ifdef SOUND_USE_SEMAPHORES sem_wait(&sound_sem); #endif - //printf("Sound callback %i\n", cnt); - //__android_log_print(ANDROID_LOG_INFO, "UAE4ALL2","Sound callback cnt %d buf %d\n", cnt, cnt%SOUND_BUFFERS_COUNT); - if(currprefs.sound_stereo) + if (currprefs.sound_stereo) + { + if (cdaudio_active && currprefs.sound_freq == 44100 && cdrdcnt < cdwrcnt) { - - if(cdaudio_active && currprefs.sound_freq == 44100 && cdrdcnt < cdwrcnt) - { - for(int i=0; i= (SOUND_BUFFERS_COUNT/2)) + { + rdcnt++; + cdrdcnt++; + } + + // if less than half of the production buffers are full, it means that more sound has been + // output (by SDL) than the emulation has produced. We solve this by simply not + // moving the "read head", until the emulation side has got enough headway. + #ifdef SOUND_USE_SEMAPHORES sem_post(&callback_sem); #endif } +static void sound_thread_mixer(void *ud, Uint8 *stream, int len) +{ + static int call_count = 0; + if (sound_thread_exit) return; + sound_thread_active = 1; + + int sample_size = currprefs.sound_stereo ? 4 : 2; + + while (len > 0) { + int l = MIN(SNDBUFFER_LEN * sample_size, len); + sound_copy_produced_block(ud, stream, l); + stream += l; + len -= l; + } + +// if (call_count % 10 == 0) +// printf("wrcnt - rdcnt: %d\n", wrcnt - rdcnt); + + call_count++; +} + static void init_soundbuffer_usage(void) { - sndbufpt = sndbuffer[0]; - render_sndbuff = sndbuffer[0]; - finish_sndbuff = sndbuffer[0] + SNDBUFFER_LEN * 2; - //output_cnt = 0; - cnt = 0; - wrcnt = 0; + sndbufpt = sndbuffer[0]; + render_sndbuff = sndbuffer[0]; + finish_sndbuff = sndbuffer[0] + SNDBUFFER_LEN * 2; + //output_cnt = 0; + rdcnt = 0; + wrcnt = 0; - cdbufpt = cdaudio_buffer[0]; - render_cdbuff = cdaudio_buffer[0]; - finish_cdbuff = cdaudio_buffer[0] + CDAUDIO_BUFFER_LEN * 2; - cdrdcnt = 0; - cdwrcnt = 0; + cdbufpt = cdaudio_buffer[0]; + render_cdbuff = cdaudio_buffer[0]; + finish_cdbuff = cdaudio_buffer[0] + CDAUDIO_BUFFER_LEN * 2; + cdrdcnt = 0; + cdwrcnt = 0; } @@ -168,17 +194,15 @@ static int pandora_start_sound(int rate, int bits, int stereo) // if no settings change, we don't need to do anything if (rate == s_oldrate && s_oldbits == bits && s_oldstereo == stereo && audioOpened) - return 0; + return 0; if (audioOpened) - pandora_stop_sound(); + pandora_stop_sound(); - // init sem, start sound thread + // init sem, start sound thread init_soundbuffer_usage(); -#ifdef DEBUG printf("starting sound thread..\n"); -#endif ret = sem_init(&sound_sem, 0, 0); sem_init(&callback_sem, 0, SOUND_BUFFERS_COUNT - 1); if (ret != 0) printf("sem_init() failed: %i, errno=%i\n", ret, errno); @@ -191,18 +215,19 @@ static int pandora_start_sound(int rate, int bits, int stereo) as.freq = rate; as.format = (bits == 8 ? AUDIO_S8 : AUDIO_S16); as.channels = (stereo ? 2 : 1); - as.samples = SNDBUFFER_LEN; + as.samples = SOUND_CONSUMER_BUFFER_LENGTH; +// as.samples = SNDBUFFER_LEN; as.callback = sound_thread_mixer; if (SDL_OpenAudio(&as, NULL)) - printf("Error when opening SDL audio !\n"); + printf("Error when opening SDL audio !\n"); audioOpened = 1; s_oldrate = rate; s_oldbits = bits; s_oldstereo = stereo; - SDL_PauseAudio (0); + SDL_PauseAudio(0); return 0; } @@ -215,21 +240,19 @@ void pandora_stop_sound(void) printf("don't call pandora_stop_sound more than once!\n"); if (sound_thread_active) { -#ifdef DEBUG - printf("stopping sound thread...\n"); -#endif + printf("stopping sound thread..\n"); sound_thread_exit = 1; sem_post(&sound_sem); - usleep(100*1000); + usleep(100 * 1000); sem_destroy(&sound_sem); sem_destroy(&callback_sem); } sound_thread_exit = 0; - SDL_PauseAudio (1); + SDL_PauseAudio(1); SDL_CloseAudio(); } -void finish_sound_buffer (void) +void finish_sound_buffer(void) { #ifdef DEBUG_SOUND @@ -238,195 +261,198 @@ void finish_sound_buffer (void) //printf("Sound finish %i\n", wrcnt); - + // "GET NEXT PRODUCER BUFFER FOR WRITING" wrcnt++; - sndbufpt = render_sndbuff = sndbuffer[wrcnt%SOUND_BUFFERS_COUNT]; + sndbufpt = render_sndbuff = sndbuffer[wrcnt % SOUND_BUFFERS_COUNT]; - if(currprefs.sound_stereo) - finish_sndbuff = sndbufpt + SNDBUFFER_LEN * 2; + if (currprefs.sound_stereo) + finish_sndbuff = sndbufpt + SNDBUFFER_LEN * 2; else - finish_sndbuff = sndbufpt + SNDBUFFER_LEN; + finish_sndbuff = sndbufpt + SNDBUFFER_LEN; #ifdef SOUND_USE_SEMAPHORES sem_post(&sound_sem); sem_wait(&callback_sem); #endif - +/* while ((wrcnt % SOUND_BUFFERS_COUNT) == (rdcnt % SOUND_BUFFERS_COUNT)) + { + + } */ #ifdef DEBUG_SOUND dbg(" sound.c : ! finish_sound_buffer"); #endif } -void pause_sound_buffer (void) +void pause_sound_buffer(void) { - reset_sound (); + reset_sound(); } void restart_sound_buffer(void) { sndbufpt = render_sndbuff = sndbuffer[wrcnt % SOUND_BUFFERS_COUNT]; - if(currprefs.sound_stereo) - finish_sndbuff = sndbufpt + SNDBUFFER_LEN * 2; + if (currprefs.sound_stereo) + finish_sndbuff = sndbufpt + SNDBUFFER_LEN * 2; else - finish_sndbuff = sndbufpt + SNDBUFFER_LEN; + finish_sndbuff = sndbufpt + SNDBUFFER_LEN; cdbufpt = render_cdbuff = cdaudio_buffer[cdwrcnt & (CDAUDIO_BUFFERS - 1)]; finish_cdbuff = cdbufpt + CDAUDIO_BUFFER_LEN * 2; } -void finish_cdaudio_buffer (void) +void finish_cdaudio_buffer(void) { cdwrcnt++; cdbufpt = render_cdbuff = cdaudio_buffer[cdwrcnt & (CDAUDIO_BUFFERS - 1)]; - finish_cdbuff = cdbufpt + CDAUDIO_BUFFER_LEN * 2; - audio_activate(); + finish_cdbuff = cdbufpt + CDAUDIO_BUFFER_LEN * 2; + audio_activate(); } bool cdaudio_catchup(void) { - while((cdwrcnt > cdrdcnt + CDAUDIO_BUFFERS - 10) && (sound_thread_active != 0) && (quit_program == 0)) { - sleep_millis(10); - } - return (sound_thread_active != 0); + while ((cdwrcnt > cdrdcnt + CDAUDIO_BUFFERS - 30) && (sound_thread_active != 0) && (quit_program == 0)) { + sleep_millis(10); + } + return (sound_thread_active != 0); } /* Try to determine whether sound is available. This is only for GUI purposes. */ -int setup_sound (void) +int setup_sound(void) { #ifdef DEBUG_SOUND - dbg("sound.c : setup_sound"); + dbg("sound.c : setup_sound"); #endif - // Android does not like opening sound device several times - if (pandora_start_sound(currprefs.sound_freq, 16, currprefs.sound_stereo) != 0) - return 0; + // Android does not like opening sound device several times + if (pandora_start_sound(currprefs.sound_freq, 16, currprefs.sound_stereo) != 0) + return 0; - sound_available = 1; + sound_available = 1; #ifdef DEBUG_SOUND - dbg(" sound.c : ! setup_sound"); + dbg(" sound.c : ! setup_sound"); #endif - return 1; + return 1; } -static int open_sound (void) +static int open_sound(void) { #ifdef DEBUG_SOUND - dbg("sound.c : open_sound"); + dbg("sound.c : open_sound"); #endif - // Android does not like opening sound device several times - if (pandora_start_sound(currprefs.sound_freq, 16, currprefs.sound_stereo) != 0) - return 0; + // Android does not like opening sound device several times + if (pandora_start_sound(currprefs.sound_freq, 16, currprefs.sound_stereo) != 0) + return 0; - have_sound = 1; - sound_available = 1; + have_sound = 1; + sound_available = 1; - if(currprefs.sound_stereo) - sample_handler = sample16s_handler; - else - sample_handler = sample16_handler; + if (currprefs.sound_stereo) + sample_handler = sample16s_handler; + else + sample_handler = sample16_handler; #ifdef DEBUG_SOUND - dbg(" sound.c : ! open_sound"); + dbg(" sound.c : ! open_sound"); #endif - return 1; + return 1; } -void close_sound (void) +void close_sound(void) { #ifdef DEBUG_SOUND - dbg("sound.c : close_sound"); + dbg("sound.c : close_sound"); #endif - if (!have_sound) - return; + if (!have_sound) + return; - // testing shows that reopenning sound device is not a good idea (causes random sound driver crashes) - // we will close it on real exit instead + // testing shows that reopenning sound device is not a good idea (causes random sound driver crashes) + // we will close it on real exit instead #ifdef RASPBERRY - //pandora_stop_sound(); + //pandora_stop_sound(); #endif - have_sound = 0; + have_sound = 0; #ifdef DEBUG_SOUND - dbg(" sound.c : ! close_sound"); + dbg(" sound.c : ! close_sound"); #endif } -int init_sound (void) +int init_sound(void) { #ifdef DEBUG_SOUND - dbg("sound.c : init_sound"); + dbg("sound.c : init_sound"); #endif - have_sound=open_sound(); + have_sound = open_sound(); #ifdef DEBUG_SOUND - dbg(" sound.c : ! init_sound"); + dbg(" sound.c : ! init_sound"); #endif - return have_sound; + return have_sound; } -void pause_sound (void) +void pause_sound(void) { #ifdef DEBUG_SOUND - dbg("sound.c : pause_sound"); + dbg("sound.c : pause_sound"); #endif - SDL_PauseAudio (1); + SDL_PauseAudio(1); /* nothing to do */ #ifdef DEBUG_SOUND - dbg(" sound.c : ! pause_sound"); + dbg(" sound.c : ! pause_sound"); #endif } -void resume_sound (void) +void resume_sound(void) { #ifdef DEBUG_SOUND - dbg("sound.c : resume_sound"); + dbg("sound.c : resume_sound"); #endif - SDL_PauseAudio (0); + SDL_PauseAudio(0); /* nothing to do */ #ifdef DEBUG_SOUND - dbg(" sound.c : ! resume_sound"); + dbg(" sound.c : ! resume_sound"); #endif } void uae4all_init_sound(void) { #ifdef DEBUG_SOUND - dbg("sound.c : uae4all_init_sound"); + dbg("sound.c : uae4all_init_sound"); #endif #ifdef DEBUG_SOUND - dbg(" sound.c : ! uae4all_init_sound"); + dbg(" sound.c : ! uae4all_init_sound"); #endif } void uae4all_pause_music(void) { #ifdef DEBUG_SOUND - dbg("sound.c : pause_music"); + dbg("sound.c : pause_music"); #endif #ifdef DEBUG_SOUND - dbg(" sound.c : ! pause_music"); + dbg(" sound.c : ! pause_music"); #endif } void uae4all_resume_music(void) { #ifdef DEBUG_SOUND - dbg("sound.c : resume_music"); + dbg("sound.c : resume_music"); #endif #ifdef DEBUG_SOUND - dbg(" sound.c : ! resume_music"); + dbg(" sound.c : ! resume_music"); #endif } @@ -434,21 +460,22 @@ void uae4all_play_click(void) { } -void reset_sound (void) +void reset_sound(void) { - if (!have_sound) - return; + if (!have_sound) + return; - //init_soundbuffer_usage(); + init_soundbuffer_usage(); - clear_sound_buffers(); - clear_cdaudio_buffers(); + clear_sound_buffers(); + clear_cdaudio_buffers(); } -void sound_volume (int dir) +void sound_volume(int dir) { } #endif +