From a2b1482cadf8a995745d1aa227c324f6756af2e7 Mon Sep 17 00:00:00 2001 From: John Emmas Date: Thu, 18 Mar 2021 16:12:28 +0000 Subject: [PATCH] Fix a problem with ASIO buffer sizes on Windows PortAudio uses what it calls 'default suggested latencies' but in callback streaming mode, they can result in wildly inaccurate buffer sizing (e.g. the user requests a buffer size of 128 but PortAudio actually instructs ASIO to use a much bigger size). What we do now is to improve PortAudio's suggested latency calculation by basing it on the actual buffer size requested by the user. --- libs/backends/portaudio/portaudio_io.cc | 22 +++++++++++++++++----- libs/backends/portaudio/portaudio_io.h | 4 +++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/libs/backends/portaudio/portaudio_io.cc b/libs/backends/portaudio/portaudio_io.cc index 5739e982b6..d2d6ac4c58 100644 --- a/libs/backends/portaudio/portaudio_io.cc +++ b/libs/backends/portaudio/portaudio_io.cc @@ -698,7 +698,9 @@ PortAudioIO::get_input_stream_params(int device_input, #else inputParam.sampleFormat = paFloat32 | paNonInterleaved; #endif - inputParam.suggestedLatency = nfo_in->defaultLowInputLatency; + if (!inputParam.suggestedLatency) { + inputParam.suggestedLatency = nfo_in->defaultLowInputLatency; + } inputParam.hostApiSpecificStreamInfo = NULL; return true; @@ -732,7 +734,9 @@ PortAudioIO::get_output_stream_params(int device_output, #else outputParam.sampleFormat = paFloat32 | paNonInterleaved; #endif - outputParam.suggestedLatency = nfo_out->defaultLowOutputLatency; + if (!outputParam.suggestedLatency) { + outputParam.suggestedLatency = nfo_out->defaultLowOutputLatency; + } outputParam.hostApiSpecificStreamInfo = NULL; return true; @@ -742,7 +746,9 @@ PaErrorCode PortAudioIO::pre_stream_open(int device_input, PaStreamParameters& inputParam, int device_output, - PaStreamParameters& outputParam) + PaStreamParameters& outputParam, + uint32_t sample_rate, + uint32_t samples_per_period) { if (!pa_initialize()) { DEBUG_AUDIO ("PortAudio Initialization Failed\n"); @@ -758,6 +764,12 @@ PortAudioIO::pre_stream_open(int device_input, return paBadIODeviceCombination; } + if ((get_current_host_api_type() == paASIO) && sample_rate) { + outputParam.suggestedLatency = inputParam.suggestedLatency = ((double)samples_per_period / (double)sample_rate); + } else { + outputParam.suggestedLatency = inputParam.suggestedLatency = 0; + } + if (get_input_stream_params(device_input, inputParam)) { _capture_channels = inputParam.channelCount; } @@ -790,7 +802,7 @@ PortAudioIO::open_callback_stream(int device_input, PaStreamParameters outputParam; PaErrorCode error_code = - pre_stream_open(device_input, inputParam, device_output, outputParam); + pre_stream_open(device_input, inputParam, device_output, outputParam, sample_rate, samples_per_period); if (error_code != paNoError) return error_code; @@ -832,7 +844,7 @@ PortAudioIO::open_blocking_stream(int device_input, PaStreamParameters outputParam; PaErrorCode error_code = - pre_stream_open(device_input, inputParam, device_output, outputParam); + pre_stream_open(device_input, inputParam, device_output, outputParam, sample_rate, samples_per_period); if (error_code != paNoError) return error_code; diff --git a/libs/backends/portaudio/portaudio_io.h b/libs/backends/portaudio/portaudio_io.h index 2025320673..871cafb9c1 100644 --- a/libs/backends/portaudio/portaudio_io.h +++ b/libs/backends/portaudio/portaudio_io.h @@ -128,7 +128,9 @@ private: // Methods PaErrorCode pre_stream_open(int device_input, PaStreamParameters& inputParam, int device_output, - PaStreamParameters& outputParam); + PaStreamParameters& outputParam, + uint32_t sample_rate, + uint32_t samples_per_period); void reset_stream_dependents ();