From d3d120fa281134735fc4b113d0bcd7e4e1929ea9 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 28 Apr 2020 03:28:34 +0200 Subject: [PATCH] Prepare to allow using ALSA backend with nperiods > 3 This will still need an update for Alsa_pcmi::set_hwpar() capture channel (which is fixed at 2, unless FRAG_NEAR is used). --- .../ardouralsautil/deviceinfo.h | 1 + libs/ardouralsautil/deviceparams.cc | 19 +++++-------- libs/backends/alsa/alsa_audiobackend.cc | 27 ++++++++++++++++--- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/libs/ardouralsautil/ardouralsautil/deviceinfo.h b/libs/ardouralsautil/ardouralsautil/deviceinfo.h index d0a1b7ec18..e217a0d575 100644 --- a/libs/ardouralsautil/ardouralsautil/deviceinfo.h +++ b/libs/ardouralsautil/ardouralsautil/deviceinfo.h @@ -24,6 +24,7 @@ namespace ARDOUR { struct ALSADeviceInfo { unsigned int max_channels; unsigned int min_rate, max_rate; + unsigned int min_nper, min_nper; unsigned long min_size, max_size; bool valid; }; diff --git a/libs/ardouralsautil/deviceparams.cc b/libs/ardouralsautil/deviceparams.cc index 2e9bca95f6..613eac76e0 100644 --- a/libs/ardouralsautil/deviceparams.cc +++ b/libs/ardouralsautil/deviceparams.cc @@ -34,7 +34,6 @@ ARDOUR::get_alsa_device_parameters (const char* device_name, const bool play, AL unsigned long min_psiz, max_psiz; unsigned long min_bufz, max_bufz; - unsigned int min_nper, max_nper; err = snd_pcm_open (&pcm, device_name, play ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, @@ -91,12 +90,12 @@ ARDOUR::get_alsa_device_parameters (const char* device_name, const bool play, AL goto error_out; } - err = snd_pcm_hw_params_get_periods_min (hw_params, &min_nper, 0); + err = snd_pcm_hw_params_get_periods_min (hw_params, &nfo->min_nper, 0); if (err < 0) { errmsg = "Cannot get minimum period count"; goto error_out; } - err = snd_pcm_hw_params_get_periods_max (hw_params, &max_nper, 0); + err = snd_pcm_hw_params_get_periods_max (hw_params, &nfo->max_nper, 0); if (err < 0) { errmsg = "Cannot get maximum period count"; goto error_out; @@ -117,19 +116,13 @@ ARDOUR::get_alsa_device_parameters (const char* device_name, const bool play, AL fprintf (stdout, " max_psiz : %lu\n", nfo->max_size); fprintf (stdout, " min_bufz : %lu\n", min_bufz); fprintf (stdout, " max_bufz : %lu\n", max_bufz); - fprintf (stdout, " min_nper : %d\n", min_nper); - fprintf (stdout, " max_nper : %d\n", max_nper); + fprintf (stdout, " min_nper : %d\n", nfo->min_nper); + fprintf (stdout, " max_nper : %d\n", nfo->max_nper); fprintf (stdout, " possible : %lu .. %lu\n", nfo->min_size, nfo->max_size); } - /* AlsaAudioBackend supports n-periods 2, 3 */ - if (min_nper > 2 || max_nper < 3) { - errmsg = "Unsupported period count"; - return 1; - } - - nfo->min_size = std::max (min_psiz, min_bufz / 3); - nfo->max_size = std::min (max_psiz, max_bufz / 2); + nfo->min_size = std::max (min_psiz, min_bufz / nfo->max_nper); + nfo->max_size = std::min (max_psiz, max_bufz / nfo->min_nper); nfo->valid = true; return 0; diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc index 7dec3eb738..6c931b08cb 100644 --- a/libs/backends/alsa/alsa_audiobackend.cc +++ b/libs/backends/alsa/alsa_audiobackend.cc @@ -270,8 +270,27 @@ std::vector AlsaAudioBackend::available_period_sizes (const std::string& driver) const { std::vector ps; - ps.push_back (2); - ps.push_back (3); + + ALSADeviceInfo *nfo = NULL; + if (device == get_standard_device_name(DeviceNone)) { + return ps; + } + if (device == _output_audio_device && _output_audio_device_info.valid) { + nfo = &_output_audio_device_info; + } else { + ps.push_back (2); + return ps; + } + + if (nfo->min_nper == 2) { + ps.push_back (2); + if (nfo->max_nper >= 3) { + ps.push_back (3); + } + } else { + ps.push_back (nfo->min_nper); + } + return ps; } @@ -370,7 +389,7 @@ AlsaAudioBackend::set_sample_rate (float sr) int AlsaAudioBackend::set_peridod_size (uint32_t n) { - if (n == 0 || n > 3) { + if (n == 0) { return -1; } if (_run) { @@ -830,7 +849,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement) (duplex & 1) ? alsa_device.c_str() : NULL, /* ctrl name */ 0, _samplerate, _samples_per_period, - _periods_per_cycle, /* _periods_per_cycle */ 2, + _periods_per_cycle, /* capture p/c */ 2, /* debug */ 0); AudioBackend::ErrorCode error_code = NoError;