pcm/Export: add CalcOutputSampleRate(), CalcInputSampleRate()

Prepare for DSD sample rate fixups.
This commit is contained in:
Max Kellermann 2017-01-10 23:48:26 +01:00
parent 142fdc8d86
commit c143adba91
4 changed files with 51 additions and 5 deletions

View File

@ -469,7 +469,6 @@ static void
AlsaSetup(AlsaOutput *ad, AudioFormat &audio_format,
PcmExport::Params &params)
{
unsigned int sample_rate = audio_format.sample_rate;
unsigned int channels = audio_format.channels;
int err;
unsigned retry = MPD_ALSA_RETRY_NR;
@ -513,18 +512,23 @@ configure_hw:
audio_format.channels = (int8_t)channels;
const unsigned requested_sample_rate =
params.CalcOutputSampleRate(audio_format.sample_rate);
unsigned output_sample_rate = requested_sample_rate;
err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams,
&sample_rate, nullptr);
&output_sample_rate, nullptr);
if (err < 0)
throw FormatRuntimeError("Failed to configure sample rate %u Hz: %s",
audio_format.sample_rate,
requested_sample_rate,
snd_strerror(-err));
if (sample_rate == 0)
if (output_sample_rate == 0)
throw FormatRuntimeError("Failed to configure sample rate %u Hz",
audio_format.sample_rate);
audio_format.sample_rate = sample_rate;
if (output_sample_rate != requested_sample_rate)
audio_format.sample_rate = params.CalcInputSampleRate(output_sample_rate);
snd_pcm_uframes_t buffer_size_min, buffer_size_max;
snd_pcm_hw_params_get_buffer_size_min(hwparams, &buffer_size_min);

View File

@ -98,6 +98,18 @@ PcmExport::GetFrameSize(const AudioFormat &audio_format) const
return audio_format.GetFrameSize();
}
unsigned
PcmExport::Params::CalcOutputSampleRate(unsigned sample_rate) const
{
return sample_rate;
}
unsigned
PcmExport::Params::CalcInputSampleRate(unsigned sample_rate) const
{
return sample_rate;
}
ConstBuffer<void>
PcmExport::Export(ConstBuffer<void> data)
{

View File

@ -41,6 +41,21 @@ struct PcmExport {
bool shift8 = false;
bool pack24 = false;
bool reverse_endian = false;
/**
* Calculate the output sample rate, given a specific input
* sample rate. Usually, both are the same; however, with
* DSD_U32, four input bytes (= 4 * 8 bits) are combined to
* one output word (32 bits), dividing the sample rate by 4.
*/
gcc_pure
unsigned CalcOutputSampleRate(unsigned input_sample_rate) const;
/**
* The inverse of CalcOutputSampleRate().
*/
gcc_pure
unsigned CalcInputSampleRate(unsigned output_sample_rate) const;
};
/**

View File

@ -35,6 +35,9 @@ PcmExportTest::TestShift8()
PcmExport::Params params;
params.shift8 = true;
CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
PcmExport e;
e.Open(SampleFormat::S24_P32, 2, params);
@ -71,6 +74,9 @@ PcmExportTest::TestPack24()
PcmExport::Params params;
params.pack24 = true;
CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
PcmExport e;
e.Open(SampleFormat::S24_P32, 2, params);
@ -97,6 +103,9 @@ PcmExportTest::TestReverseEndian()
PcmExport::Params params;
params.reverse_endian = true;
CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
PcmExport e;
e.Open(SampleFormat::S8, 2, params);
@ -192,6 +201,9 @@ TestAlsaChannelOrder51()
PcmExport::Params params;
params.alsa_channel_order = true;
CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
PcmExport e;
e.Open(F, 6, params);
@ -219,6 +231,9 @@ TestAlsaChannelOrder71()
PcmExport::Params params;
params.alsa_channel_order = true;
CPPUNIT_ASSERT_EQUAL(params.CalcOutputSampleRate(42u), 42u);
CPPUNIT_ASSERT_EQUAL(params.CalcInputSampleRate(42u), 42u);
PcmExport e;
e.Open(F, 8, params);