From: David Griffith Date: Wed, 13 May 2015 21:03:19 +0000 (-0700) Subject: Don't allow multiple playaiff() threads. X-Git-Url: https://scope-eye.net/git/?a=commitdiff_plain;h=f8ec80629cfb8127ebd774c7351541f3f95242fb;p=liskon_frotz.git Don't allow multiple playaiff() threads. If there's already a playaiff() thread going when another playaiff() thread is to be started, tell the first one to stop and clean up, then join to it when it terminates before proceeding to start another playaiff() thread. This will cleanly handle a barrage of samples called to start in quick succession. For example, suppose your game has several buttons that make noises. Doing "PRESS GREEN BUTTON. PRESS BLUE BUTTON. PRESS RED BUTTON. PRESS YELLOW BUTTON" will not cause playaiff() to trip over itself. Instead all the samples will be played briefly except the one for the yellow button, which will play until the player does something else noisy at the next command prompt. What's actually heard is the last button noise. Such a reaction probably isn't desirable, but is well-within the responsibility of the game author to decide if and how AIFF samples will be allowed to stomp on one another. The business about allowing only one AIFF at a time and one OGG/MOD at a time, but mix the two comes from the fact that all other Z-machine emulators with audio capability behave this way. The Z-machine spec clearly says that only one sample (AIFF) may be played at once. I don't know where the idea that allowing an OGG/MOD to be mixed came from or who decided it was okay. The Blorb specs seem silent on the issue of having multiple AIFFs and OGG/MODs playing at once. --- diff --git a/src/curses/ux_audio.c b/src/curses/ux_audio.c index cf248dc..e299452 100644 --- a/src/curses/ux_audio.c +++ b/src/curses/ux_audio.c @@ -185,9 +185,12 @@ void os_start_sample (int number, int volume, int repeats, zword eos) myeffect.number = number; pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (blorb_map->chunks[resource.chunknum].type == bb_make_id('F','O','R','M')) { + if (bleep_playing) { + bleep_playing = FALSE; + pthread_join(playaiff_id, NULL); + } err = pthread_create(&playaiff_id, &attr, (void *) &playaiff, &myeffect); if (err != 0) { printf("Can't create playaiff thread :[%s]", strerror(err)); @@ -212,8 +215,9 @@ void os_start_sample (int number, int volume, int repeats, zword eos) */ void os_stop_sample (int number) { - if (bleep_playing && number == bleepnum) { - bleep_stop = TRUE; + if (bleep_playing && (number == bleepnum || number == 0)) { + bleep_playing = FALSE; + while(pthread_kill(playaiff_id, 0) == 0); } return; }/* os_stop_sample */ @@ -448,7 +452,7 @@ void *playaiff(EFFECT *raw_effect) while (1) { /* Check if we're being told to stop. */ - if (bleep_stop) break; + if (!bleep_playing) break; sem_wait(&audio_empty); pthread_mutex_lock(&mutex); @@ -504,13 +508,14 @@ void *playaiff(EFFECT *raw_effect) * Whichever, we need to clean up and terminate this thread. */ - bleep_stop = FALSE; bleep_playing = FALSE; fseek(myeffect.fp, filestart, SEEK_SET); sf_close(sndfile); + free(floatbuffer); + free(floatbuffer2); - pthread_exit((void*) raw_effect); + pthread_exit(NULL); }