From da6b6c2dd790a1a6f1702efe1b075b09ec76fb48 Mon Sep 17 00:00:00 2001 From: lonesurvivor Date: Tue, 3 Jan 2017 19:00:31 +0100 Subject: Fix for the huge audio latency of the SamplePlayer (>200 ms) - fixes PulseAudio, ALSA and RtAudio driver - cleans up the driver files for better readability (mostly whitespace-related stuff) - makes ALSA and Pulseaudio actually use the global setting "audio/mix_rate" for the sample rate instead of a fixed value (RtAudio did this already) --- drivers/alsa/audio_driver_alsa.cpp | 50 +++++++++++++++----------------------- drivers/alsa/audio_driver_alsa.h | 1 + 2 files changed, 20 insertions(+), 31 deletions(-) (limited to 'drivers/alsa') diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 9895a10007..b026241579 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -45,7 +45,7 @@ Error AudioDriverALSA::init() { samples_in = NULL; samples_out = NULL; - mix_rate = 44100; + mix_rate = GLOBAL_DEF("audio/mix_rate",44100); output_format = OUTPUT_STEREO; channels = 2; @@ -70,67 +70,62 @@ Error AudioDriverALSA::init() { ERR_FAIL_COND_V( status<0, ERR_CANT_OPEN ); snd_pcm_hw_params_alloca(&hwparams); - status = snd_pcm_hw_params_any(pcm_handle, hwparams); + status = snd_pcm_hw_params_any(pcm_handle, hwparams); CHECK_FAIL( status<0 ); status = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); - CHECK_FAIL( status<0 ); //not interested in anything else status = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE); - CHECK_FAIL( status<0 ); //todo: support 4 and 6 status = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2); - CHECK_FAIL( status<0 ); status = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &mix_rate, NULL); - - CHECK_FAIL( status<0 ); int latency = GLOBAL_DEF("audio/output_latency",25); buffer_size = nearest_power_of_2( latency * mix_rate / 1000 ); - status = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &buffer_size, NULL); - + // set buffer size from project settings + status = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size); + CHECK_FAIL( status<0 ); + // make period size 1/8 + period_size = buffer_size >> 3; + status = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &period_size, NULL); CHECK_FAIL( status<0 ); unsigned int periods=2; status = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &periods, NULL); - CHECK_FAIL( status<0 ); status = snd_pcm_hw_params(pcm_handle,hwparams); - CHECK_FAIL( status<0 ); //snd_pcm_hw_params_free(&hwparams); snd_pcm_sw_params_alloca(&swparams); + status = snd_pcm_sw_params_current(pcm_handle, swparams); CHECK_FAIL( status<0 ); - status = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, buffer_size); - + status = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, period_size); CHECK_FAIL( status<0 ); status = snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 1); - CHECK_FAIL( status<0 ); status = snd_pcm_sw_params(pcm_handle, swparams); - CHECK_FAIL( status<0 ); - samples_in = memnew_arr(int32_t, buffer_size*channels); - samples_out = memnew_arr(int16_t, buffer_size*channels); + samples_in = memnew_arr(int32_t, period_size*channels); + samples_out = memnew_arr(int16_t, period_size*channels); snd_pcm_nonblock(pcm_handle, 0); @@ -144,36 +139,28 @@ void AudioDriverALSA::thread_func(void* p_udata) { AudioDriverALSA* ad = (AudioDriverALSA*)p_udata; - while (!ad->exit_thread) { - - if (!ad->active) { - - for (unsigned int i=0; i < ad->buffer_size*ad->channels; i++) { - + for (unsigned int i=0; i < ad->period_size*ad->channels; i++) { ad->samples_out[i] = 0; }; } else { - ad->lock(); - ad->audio_server_process(ad->buffer_size, ad->samples_in); + ad->audio_server_process(ad->period_size, ad->samples_in); ad->unlock(); - for(unsigned int i=0;ibuffer_size*ad->channels;i++) { - + for(unsigned int i=0;iperiod_size*ad->channels;i++) { ad->samples_out[i]=ad->samples_in[i]>>16; } }; - int todo = ad->buffer_size; // * ad->channels * 2; + int todo = ad->period_size; int total = 0; while (todo) { - if (ad->exit_thread) break; uint8_t* src = (uint8_t*)ad->samples_out; @@ -184,7 +171,8 @@ void AudioDriverALSA::thread_func(void* p_udata) { break; if ( wrote == -EAGAIN ) { - usleep(1000); //can't write yet (though this is blocking..) + //can't write yet (though this is blocking..) + usleep(1000); continue; } wrote = snd_pcm_recover(ad->pcm_handle, wrote, 0); @@ -197,9 +185,9 @@ void AudioDriverALSA::thread_func(void* p_udata) { } continue; }; + total += wrote; todo -= wrote; - }; }; diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h index 487f017584..df28294f56 100644 --- a/drivers/alsa/audio_driver_alsa.h +++ b/drivers/alsa/audio_driver_alsa.h @@ -51,6 +51,7 @@ class AudioDriverALSA : public AudioDriverSW { OutputFormat output_format; snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; int channels; bool active; -- cgit v1.2.3