From d0be6591c4758a12a3307682911ad3bf14bbda90 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 13 Aug 2017 15:25:17 +0300 Subject: [PATCH] Support on the fly audio mode change when CDA/FMV is playing. --- audio.cpp | 7 ++++ blkdev_cdimage.cpp | 60 ++++++++++++++++++++++++------- cd32_fmv.cpp | 11 ++++++ od-win32/blkdev_win32_ioctl.cpp | 62 ++++++++++++++++++++++++--------- od-win32/cda_play.h | 2 ++ 5 files changed, 114 insertions(+), 28 deletions(-) diff --git a/audio.cpp b/audio.cpp index 2f3a8b8f..f950e5f7 100644 --- a/audio.cpp +++ b/audio.cpp @@ -53,6 +53,7 @@ #define PERIOD_MIN_NONCE 60 int audio_channel_mask = 15; +volatile bool cd_audio_mode_changed; STATIC_INLINE bool isaudio (void) { @@ -1946,6 +1947,7 @@ void set_audio (void) events_schedule (); } set_config_changed (); + cd_audio_mode_changed = true; } void update_audio (void) @@ -2492,6 +2494,11 @@ static bool audio_state_cda(int streamid) void audio_cda_new_buffer(uae_s16 *buffer, int length, int userdata, CDA_CALLBACK next_cd_audio_buffer_callback) { + if (length < 0 && cda_streamid > 0) { + audio_enable_stream(false, cda_streamid, 0, NULL); + cda_streamid = 0; + return; + } if (!buffer) { cda_bufptr = dummy_buffer; cda_length = 0; diff --git a/blkdev_cdimage.cpp b/blkdev_cdimage.cpp index 8fd94f86..7f9848b5 100644 --- a/blkdev_cdimage.cpp +++ b/blkdev_cdimage.cpp @@ -458,7 +458,7 @@ static void next_cd_audio_buffer_callback(int bufnum) uae_sem_post(&play_sem); } -static void *cdda_play_func (void *v) +static bool cdda_play_func2 (struct cdunit *cdu, int *outpos) { int cdda_pos; int bufnum; @@ -466,9 +466,9 @@ static void *cdda_play_func (void *v) int idleframes = 0; int silentframes = 0; bool foundsub; - struct cdunit *cdu = (struct cdunit*)v; int oldtrack = -1; int mode = currprefs.sound_cdaudio; + bool restart = false; cdu->thread_active = true; @@ -545,12 +545,14 @@ static void *cdda_play_func (void *v) } cdda_pos -= idleframes; - _ftime (&tb2); - diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm); - diff -= cdu->cdda_delay; - if (idleframes >= 0 && diff < 0 && cdu->cdda_play > 0) - sleep_millis(-diff); - setstate (cdu, AUDIO_STATUS_IN_PROGRESS, cdda_pos); + if (*outpos < 0) { + _ftime (&tb2); + diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm); + diff -= cdu->cdda_delay; + if (idleframes >= 0 && diff < 0 && cdu->cdda_play > 0) + sleep_millis(-diff); + setstate (cdu, AUDIO_STATUS_IN_PROGRESS, cdda_pos); + } sector = cdda_pos; struct cdtoc *t1 = findtoc (cdu, §or, false); @@ -568,8 +570,13 @@ static void *cdda_play_func (void *v) } if (mode) { - while (cda_bufon[bufnum] && cdu->cdda_play > 0) + while (cda_bufon[bufnum] && cdu->cdda_play > 0) { + if (cd_audio_mode_changed) { + restart = true; + goto end; + } sleep_millis(10); + } } else { cda->wait(bufnum); } @@ -702,12 +709,20 @@ static void *cdda_play_func (void *v) sleep_millis(10); } + if (cd_audio_mode_changed) { + restart = true; + goto end; + } + bufnum = 1 - bufnum; } end: + *outpos = cdda_pos; if (mode) { next_cd_audio_buffer_callback(-1); + if (restart) + audio_cda_new_buffer(NULL, -1, -1, NULL); } else { cda->wait (0); cda->wait (1); @@ -718,13 +733,34 @@ end: delete cda; - cdu->cdda_play = 0; - write_log (_T("IMAGE CDDA: thread killed\n")); + write_log (_T("IMAGE CDDA: thread killed (%s)\n"), restart ? _T("restart") : _T("play end")); + cd_audio_mode_changed = false; + return restart; +} + +static void *cdda_play_func (void *v) +{ + int outpos = -1; + struct cdunit *cdu = (struct cdunit*)v; + cd_audio_mode_changed = false; + for (;;) { + if (!cdda_play_func2(cdu, &outpos)) { + cdu->cdda_play = 0; + break; + } + cdu->cdda_start = outpos; + if (cdu->cdda_start + 150 >= cdu->cdda_end) { + if (cdu->cdda_play >= 0) + setstate (cdu, AUDIO_STATUS_PLAY_COMPLETE, cdu->cdda_end + 1); + cdu->cdda_play = -1; + break; + } + cdu->cdda_play = 1; + } cdu->thread_active = false; return NULL; } - static void cdda_stop (struct cdunit *cdu) { if (cdu->cdda_play != 0) { diff --git a/cd32_fmv.cpp b/cd32_fmv.cpp index 56d4b608..0038bfde 100644 --- a/cd32_fmv.cpp +++ b/cd32_fmv.cpp @@ -1404,6 +1404,17 @@ static void cd32_fmv_audio_handler(void) if (!fmv_ram_bank.baseaddr) return; + if (cd_audio_mode_changed) { + cd_audio_mode_changed = false; + if (cl450_play) { + if (audio_mode) { + audio_cda_new_buffer(NULL, -1, -1, NULL); + } + audio_mode = currprefs.sound_cdaudio; + fmv_bufon[0] = fmv_bufon[1] = 0; + } + } + if (cl450_buffer_offset == 0) { if (cl450_buffer_empty_cnt >= 2) cl450_set_status(CL_INT_UND); diff --git a/od-win32/blkdev_win32_ioctl.cpp b/od-win32/blkdev_win32_ioctl.cpp index 62f4e028..8abfab5d 100644 --- a/od-win32/blkdev_win32_ioctl.cpp +++ b/od-win32/blkdev_win32_ioctl.cpp @@ -503,9 +503,8 @@ void ioctl_next_cd_audio_buffer_callback(int bufnum) uae_sem_post(&play_sem); } -static void *cdda_play (void *v) +static bool cdda_play2 (struct dev_info_ioctl *ciw, int *outpos) { - struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v; int cdda_pos; int bufnum; int buffered; @@ -515,6 +514,7 @@ static void *cdda_play (void *v) int muteframes; int readblocksize = 2352 + 96; int mode = currprefs.sound_cdaudio; + bool restart = false; while (ciw->cdda_play == 0) sleep_millis(10); @@ -589,20 +589,21 @@ static void *cdda_play (void *v) } cdda_pos -= idleframes; - _ftime (&tb2); - int diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm); - diff -= ciw->cdda_delay; - if (idleframes >= 0 && diff < 0 && ciw->cdda_play > 0) - sleep_millis(-diff); - if (diff > 0 && !seensub) { - int ch = diff / 7 + 25; - if (ch > idleframes) - ch = idleframes; - idleframes -= ch; - cdda_pos += ch; + if (*outpos < 0) { + _ftime (&tb2); + int diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm); + diff -= ciw->cdda_delay; + if (idleframes >= 0 && diff < 0 && ciw->cdda_play > 0) + sleep_millis(-diff); + if (diff > 0 && !seensub) { + int ch = diff / 7 + 25; + if (ch > idleframes) + ch = idleframes; + idleframes -= ch; + cdda_pos += ch; + } + setstate (ciw, AUDIO_STATUS_IN_PROGRESS, cdda_pos); } - - setstate (ciw, AUDIO_STATUS_IN_PROGRESS, cdda_pos); } if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) { @@ -704,6 +705,11 @@ static void *cdda_play (void *v) while (ciw->cdda_paused && ciw->cdda_play == oldplay) sleep_millis(10); + if (cd_audio_mode_changed) { + restart = true; + goto end; + } + bufnum = 1 - bufnum; } @@ -712,16 +718,40 @@ end: if (mode) { ioctl_next_cd_audio_buffer_callback(-1); + if (restart) + audio_cda_new_buffer(NULL, -1, -1, NULL); } else { cda->wait (0); cda->wait (1); } ciw->subcodevalid = false; + cd_audio_mode_changed = false; delete cda; - ciw->cdda_play = 0; write_log (_T("IOCTL CDDA: thread killed\n")); + return restart; +} + +static void *cdda_play (void *v) +{ + int outpos = -1; + struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v; + cd_audio_mode_changed = false; + for (;;) { + if (!cdda_play2(ciw, &outpos)) { + break; + } + ciw->cdda_start = outpos; + if (ciw->cdda_start + 150 >= ciw->cdda_end) { + if (ciw->cdda_play >= 0) + setstate (ciw, AUDIO_STATUS_PLAY_COMPLETE, ciw->cdda_end + 1); + ciw->cdda_play = -1; + break; + } + ciw->cdda_play = 1; + } + ciw->cdda_play = 0; return NULL; } diff --git a/od-win32/cda_play.h b/od-win32/cda_play.h index fe5e948c..2b8faea0 100644 --- a/od-win32/cda_play.h +++ b/od-win32/cda_play.h @@ -3,6 +3,8 @@ #include #endif +extern volatile bool cd_audio_mode_changed; + class cda_audio { private: -- 2.47.3