From cae3199a24083df39fb6c67f4e205127e22648cf Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Mon, 5 Jan 2015 15:07:23 +0200 Subject: [PATCH] CD and FMV audio to Paula audio stream mixing support. --- audio.cpp | 165 ++++++++++++++++++++++++++++---- blkdev_cdimage.cpp | 95 ++++++++++++------ cd32_fmv.cpp | 161 +++++++++++++++++++++---------- custom.cpp | 7 +- include/audio.h | 8 +- include/cd32_fmv.h | 2 +- include/gensound.h | 1 + od-win32/blkdev_win32_ioctl.cpp | 101 +++++++++++++------ od-win32/sounddep/sound.h | 7 +- 9 files changed, 404 insertions(+), 143 deletions(-) diff --git a/audio.cpp b/audio.cpp index 84c69e26..1d9bc545 100644 --- a/audio.cpp +++ b/audio.cpp @@ -427,7 +427,7 @@ STATIC_INLINE void put_sound_word_right (uae_u32 w) right_word_saved[saved_ptr] = w; return; } - PUT_SOUND_WORD_RIGHT (w); + PUT_SOUND_WORD (w); } STATIC_INLINE void put_sound_word_left (uae_u32 w) @@ -448,10 +448,10 @@ STATIC_INLINE void put_sound_word_left (uae_u32 w) rold = right_word_saved[saved_ptr] - SOUND16_BASE_VAL; w = (lnew * mixed_mul2 + rold * mixed_mul1) / MIXED_STEREO_SCALE; - PUT_SOUND_WORD_LEFT (w); - PUT_SOUND_WORD_RIGHT (tmp); + PUT_SOUND_WORD (w); + PUT_SOUND_WORD (tmp); } else { - PUT_SOUND_WORD_LEFT (w); + PUT_SOUND_WORD (w); } } @@ -461,7 +461,7 @@ STATIC_INLINE void put_sound_word_right2 (uae_u32 w) right2_word_saved[saved_ptr2] = w; return; } - PUT_SOUND_WORD_RIGHT2 (w); + PUT_SOUND_WORD (w); } STATIC_INLINE void put_sound_word_left2 (uae_u32 w) @@ -482,10 +482,10 @@ STATIC_INLINE void put_sound_word_left2 (uae_u32 w) rold = right2_word_saved[saved_ptr2] - SOUND16_BASE_VAL; w = (lnew * mixed_mul2 + rold * mixed_mul1) / MIXED_STEREO_SCALE; - PUT_SOUND_WORD_LEFT2 (w); - PUT_SOUND_WORD_RIGHT2 (tmp); + PUT_SOUND_WORD (w); + PUT_SOUND_WORD (tmp); } else { - PUT_SOUND_WORD_LEFT2 (w); + PUT_SOUND_WORD (w); } } @@ -583,6 +583,14 @@ static void get_extra_channels(int *data1, int *data2, int sample1, int sample2) { int d1 = *data1 + sample1; int d2 = *data2 + sample2; + if (d1 < -32768) + d1 = -32768; + if (d1 > 32767) + d1 = 32767; + if (d2 < -32768) + d2 = -32768; + if (d2 > 32767) + d2 = 32767; int needswap = currprefs.sound_stereo_swap_paula ^ currprefs.sound_stereo_swap_ahi; if (needswap) { *data1 = d2; @@ -609,14 +617,28 @@ static void get_extra_channels_sample_mono(int *data1) { if (audio_extra_channels[0]) { int d1 = *data1 + audio_channel[AUDIO_CHANNEL_SNDBOARD_LEFT].current_sample; + if (d1 < -32768) + d1 = -32768; + if (d1 > 32767) + d1 = 32767; *data1 = d1; } if (audio_extra_channels[1]) { int d1 = *data1 + audio_channel[AUDIO_CHANNEL_CDA_LEFT].current_sample; + if (d1 < -32768) + d1 = -32768; + if (d1 > 32767) + d1 = 32767; *data1 = d1; } } +static void do_filter(int *data, int num) +{ + if (currprefs.sound_filter) + *data = filter (*data, &sound_filter_state[num]); +} + static void sample16i_sinc_handler (void) { int datas[4], data1; @@ -624,6 +646,11 @@ static void sample16i_sinc_handler (void) samplexx_sinc_handler (datas); data1 = datas[0] + datas[3] + datas[1] + datas[2]; data1 = FINISH_DATA (data1, 18); + + do_filter(&data1, 0); + + get_extra_channels_sample_mono(&data1); + set_sound_buffers (); PUT_SOUND_WORD_MONO (data1); check_sound_buffers (); @@ -651,6 +678,8 @@ void sample16_handler (void) data = SBASEVAL16(2) + data0; data = FINISH_DATA (data, 16); + do_filter(&data, 0); + get_extra_channels_sample_mono(&data); set_sound_buffers (); @@ -668,6 +697,8 @@ static void sample16i_anti_handler (void) data1 = datas[0] + datas[3] + datas[1] + datas[2]; data1 = FINISH_DATA (data1, 16); + do_filter(&data1, 0); + get_extra_channels_sample_mono(&data1); set_sound_buffers (); @@ -723,6 +754,8 @@ static void sample16i_rh_handler (void) data = SBASEVAL16(2) + data0; data = FINISH_DATA (data, 16); + do_filter(&data, 0); + get_extra_channels_sample_mono(&data); set_sound_buffers (); @@ -798,6 +831,8 @@ static void sample16i_crux_handler (void) data = SBASEVAL16(2) + data0; data = FINISH_DATA (data, 16); + do_filter(&data, 0); + get_extra_channels_sample_mono(&data); set_sound_buffers (); @@ -836,6 +871,11 @@ void sample16ss_handler (void) data2 = FINISH_DATA (data2, 14); data3 = FINISH_DATA (data3, 14); + do_filter(&data0, 0); + do_filter(&data1, 1); + do_filter(&data2, 3); + do_filter(&data3, 2); + get_extra_channels_sample(&data0, &data1); get_extra_channels_sample(&data2, &data3); @@ -863,6 +903,11 @@ void sample16ss_anti_handler (void) data2 = FINISH_DATA (datas[2], 14); data3 = FINISH_DATA (datas[3], 14); + do_filter(&data0, 0); + do_filter(&data1, 1); + do_filter(&data2, 3); + do_filter(&data3, 2); + get_extra_channels_sample(&data0, &data1); get_extra_channels_sample(&data3, &data2); @@ -886,6 +931,9 @@ static void sample16si_anti_handler (void) data1 = FINISH_DATA (data1, 15); data2 = FINISH_DATA (data2, 15); + do_filter(&data1, 0); + do_filter(&data2, 1); + get_extra_channels_sample(&data1, &data2); set_sound_buffers (); @@ -905,6 +953,11 @@ void sample16ss_sinc_handler (void) data2 = FINISH_DATA (datas[2], 16); data3 = FINISH_DATA (datas[3], 16); + do_filter(&data0, 0); + do_filter(&data1, 1); + do_filter(&data2, 3); + do_filter(&data3, 2); + get_extra_channels_sample(&data0, &data1); get_extra_channels_sample(&data3, &data2); @@ -928,6 +981,9 @@ static void sample16si_sinc_handler (void) data1 = FINISH_DATA (data1, 17); data2 = FINISH_DATA (data2, 17); + do_filter(&data1, 0); + do_filter(&data2, 1); + get_extra_channels_sample(&data1, &data2); set_sound_buffers (); @@ -959,6 +1015,9 @@ void sample16s_handler (void) data3 = SBASEVAL16(1) + data1; data3 = FINISH_DATA (data3, 15); + do_filter(&data2, 0); + do_filter(&data3, 1); + get_extra_channels_sample(&data2, &data3); set_sound_buffers (); @@ -1035,6 +1094,9 @@ static void sample16si_crux_handler (void) data3 = SBASEVAL16(1) + data1; data3 = FINISH_DATA (data3, 15); + do_filter(&data2, 0); + do_filter(&data3, 1); + get_extra_channels_sample(&data2, &data3); set_sound_buffers (); @@ -1092,6 +1154,9 @@ static void sample16si_rh_handler (void) data3 = SBASEVAL16(1) + data1; data3 = FINISH_DATA (data3, 15); + do_filter(&data2, 0); + do_filter(&data3, 1); + get_extra_channels_sample(&data2, &data3); set_sound_buffers (); @@ -1516,6 +1581,8 @@ static void audio_state_channel2 (int nr, bool perfin) } } +void audio_state_cda(void); + static void audio_state_channel (int nr, bool perfin) { struct audio_channel_data *cdp = audio_channel + nr; @@ -1524,8 +1591,8 @@ static void audio_state_channel (int nr, bool perfin) cdp->dat_written = false; } else if (nr == AUDIO_CHANNEL_SNDBOARD_LEFT || nr == AUDIO_CHANNEL_SNDBOARD_RIGHT) { audio_state_sndboard(nr - AUDIO_CHANNEL_SNDBOARD_LEFT); - } else { - audio_state_cda(nr - AUDIO_CHANNEL_CDA_LEFT); + } else if (nr == AUDIO_CHANNEL_CDA_LEFT) { + audio_state_cda(); } } @@ -1586,6 +1653,7 @@ static int sound_prefs_changed (void) || changed_prefs.sound_volume != currprefs.sound_volume || changed_prefs.sound_stereo_swap_paula != currprefs.sound_stereo_swap_paula || changed_prefs.sound_stereo_swap_ahi != currprefs.sound_stereo_swap_ahi + || changed_prefs.sound_cdaudio != currprefs.sound_cdaudio || changed_prefs.sound_filter != currprefs.sound_filter || changed_prefs.sound_filter_type != currprefs.sound_filter_type) return -1; @@ -1657,6 +1725,7 @@ void set_audio (void) currprefs.sound_filter = changed_prefs.sound_filter; currprefs.sound_filter_type = changed_prefs.sound_filter_type; currprefs.sound_volume = changed_prefs.sound_volume; + currprefs.sound_cdaudio = changed_prefs.sound_cdaudio; currprefs.sound_stereo_swap_paula = changed_prefs.sound_stereo_swap_paula; currprefs.sound_stereo_swap_ahi = changed_prefs.sound_stereo_swap_ahi; @@ -1869,7 +1938,7 @@ void audio_hsync (void) { if (!isaudio ()) return; - if (audio_work_to_do > 0 && currprefs.sound_auto + if (audio_work_to_do > 0 && currprefs.sound_auto && !audio_extra_channels[0] && !audio_extra_channels[1] #ifdef AVIOUTPUT && !avioutput_enabled #endif @@ -2182,33 +2251,35 @@ uae_u8 *save_audio (int nr, int *len, uae_u8 *dstptr) return dstbak; } +static void audio_set_extra_channels(void) +{ + audio_channel_count = audio_extra_channels[1] ? AUDIO_CHANNELS_PAULA + 4 : (audio_extra_channels[0] ? AUDIO_CHANNELS_PAULA + 2 : AUDIO_CHANNELS_PAULA); +} + void audio_enable_sndboard(bool enable) { struct audio_channel_data *acd = audio_channel + AUDIO_CHANNEL_SNDBOARD_LEFT; if (!enable) { - audio_channel_count = AUDIO_CHANNELS_PAULA; audio_extra_channels[0] = false; acd[1].evtime = acd->evtime = MAX_EV; } else { - audio_channel_count = AUDIO_CHANNELS_PAULA + 2; audio_extra_channels[0] = true; acd[1].evtime = acd->evtime = CYCLE_UNIT; } + audio_set_extra_channels(); } void audio_enable_cda(bool enable) { struct audio_channel_data *acd = audio_channel + AUDIO_CHANNEL_CDA_LEFT; if (!enable) { - audio_channel_count = AUDIO_CHANNELS_PAULA; audio_extra_channels[1] = false; acd[1].evtime = acd->evtime = MAX_EV; } else { - audio_channel_count = AUDIO_CHANNELS_PAULA + 4; audio_extra_channels[1] = true; acd[1].evtime = acd->evtime = CYCLE_UNIT; } - + audio_set_extra_channels(); } void audio_state_sndboard_state(int ch, int sample, unsigned int evt) @@ -2219,11 +2290,63 @@ void audio_state_sndboard_state(int ch, int sample, unsigned int evt) acd->evtime = evt; } -void audio_state_cda_state(int ch, int sample, unsigned int evt) +static uae_s16 *cda_bufptr; +static int cda_length, cda_userdata; +static unsigned int cda_evt; +static uae_s16 dummy_buffer[4] = { 0 }; +static CDA_CALLBACK cda_next_cd_audio_buffer_callback; +static int cda_volume[2]; + +void update_cda_sound(double clk) { - struct audio_channel_data *acd = audio_channel + AUDIO_CHANNEL_CDA_LEFT + ch; - acd->last_sample = acd->current_sample; - acd->current_sample = sample; - acd->evtime = evt; + cda_evt = clk * CYCLE_UNIT / 44100; +} + +void audio_cda_volume(int master, int left, int right) +{ + for (int j = 0; j < 2; j++) { + cda_volume[j] = j == 0 ? left : right; + cda_volume[j] = (100 - master) * cda_volume[j] / 100; + if (cda_volume[j]) + cda_volume[j]++; + if (cda_volume[j] >= 32768) + cda_volume[j] = 32768; + } +} + +void audio_cda_new_buffer(uae_s16 *buffer, int length, int userdata, CDA_CALLBACK next_cd_audio_buffer_callback) +{ + if (!buffer) { + cda_bufptr = dummy_buffer; + cda_length = 0; + } else { + cda_bufptr = buffer; + cda_length = length; + cda_userdata = userdata; + if (!audio_extra_channels[1]) + audio_enable_cda(true); + } + cda_next_cd_audio_buffer_callback = next_cd_audio_buffer_callback; + audio_activate(); } +static void audio_state_cda(void) +{ + if (cda_bufptr >= dummy_buffer && cda_bufptr <= dummy_buffer + 4) { + audio_enable_cda(false); + return; + } + struct audio_channel_data *acd = audio_channel + AUDIO_CHANNEL_CDA_LEFT; + acd->last_sample = acd->current_sample; + acd->current_sample = cda_bufptr[0] * cda_volume[0] / 32768; + acd->evtime = cda_evt; + acd++; + acd->last_sample = acd->current_sample; + acd->current_sample = cda_bufptr[1] * cda_volume[1] / 32768; + acd->evtime = cda_evt; + cda_bufptr += 2; + cda_length--; + if (cda_length <= 0 && cda_next_cd_audio_buffer_callback) { + cda_next_cd_audio_buffer_callback(cda_userdata); + } +} diff --git a/blkdev_cdimage.cpp b/blkdev_cdimage.cpp index b4f062bb..2138a339 100644 --- a/blkdev_cdimage.cpp +++ b/blkdev_cdimage.cpp @@ -27,6 +27,7 @@ #include "cda_play.h" #include "memory.h" #include "audio.h" +#include "uae.h" #ifdef RETROPLATFORM #include "rp.h" #endif @@ -109,6 +110,7 @@ static int bus_open; static volatile int cdimage_unpack_thread, cdimage_unpack_active; static smp_comm_pipe unpack_pipe; +static uae_sem_t play_sem; static struct cdunit *unitisopen (int unitnum) { @@ -417,42 +419,56 @@ static void audio_unpack (struct cdunit *cdu, struct cdtoc *t) // do this even if audio is not compressed, t->handle also could be // compressed and we want to unpack it in background too while (cdimage_unpack_active == 1) - Sleep (10); + sleep_millis(10); cdimage_unpack_active = 0; write_comm_pipe_u32 (&unpack_pipe, cdu - &cdunits[0], 0); write_comm_pipe_u32 (&unpack_pipe, t - &cdu->toc[0], 1); while (cdimage_unpack_active == 0) - Sleep (10); + sleep_millis(10); } -void audio_state_cda(int ch) +static volatile int cda_bufon[2]; +static cda_audio *cda; + +void next_cd_audio_buffer_callback(int bufnum) { - audio_state_cda_state(ch, 0, 0); + uae_sem_wait(&play_sem); + if (bufnum >= 0) { + cda_bufon[bufnum] = 0; + bufnum = 1 - bufnum; + if (cda_bufon[bufnum]) + audio_cda_new_buffer((uae_s16*)cda->buffers[bufnum], CDDA_BUFFERS * 2352 / 4, bufnum, next_cd_audio_buffer_callback); + else + bufnum = -1; + } + if (bufnum < 0) { + audio_cda_new_buffer(NULL, 0, -1, NULL); + } + uae_sem_post(&play_sem); } static void *cdda_play_func (void *v) { int cdda_pos; - int num_sectors = CDDA_BUFFERS; int bufnum; - int bufon[2]; int oldplay; int idleframes = 0; int silentframes = 0; bool foundsub; struct cdunit *cdu = (struct cdunit*)v; int oldtrack = -1; + int mode = currprefs.sound_cdaudio; cdu->thread_active = true; while (cdu->cdda_play == 0) - Sleep (10); + sleep_millis(10); oldplay = -1; - bufon[0] = bufon[1] = 0; + cda_bufon[0] = cda_bufon[1] = 0; bufnum = 0; - cda_audio *cda = new cda_audio (num_sectors, 2352, 44100); + cda = new cda_audio (CDDA_BUFFERS, 2352, 44100); while (cdu->cdda_play > 0) { @@ -486,7 +502,7 @@ static void *cdda_play_func (void *v) } idleframes = cdu->cdda_delay_frames; while (cdu->cdda_paused && cdu->cdda_play > 0) { - Sleep (10); + sleep_millis(10); idleframes = -1; } @@ -522,7 +538,7 @@ static void *cdda_play_func (void *v) 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 (-diff); + sleep_millis(-diff); setstate (cdu, AUDIO_STATUS_IN_PROGRESS); sector = cdda_pos; @@ -540,9 +556,15 @@ static void *cdda_play_func (void *v) } } - cda->wait(bufnum); - bufon[bufnum] = 0; - if (!cdu->cdda_play) + if (mode) { + while (cda_bufon[bufnum] && cdu->cdda_play > 0) + sleep_millis(10); + } else { + cda->wait(bufnum); + } + + cda_bufon[bufnum] = 0; + if (cdu->cdda_play <= 0) goto end; if (idleframes <= 0 && cdda_pos >= cdu->cdda_start && !isaudiotrack (&cdu->di.toc, cdda_pos)) { @@ -558,9 +580,9 @@ static void *cdda_play_func (void *v) gui_flicker_led (LED_CD, cdu->di.unitnum - 1, LED_CD_AUDIO); - memset (cda->buffers[bufnum], 0, num_sectors * 2352); + memset (cda->buffers[bufnum], 0, CDDA_BUFFERS * 2352); - for (cnt = 0; cnt < num_sectors && cdu->cdda_play > 0; cnt++) { + for (cnt = 0; cnt < CDDA_BUFFERS && cdu->cdda_play > 0; cnt++) { uae_u8 *dst = cda->buffers[bufnum] + cnt * 2352; uae_u8 subbuf[SUB_CHANNEL_SIZE]; sector = cdda_pos; @@ -628,7 +650,7 @@ static void *cdda_play_func (void *v) cdda_pos++; } - if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end) + if (cdda_pos - CDDA_BUFFERS < cdu->cdda_end && cdda_pos >= cdu->cdda_end) dofinish = 1; } @@ -636,12 +658,21 @@ static void *cdda_play_func (void *v) if (idleframes <= 0) cdu->cd_last_pos = cdda_pos; - bufon[bufnum] = 1; - cda->setvolume (currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, cdu->cdda_volume[0], cdu->cdda_volume[1]); - if (!cda->play (bufnum)) { - if (cdu->cdda_play > 0) - setstate (cdu, AUDIO_STATUS_PLAY_ERROR); - goto end; + if (mode) { + if (cda_bufon[0] == 0 && cda_bufon[1] == 0) { + cda_bufon[bufnum] = 1; + next_cd_audio_buffer_callback(1 - bufnum); + } + audio_cda_volume(currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, cdu->cdda_volume[0], cdu->cdda_volume[1]); + cda_bufon[bufnum] = 1; + } else { + cda_bufon[bufnum] = 1; + cda->setvolume (currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, cdu->cdda_volume[0], cdu->cdda_volume[1]); + if (!cda->play (bufnum)) { + if (cdu->cdda_play > 0) + setstate (cdu, AUDIO_STATUS_PLAY_ERROR); + goto end; + } } if (dofinish) { @@ -653,20 +684,24 @@ static void *cdda_play_func (void *v) } - if (bufon[0] == 0 && bufon[1] == 0) { + if (cda_bufon[0] == 0 && cda_bufon[1] == 0) { while (cdu->cdda_paused && cdu->cdda_play == oldplay) - Sleep (10); + sleep_millis(10); } bufnum = 1 - bufnum; } end: - cda->wait (0); - cda->wait (1); + if (mode) { + next_cd_audio_buffer_callback(-1); + } else { + cda->wait (0); + cda->wait (1); + } while (cdimage_unpack_active == 1) - Sleep (10); + sleep_millis(10); delete cda; @@ -682,7 +717,7 @@ static void cdda_stop (struct cdunit *cdu) if (cdu->cdda_play != 0) { cdu->cdda_play = -1; while (cdu->cdda_play && cdu->thread_active) { - Sleep (10); + sleep_millis(10); } cdu->cdda_play = 0; } @@ -1977,6 +2012,7 @@ static void close_bus (void) cdu->enabled = false; } bus_open = 0; + uae_sem_destroy(&play_sem); write_log (_T("IMAGE driver closed.\n")); } @@ -1987,6 +2023,7 @@ static int open_bus (int flags) return 1; } bus_open = 1; + uae_sem_init(&play_sem, 0, 1); write_log (_T("Image driver open.\n")); return 1; } diff --git a/cd32_fmv.cpp b/cd32_fmv.cpp index 8afa6dff..a648cda7 100644 --- a/cd32_fmv.cpp +++ b/cd32_fmv.cpp @@ -20,6 +20,8 @@ #include "uae.h" #include "debug.h" #include "custom.h" +#include "audio.h" +#include "threaddep/thread.h" #include "cda_play.h" #include "archivers/mp2/kjmp2.h" @@ -221,6 +223,10 @@ static uae_u16 cl450_threshold; static int cl450_buffer_offset; static int cl450_buffer_empty_cnt; static int libmpeg_offset; +static bool audio_mode; +static uae_sem_t play_sem; +static volatile bool fmv_bufon[2]; +static double fmv_syncadjust; struct cl450_videoram { @@ -388,8 +394,13 @@ static void l64111_setvolume(void) if (!pcmaudio) return; write_log(_T("L64111 mute %d\n"), volume ? 0 : 1); - if (cda) - cda->setvolume(currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, volume, volume); + if (cda) { + if (audio_mode) { + audio_cda_volume(currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, volume, volume); + } else { + cda->setvolume(currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, volume, volume); + } + } } static int l64111_get_frame(uae_u8 *data, int remaining) @@ -979,6 +990,7 @@ static void cl450_newcmd(void) { case CL_Play: cl450_play = 1; + audio_mode = currprefs.sound_cdaudio; write_log(_T("CL450 PLAY\n")); break; case CL_Pause: @@ -1044,6 +1056,7 @@ static void cl450_newcmd(void) case CL_Reset: write_log(_T("CL450 Reset\n")); cl450_reset_cmd(); + audio_mode = currprefs.sound_cdaudio; break; case CL_FlushBitStream: write_log(_T("CL450 CL_FlushBitStream\n")); @@ -1356,59 +1369,34 @@ static void REGPARAM2 fmv_bput (uaecptr addr, uae_u32 w) static double max_sync_vpos; static double remaining_sync_vpos; -void cd32_fmv_set_sync(double svpos) +void cd32_fmv_set_sync(double svpos, double adjust) { - max_sync_vpos = svpos; + max_sync_vpos = svpos / adjust; + fmv_syncadjust = adjust; } -void cd32_fmv_hsync_handler(void) +void fmv_next_cd_audio_buffer_callback(int bufnum) { - if (!fmv_ram_bank.baseaddr) - return; - - if (cl450_play > 0) - cl450_scr += 90000.0 / hblank_hz; - - if (cl450_video_hsync_wait > 0) - cl450_video_hsync_wait--; - if (cl450_video_hsync_wait == 0) { - cl450_set_status(CL_INT_PIC_D); - if (cl450_videoram_cnt > 0) { - cd32_fmv_new_image(videoram[cl450_videoram_read].width, videoram[cl450_videoram_read].height, - videoram[cl450_videoram_read].depth, cl450_blank ? NULL : videoram[cl450_videoram_read].data); - cl450_videoram_read++; - cl450_videoram_read &= CL450_VIDEO_BUFFERS - 1; - cl450_videoram_cnt--; - } - cl450_video_hsync_wait = max_sync_vpos; - while (remaining_sync_vpos >= 1.0) { - cl450_video_hsync_wait++; - remaining_sync_vpos -= 1.0; - } - remaining_sync_vpos += max_sync_vpos - cl450_video_hsync_wait; - if (cl450_frame_rate < 40) - cl450_video_hsync_wait *= 2; + uae_sem_wait(&play_sem); + if (bufnum >= 0) { + fmv_bufon[bufnum] = 0; + bufnum = 1 - bufnum; + if (fmv_bufon[bufnum]) + audio_cda_new_buffer((uae_s16*)cda->buffers[bufnum], PCM_SECTORS * KJMP2_SAMPLES_PER_FRAME, bufnum, fmv_next_cd_audio_buffer_callback); + else + bufnum = -1; } - - if (vpos & 7) - return; - - if (cl450_play > 0) { - if (cl450_newpacket_mode && cl450_buffer_offset < cl450_threshold) { - int newpacket_len = 0; - for (int i = 0; i < CL450_NEWPACKET_BUFFER_SIZE; i++) - newpacket_len += cl450_newpacket_buffer[i].length; - if (cl450_buffer_offset >= newpacket_len - 6) - cl450_set_status(CL_INT_RDY); - } - - if (cl450_buffer_offset >= 512 && cl450_videoram_cnt < CL450_VIDEO_BUFFERS - 1) { - cl450_parse_frame(); - } + if (bufnum < 0) { + audio_cda_new_buffer(NULL, 0, -1, NULL); } + uae_sem_post(&play_sem); } void cd32_fmv_vsync_handler(void) +{ +} + +static void cd32_fmv_audio_handler(void) { int bufnum; int offset, needsectors; @@ -1426,11 +1414,15 @@ void cd32_fmv_vsync_handler(void) cl450_buffer_empty_cnt = 0; } - if (!cda || !(l64111_regs[A_CONTROL1] & 1)) return; - play0 = cda->isplaying(0); - play1 = cda->isplaying(1); + if (audio_mode) { + play0 = fmv_bufon[0]; + play1 = fmv_bufon[1]; + } else { + play0 = cda->isplaying(0); + play1 = cda->isplaying(1); + } needsectors = PCM_SECTORS; if (!play0 && !play1) { needsectors *= 2; @@ -1454,13 +1446,72 @@ void cd32_fmv_vsync_handler(void) memcpy(cda->buffers[bufnum] + i * KJMP2_SAMPLES_PER_FRAME * 4, pcmaudio[offset2].pcm, KJMP2_SAMPLES_PER_FRAME * 4); pcmaudio[offset2].ready = false; } - cda->play(bufnum); + if (audio_mode) { + if (!play0 && !play1) { + fmv_bufon[bufnum] = 1; + fmv_next_cd_audio_buffer_callback(1 - bufnum); + } + fmv_bufon[bufnum] = 1; + } else { + cda->play(bufnum); + } offset += PCM_SECTORS; offset &= l64111_cb_mask; l64111_regs[A_CB_READ] = offset; l64111_regs[A_CB_STATUS] -= PCM_SECTORS; } +void cd32_fmv_hsync_handler(void) +{ + if (!fmv_ram_bank.baseaddr) + return; + + if (cl450_play > 0) + cl450_scr += 90000.0 / (hblank_hz / fmv_syncadjust); + + if (cl450_video_hsync_wait > 0) + cl450_video_hsync_wait--; + if (cl450_video_hsync_wait == 0) { + cl450_set_status(CL_INT_PIC_D); + if (cl450_videoram_cnt > 0) { + cd32_fmv_new_image(videoram[cl450_videoram_read].width, videoram[cl450_videoram_read].height, + videoram[cl450_videoram_read].depth, cl450_blank ? NULL : videoram[cl450_videoram_read].data); + cl450_videoram_read++; + cl450_videoram_read &= CL450_VIDEO_BUFFERS - 1; + cl450_videoram_cnt--; + } + cl450_video_hsync_wait = max_sync_vpos; + while (remaining_sync_vpos >= 1.0) { + cl450_video_hsync_wait++; + remaining_sync_vpos -= 1.0; + } + remaining_sync_vpos += max_sync_vpos - cl450_video_hsync_wait; + if (cl450_frame_rate < 40) + cl450_video_hsync_wait *= 2; + } + + if ((vpos & 63) == 0) + cd32_fmv_audio_handler(); + + if (vpos & 7) + return; + + if (cl450_play > 0) { + if (cl450_newpacket_mode && cl450_buffer_offset < cl450_threshold) { + int newpacket_len = 0; + for (int i = 0; i < CL450_NEWPACKET_BUFFER_SIZE; i++) + newpacket_len += cl450_newpacket_buffer[i].length; + if (cl450_buffer_offset >= newpacket_len - 6) + cl450_set_status(CL_INT_RDY); + } + + if (cl450_buffer_offset >= 512 && cl450_videoram_cnt < CL450_VIDEO_BUFFERS - 1) { + cl450_parse_frame(); + } + } +} + + void cd32_fmv_reset(void) { if (fmv_ram_bank.baseaddr) @@ -1477,11 +1528,16 @@ void cd32_fmv_free(void) xfree(videoram); videoram = NULL; if (cda) { - cda->wait(0); - cda->wait(1); + if (audio_mode) { + fmv_next_cd_audio_buffer_callback(-1); + } else { + cda->wait(0); + cda->wait(1); + } delete cda; } cda = NULL; + uae_sem_destroy(&play_sem); xfree(pcmaudio); pcmaudio = NULL; if (mpeg_decoder) @@ -1550,6 +1606,7 @@ addrbank *cd32_fmv_init (uaecptr start) map_banks(&fmv_rom_bank, (fmv_start + ROM_BASE) >> 16, fmv_rom_size >> 16, 0); map_banks(&fmv_ram_bank, (fmv_start + RAM_BASE) >> 16, fmv_ram_size >> 16, 0); map_banks(&fmv_bank, (fmv_start + IO_BASE) >> 16, (RAM_BASE - IO_BASE) >> 16, 0); + uae_sem_init(&play_sem, 0, 1); cd32_fmv_reset(); return &fmv_rom_bank; } diff --git a/custom.cpp b/custom.cpp index 947af5d2..20ca6d6a 100644 --- a/custom.cpp +++ b/custom.cpp @@ -3506,11 +3506,13 @@ void compute_vsynctime (void) { double svpos = maxvpos_nom; double shpos = maxhpos_short; + double syncadjust = 1.0; fake_vblank_hz = 0; vblank_hz_mult = 0; vblank_hz_state = 1; if (fabs (currprefs.chipset_refreshrate) > 0.1) { + syncadjust = currprefs.chipset_refreshrate / vblank_hz_nom; vblank_hz = currprefs.chipset_refreshrate; if (isvsync_chipset ()) { int mult = 0; @@ -3544,9 +3546,10 @@ void compute_vsynctime (void) double clk = svpos * shpos * fake_vblank_hz; //write_log (_T("SNDRATE %.1f*%.1f*%.6f=%.6f\n"), svpos, shpos, fake_vblank_hz, clk); update_sound (clk); - update_sndboard_sound (clk); + update_sndboard_sound (clk / syncadjust); + update_cda_sound(clk / syncadjust); } - cd32_fmv_set_sync(svpos); + cd32_fmv_set_sync(svpos, syncadjust); } diff --git a/include/audio.h b/include/audio.h index 8f438a9f..4228f74e 100644 --- a/include/audio.h +++ b/include/audio.h @@ -34,6 +34,7 @@ extern void audio_evhandler (void); extern void audio_hsync (void); extern void audio_update_adkmasks (void); extern void update_sound (double clk); +extern void update_cda_sound (double clk); extern void led_filter_audio (void); extern void set_audio (void); extern int audio_activate (void); @@ -49,10 +50,9 @@ extern void audio_enable_sndboard(bool); extern void audio_state_sndboard(int); extern void audio_state_sndboard_state(int, int, unsigned int); -extern void audio_update_cda(unsigned int); -extern void audio_enable_cda(bool); -extern void audio_state_cda(int); -extern void audio_state_cda_state(int, int, unsigned int); +typedef void (*CDA_CALLBACK)(int); +extern void audio_cda_new_buffer(uae_s16 *buffer, int length, int userdata, CDA_CALLBACK next_cd_audio_buffer_callback); +extern void audio_cda_volume(int master, int left, int right); #define AUDIO_CHANNELS_PAULA 4 #define AUDIO_CHANNELS_MAX 8 diff --git a/include/cd32_fmv.h b/include/cd32_fmv.h index ea57d2f9..c54d9a6d 100644 --- a/include/cd32_fmv.h +++ b/include/cd32_fmv.h @@ -10,6 +10,6 @@ extern void cd32_fmv_state(int state); extern void cd32_fmv_new_image(int, int, int, uae_u8*); extern void cd32_fmv_genlock(struct vidbuffer*, struct vidbuffer*); extern void cd32_fmv_new_border_color(uae_u32); -extern void cd32_fmv_set_sync(double svpos); +extern void cd32_fmv_set_sync(double svpos, double adjust); extern int cd32_fmv_active; diff --git a/include/gensound.h b/include/gensound.h index 94f211e6..4be557e2 100644 --- a/include/gensound.h +++ b/include/gensound.h @@ -13,6 +13,7 @@ extern void (*sample_handler) (void); /* sample_evtime is in normal Amiga cycles; scaled_sample_evtime is in our event cycles. */ extern float scaled_sample_evtime; +extern float scaled_sample_evtime_orig; /* Determine if we can produce any sound at all. This can be only a guess; * if unsure, say yes. Any call to init_sound may change the value. */ diff --git a/od-win32/blkdev_win32_ioctl.cpp b/od-win32/blkdev_win32_ioctl.cpp index 393c8764..50e3e2d1 100644 --- a/od-win32/blkdev_win32_ioctl.cpp +++ b/od-win32/blkdev_win32_ioctl.cpp @@ -21,6 +21,7 @@ #include "scsidev.h" #include "gui.h" #include "win32.h" +#include "audio.h" #include #include @@ -76,6 +77,7 @@ struct dev_info_ioctl { static struct dev_info_ioctl ciw32[MAX_TOTAL_SCSI_DEVICES]; static int unittable[MAX_TOTAL_SCSI_DEVICES]; static int bus_open; +static uae_sem_t play_sem; static void seterrormode (struct dev_info_ioctl *ciw) { @@ -480,36 +482,60 @@ static int setstate (struct dev_info_ioctl *ciw, int state) return 0; } +static cda_audio *cda; +static volatile int cda_bufon[2]; + +void ioctl_next_cd_audio_buffer_callback(int bufnum) +{ + uae_sem_wait(&play_sem); + if (bufnum >= 0) { + cda_bufon[bufnum] = 0; + bufnum = 1 - bufnum; + if (cda_bufon[bufnum]) + audio_cda_new_buffer((uae_s16*)cda->buffers[bufnum], CDDA_BUFFERS * 2352 / 4, bufnum, ioctl_next_cd_audio_buffer_callback); + else + bufnum = -1; + } + if (bufnum < 0) { + audio_cda_new_buffer(NULL, 0, -1, NULL); + } + uae_sem_post(&play_sem); +} + static void *cdda_play (void *v) { struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v; int cdda_pos; - int num_sectors = CDDA_BUFFERS; int bufnum; int buffered; - int bufon[2]; int i; int oldplay; int idleframes; int muteframes; int readblocksize = 2352 + 96; + int mode = currprefs.sound_cdaudio; while (ciw->cdda_play == 0) - Sleep (10); + sleep_millis(10); oldplay = -1; - bufon[0] = bufon[1] = 0; + cda_bufon[0] = cda_bufon[1] = 0; bufnum = 0; buffered = 0; - cda_audio *cda = new cda_audio (num_sectors, 2352, 44100); + cda = new cda_audio (CDDA_BUFFERS, 2352, 44100); while (ciw->cdda_play > 0) { - cda->wait(bufnum); + if (mode) { + while (cda_bufon[bufnum] && ciw->cdda_play > 0) + sleep_millis(10); + } else { + cda->wait(bufnum); + } if (ciw->cdda_play <= 0) goto end; - bufon[bufnum] = 0; + cda_bufon[bufnum] = 0; if (oldplay != ciw->cdda_play) { idleframes = 0; @@ -525,12 +551,12 @@ static void *cdda_play (void *v) ciw->subcodevalid = false; idleframes = ciw->cdda_delay_frames; while (ciw->cdda_paused && ciw->cdda_play > 0) { - Sleep (10); + sleep_millis(10); idleframes = -1; } // force spin up if (isaudiotrack (&ciw->di.toc, cdda_pos)) - read_block (ciw, -1, cda->buffers[bufnum], cdda_pos, num_sectors, readblocksize); + read_block (ciw, -1, cda->buffers[bufnum], cdda_pos, CDDA_BUFFERS, readblocksize); if (!isaudiotrack (&ciw->di.toc, cdda_pos - 150)) muteframes = 75; @@ -566,7 +592,7 @@ static void *cdda_play (void *v) 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 (-diff); + sleep_millis(-diff); if (diff > 0 && !seensub) { int ch = diff / 7 + 25; if (ch > idleframes) @@ -592,21 +618,21 @@ static void *cdda_play (void *v) ciw->subcodevalid = false; memset (ciw->subcode, 0, sizeof ciw->subcode); - memset (cda->buffers[bufnum], 0, num_sectors * readblocksize); + memset (cda->buffers[bufnum], 0, CDDA_BUFFERS * readblocksize); if (cdda_pos >= 0) { - if (read_block (ciw, -1, cda->buffers[bufnum], cdda_pos, num_sectors, readblocksize)) { - for (i = 0; i < num_sectors; i++) { + if (read_block (ciw, -1, cda->buffers[bufnum], cdda_pos, CDDA_BUFFERS, readblocksize)) { + for (i = 0; i < CDDA_BUFFERS; i++) { memcpy (ciw->subcode + i * SUB_CHANNEL_SIZE, cda->buffers[bufnum] + readblocksize * i + 2352, SUB_CHANNEL_SIZE); } - for (i = 1; i < num_sectors; i++) { + for (i = 1; i < CDDA_BUFFERS; i++) { memmove (cda->buffers[bufnum] + 2352 * i, cda->buffers[bufnum] + readblocksize * i, 2352); } ciw->subcodevalid = true; } } - for (i = 0; i < num_sectors; i++) { + for (i = 0; i < CDDA_BUFFERS; i++) { if (muteframes > 0) { memset (cda->buffers[bufnum] + 2352 * i, 0, 2352); muteframes--; @@ -623,36 +649,45 @@ static void *cdda_play (void *v) ciw->subcodevalid = false; if (ciw->cdda_subfunc) - ciw->cdda_subfunc (ciw->subcode, num_sectors); + ciw->cdda_subfunc (ciw->subcode, CDDA_BUFFERS); uae_sem_post (&ciw->sub_sem); if (ciw->subcodevalid) { uae_sem_wait (&ciw->sub_sem2); - memcpy (ciw->subcodebuf, ciw->subcode + (num_sectors - 1) * SUB_CHANNEL_SIZE, SUB_CHANNEL_SIZE); + memcpy (ciw->subcodebuf, ciw->subcode + (CDDA_BUFFERS - 1) * SUB_CHANNEL_SIZE, SUB_CHANNEL_SIZE); uae_sem_post (&ciw->sub_sem2); } - bufon[bufnum] = 1; - cda->setvolume (currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, ciw->cdda_volume[0], ciw->cdda_volume[1]); - if (!cda->play (bufnum)) { - setstate (ciw, AUDIO_STATUS_PLAY_ERROR); - goto end; // data track? + if (mode) { + if (cda_bufon[0] == 0 && cda_bufon[1] == 0) { + cda_bufon[bufnum] = 1; + ioctl_next_cd_audio_buffer_callback(1 - bufnum); + } + audio_cda_volume(currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, ciw->cdda_volume[0], ciw->cdda_volume[1]); + cda_bufon[bufnum] = 1; + } else { + cda_bufon[bufnum] = 1; + cda->setvolume (currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, ciw->cdda_volume[0], ciw->cdda_volume[1]); + if (!cda->play (bufnum)) { + setstate (ciw, AUDIO_STATUS_PLAY_ERROR); + goto end; // data track? + } } if (ciw->cdda_scan) { - cdda_pos += ciw->cdda_scan * num_sectors; + cdda_pos += ciw->cdda_scan * CDDA_BUFFERS; if (cdda_pos < 0) cdda_pos = 0; } else { - if (cdda_pos < 0 && cdda_pos + num_sectors >= 0) + if (cdda_pos < 0 && cdda_pos + CDDA_BUFFERS >= 0) cdda_pos = 0; else - cdda_pos += num_sectors; + cdda_pos += CDDA_BUFFERS; } if (idleframes <= 0) { - if (cdda_pos - num_sectors < ciw->cdda_end && cdda_pos >= ciw->cdda_end) { + if (cdda_pos - CDDA_BUFFERS < ciw->cdda_end && cdda_pos >= ciw->cdda_end) { setstate (ciw, AUDIO_STATUS_PLAY_COMPLETE); ciw->cdda_play_finished = 1; ciw->cdda_play = -1; @@ -663,13 +698,21 @@ static void *cdda_play (void *v) } while (ciw->cdda_paused && ciw->cdda_play == oldplay) - Sleep (10); + sleep_millis(10); bufnum = 1 - bufnum; } end: + + if (mode) { + ioctl_next_cd_audio_buffer_callback(-1); + } else { + cda->wait (0); + cda->wait (1); + } + ciw->subcodevalid = false; delete cda; @@ -683,7 +726,7 @@ static void cdda_stop (struct dev_info_ioctl *ciw) if (ciw->cdda_play != 0) { ciw->cdda_play = -1; while (ciw->cdda_play) { - Sleep (10); + sleep_millis(10); } } ciw->cdda_play_finished = 0; @@ -1427,6 +1470,7 @@ static void close_bus (void) unittable[i] = 0; } bus_open = 0; + uae_sem_destroy(&play_sem); write_log (_T("IOCTL driver closed.\n")); } @@ -1467,6 +1511,7 @@ static int open_bus (int flags) dwDriveMask >>= 1; } bus_open = 1; + uae_sem_init(&play_sem, 0, 1); write_log (_T("IOCTL driver open, %d devices.\n"), total_devices); return total_devices; } diff --git a/od-win32/sounddep/sound.h b/od-win32/sounddep/sound.h index aff844c7..0d91b004 100644 --- a/od-win32/sounddep/sound.h +++ b/od-win32/sounddep/sound.h @@ -129,12 +129,7 @@ STATIC_INLINE void clear_sound_buffers (void) } #define PUT_SOUND_WORD(b) do { *(uae_u16 *)paula_sndbufpt = b; paula_sndbufpt = (uae_u16 *)(((uae_u8 *)paula_sndbufpt) + 2); } while (0) -#define PUT_SOUND_WORD_LEFT(b) do { if (currprefs.sound_filter) b = filter (b, &sound_filter_state[0]); PUT_SOUND_WORD(b); } while (0) -#define PUT_SOUND_WORD_RIGHT(b) do { if (currprefs.sound_filter) b = filter (b, &sound_filter_state[1]); PUT_SOUND_WORD(b); } while (0) -#define PUT_SOUND_WORD_LEFT2(b) do { if (currprefs.sound_filter) b = filter (b, &sound_filter_state[2]); PUT_SOUND_WORD(b); } while (0) -#define PUT_SOUND_WORD_RIGHT2(b) do { if (currprefs.sound_filter) b = filter (b, &sound_filter_state[3]); PUT_SOUND_WORD(b); } while (0) - -#define PUT_SOUND_WORD_MONO(b) PUT_SOUND_WORD_LEFT(b) +#define PUT_SOUND_WORD_MONO(b) PUT_SOUND_WORD(b) #define SOUND16_BASE_VAL 0 #define SOUND8_BASE_VAL 128 -- 2.47.3