Support on the fly audio mode change when CDA/FMV is playing.

This commit is contained in:
Toni Wilen 2017-08-13 15:25:17 +03:00
parent d88cb52dfc
commit d0be6591c4
5 changed files with 114 additions and 28 deletions

View File

@ -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;

View File

@ -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, &sector, 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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -3,6 +3,8 @@
#include <dsound.h>
#endif
extern volatile bool cd_audio_mode_changed;
class cda_audio
{
private: