lib/alsa/HwSetup: return effective parameters

This commit is contained in:
Max Kellermann 2017-10-26 12:13:00 +02:00
parent b7e035b6f3
commit e2a74051dc
3 changed files with 45 additions and 33 deletions

View File

@ -176,11 +176,14 @@ SetupSampleFormat(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
return err; return err;
} }
void HwResult
SetupHw(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, SetupHw(snd_pcm_t *pcm,
unsigned buffer_time, unsigned period_time, unsigned buffer_time, unsigned period_time,
AudioFormat &audio_format, PcmExport::Params &params) AudioFormat &audio_format, PcmExport::Params &params)
{ {
snd_pcm_hw_params_t *hwparams;
snd_pcm_hw_params_alloca(&hwparams);
int err; int err;
unsigned int period_time_ro = period_time; unsigned int period_time_ro = period_time;
@ -285,6 +288,26 @@ SetupHw(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
if (err < 0) if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params() failed: %s", throw FormatRuntimeError("snd_pcm_hw_params() failed: %s",
snd_strerror(-err)); snd_strerror(-err));
HwResult result;
err = snd_pcm_hw_params_get_format(hwparams, &result.format);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_get_format() failed: %s",
snd_strerror(-err));
err = snd_pcm_hw_params_get_buffer_size(hwparams, &result.buffer_size);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_get_buffer_size() failed: %s",
snd_strerror(-err));
err = snd_pcm_hw_params_get_period_size(hwparams, &result.period_size,
nullptr);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_get_period_size() failed: %s",
snd_strerror(-err));
return result;
} }
} // namespace Alsa } // namespace Alsa

View File

@ -29,6 +29,11 @@ struct AudioFormat;
namespace Alsa { namespace Alsa {
struct HwResult {
snd_pcm_format_t format;
snd_pcm_uframes_t buffer_size, period_size;
};
/** /**
* Wrapper for snd_pcm_hw_params(). * Wrapper for snd_pcm_hw_params().
* *
@ -38,8 +43,8 @@ namespace Alsa {
* by this function * by this function
* @param params to be modified by this function * @param params to be modified by this function
*/ */
void HwResult
SetupHw(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, SetupHw(snd_pcm_t *pcm,
unsigned buffer_time, unsigned period_time, unsigned buffer_time, unsigned period_time,
AudioFormat &audio_format, PcmExport::Params &params); AudioFormat &audio_format, PcmExport::Params &params);

View File

@ -392,38 +392,22 @@ inline void
AlsaOutput::Setup(AudioFormat &audio_format, AlsaOutput::Setup(AudioFormat &audio_format,
PcmExport::Params &params) PcmExport::Params &params)
{ {
snd_pcm_hw_params_t *hwparams; const auto hw_result = Alsa::SetupHw(pcm,
snd_pcm_hw_params_alloca(&hwparams);
Alsa::SetupHw(pcm, hwparams,
buffer_time, period_time, buffer_time, period_time,
audio_format, params); audio_format, params);
snd_pcm_format_t format; FormatDebug(alsa_output_domain, "format=%s (%s)",
if (snd_pcm_hw_params_get_format(hwparams, &format) == 0) snd_pcm_format_name(hw_result.format),
FormatDebug(alsa_output_domain, snd_pcm_format_description(hw_result.format));
"format=%s (%s)", snd_pcm_format_name(format),
snd_pcm_format_description(format));
snd_pcm_uframes_t alsa_buffer_size;
int err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_get_buffer_size() failed: %s",
snd_strerror(-err));
snd_pcm_uframes_t alsa_period_size;
err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size,
nullptr);
if (err < 0)
throw FormatRuntimeError("snd_pcm_hw_params_get_period_size() failed: %s",
snd_strerror(-err));
AlsaSetupSw(pcm, alsa_buffer_size - alsa_period_size,
alsa_period_size);
FormatDebug(alsa_output_domain, "buffer_size=%u period_size=%u", FormatDebug(alsa_output_domain, "buffer_size=%u period_size=%u",
(unsigned)alsa_buffer_size, (unsigned)alsa_period_size); (unsigned)hw_result.buffer_size,
(unsigned)hw_result.period_size);
AlsaSetupSw(pcm, hw_result.buffer_size - hw_result.period_size,
hw_result.period_size);
auto alsa_period_size = hw_result.period_size;
if (alsa_period_size == 0) if (alsa_period_size == 0)
/* this works around a SIGFPE bug that occurred when /* this works around a SIGFPE bug that occurred when
an ALSA driver indicated period_size==0; this an ALSA driver indicated period_size==0; this
@ -435,7 +419,7 @@ AlsaOutput::Setup(AudioFormat &audio_format,
period_frames = alsa_period_size; period_frames = alsa_period_size;
silence = new uint8_t[snd_pcm_frames_to_bytes(pcm, alsa_period_size)]; silence = new uint8_t[snd_pcm_frames_to_bytes(pcm, alsa_period_size)];
snd_pcm_format_set_silence(format, silence, snd_pcm_format_set_silence(hw_result.format, silence,
alsa_period_size * audio_format.channels); alsa_period_size * audio_format.channels);
} }