static int sleep_until_start_request_or_inactivity() { SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > ENTER"); int a_start_is_required=0; // Wait for the start request (my_sem_start_is_required). // Besides this, if the audio stream is still busy, // check from time to time its end. // The end of the stream is confirmed by several checks // for filtering underflow. // int i=0; while((i<= MAX_INACTIVITY_CHECK) && !a_start_is_required) { if (wave_is_busy( NULL) ) { i = 0; } else { i++; } int err=0; struct timespec ts; struct timeval tv; clock_gettime2( &ts); #ifdef DEBUG_ENABLED struct timespec to; to.tv_sec = ts.tv_sec; to.tv_nsec = ts.tv_nsec; #endif add_time_in_ms( &ts, INACTIVITY_TIMEOUT); SHOW("fifo > sleep_until_start_request_or_inactivity > start sem_timedwait (start_is_required) from %d.%09lu to %d.%09lu \n", to.tv_sec, to.tv_nsec, ts.tv_sec, ts.tv_nsec); while ((err = sem_timedwait(&my_sem_start_is_required, &ts)) == -1 && errno == EINTR) { continue; } assert (gettimeofday(&tv, NULL) != -1); SHOW("fifo > sleep_until_start_request_or_inactivity > stop sem_timedwait (start_is_required, err=%d) %d.%09lu \n", err, tv.tv_sec, tv.tv_usec*1000); if (err==0) { a_start_is_required = 1; } } SHOW_TIME("fifo > sleep_until_start_request_or_inactivity > LEAVE"); return a_start_is_required; }
ESPEAK_API int espeak_IsPlaying(void) {//================================== // ENTER("espeak_IsPlaying"); #ifdef USE_ASYNC if((my_mode == AUDIO_OUTPUT_PLAYBACK) && wave_is_busy(my_audio)) return(1); return(fifo_is_busy()); #else return(0); #endif } // end of espeak_IsPlaying
static int get_remaining_time(uint32_t sample, uint32_t* time_in_ms, int* stop_is_required) { ENTER("get_remaining_time"); int err = 0; *stop_is_required = 0; int i=0; for (i=0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++) { err = wave_get_remaining_time( sample, time_in_ms); if (err || wave_is_busy(NULL) || (*time_in_ms == 0)) { // if err, stream not available: quit // if wave is busy, time_in_ms is known: quit // if wave is not busy but remaining time == 0, event is reached: quit break; } // stream opened but not active // // Several possible states: // * the stream is opened but not yet started: // // wait for the start of stream // // * some samples have already been played, // ** the end of stream is reached // ** or there is an underrun // // wait for the close of stream *stop_is_required = sleep_until_timeout_or_stop_request( ACTIVITY_TIMEOUT); } return err; }
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) { ENTER("wave_write"); size_t bytes_written = 0; // space in ringbuffer for the sample needed: 1x mono channel but 2x for 1 stereo channel size_t bytes_to_write = (out_channels==1) ? theSize : theSize*2; my_stream_could_start = 0; if(pa_stream == NULL) { SHOW_TIME("wave_write > wave_open_sound\n"); if (0 != wave_open_sound()) { SHOW_TIME("wave_write > wave_open_sound fails!"); return 0; } my_stream_could_start=1; } else if (!wave_is_busy(NULL)) { my_stream_could_start = 1; } assert(BUFFER_LENGTH >= bytes_to_write); if (myWrite >= myBuffer + BUFFER_LENGTH) { myWrite = myBuffer; } // end if (myWrite >= myBuffer + BUFFER_LENGTH) size_t aTotalFreeMem=0; char* aRead = myRead; SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite); while (1) { if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) { SHOW_TIME("wave_write > my_callback_is_output_enabled: no!"); return 0; } aRead = myRead; // write pointer is before read pointer? if (myWrite >= aRead) { aTotalFreeMem = aRead + BUFFER_LENGTH - myWrite; } else // read pointer is before write pointer! { aTotalFreeMem = aRead - myWrite; } // end if (myWrite >= aRead) if (aTotalFreeMem>1) { // -1 because myWrite must be different of aRead // otherwise buffer would be considered as empty aTotalFreeMem -= 1; } // end if (aTotalFreeMem>1) if (aTotalFreeMem >= bytes_to_write) { break; } // end if (aTotalFreeMem >= bytes_to_write) //SHOW_TIME("wave_write > wait"); SHOW("wave_write > wait: aTotalFreeMem=%d\n", aTotalFreeMem); SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite); usleep(10000); } // end while (1) aRead = myRead; // write pointer is ahead the read pointer? if (myWrite >= aRead) { SHOW_TIME("wave_write > myWrite >= aRead"); // determine remaining free memory to the end of the ringbuffer size_t aFreeMem = myBuffer + BUFFER_LENGTH - myWrite; // is enough linear space available (regardless 1 or 2 channels)? if (aFreeMem >= bytes_to_write) { // copy direct - no wrap around at end of ringbuffer needed myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize); } else // not enough linear space available { // 2 channels (stereo)? if (out_channels == 2) { // copy with wrap around at the end of ringbuffer copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem/2); myWrite = myBuffer; myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem/2, theSize - aFreeMem/2); } else // 1 channel (mono) { // copy with wrap around at the end of ringbuffer copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem); myWrite = myBuffer; myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem, theSize - aFreeMem); } // end if (out_channels == 2) } // end if (aFreeMem >= bytes_to_write) } // if (myWrite >= aRead) else // read pointer is ahead the write pointer { SHOW_TIME("wave_write > myWrite <= aRead"); myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize); } // end if (myWrite >= aRead) bytes_written = bytes_to_write; myWritePosition += theSize/sizeof(uint16_t); // add number of samples if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER)) { start_stream(); } // end if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER)) SHOW_TIME("wave_write > LEAVE"); return bytes_written; }