pcm/Export: convert the DSD bools to an enum
These options are exclusive.
This commit is contained in:
parent
c75dc4a647
commit
28e07e900f
|
@ -95,8 +95,7 @@ TryFormatDsd(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
|
|||
|
||||
#if defined(ENABLE_DSD) && defined(HAVE_ALSA_DSD_U32)
|
||||
if (err == 0) {
|
||||
params.dsd_u16 = false;
|
||||
params.dsd_u32 = false;
|
||||
params.dsd_mode = PcmExport::DsdMode::NONE;
|
||||
}
|
||||
|
||||
if (err == -EINVAL && fmt == SND_PCM_FORMAT_DSD_U8) {
|
||||
|
@ -106,7 +105,7 @@ TryFormatDsd(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
|
|||
: SND_PCM_FORMAT_DSD_U32_BE;
|
||||
err = TryFormatOrByteSwap(pcm, hwparams, fmt, params);
|
||||
if (err == 0)
|
||||
params.dsd_u32 = true;
|
||||
params.dsd_mode = PcmExport::DsdMode::U32;
|
||||
else
|
||||
fmt = SND_PCM_FORMAT_DSD_U8;
|
||||
}
|
||||
|
@ -118,7 +117,7 @@ TryFormatDsd(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
|
|||
: SND_PCM_FORMAT_DSD_U16_BE;
|
||||
err = TryFormatOrByteSwap(pcm, hwparams, fmt, params);
|
||||
if (err == 0)
|
||||
params.dsd_u16 = true;
|
||||
params.dsd_mode = PcmExport::DsdMode::U16;
|
||||
else
|
||||
fmt = SND_PCM_FORMAT_DSD_U8;
|
||||
}
|
||||
|
|
|
@ -558,12 +558,12 @@ AlsaOutput::SetupOrDop(AudioFormat &audio_format, PcmExport::Params ¶ms
|
|||
std::exception_ptr dop_error;
|
||||
if (dop && audio_format.format == SampleFormat::DSD) {
|
||||
try {
|
||||
params.dop = true;
|
||||
params.dsd_mode = PcmExport::DsdMode::DOP;
|
||||
SetupDop(audio_format, params);
|
||||
return;
|
||||
} catch (...) {
|
||||
dop_error = std::current_exception();
|
||||
params.dop = false;
|
||||
params.dsd_mode = PcmExport::DsdMode::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +663,7 @@ AlsaOutput::Open(AudioFormat &audio_format)
|
|||
snd_pcm_nonblock(pcm, 1);
|
||||
|
||||
#ifdef ENABLE_DSD
|
||||
if (params.dop)
|
||||
if (params.dsd_mode == PcmExport::DsdMode::DOP)
|
||||
FormatDebug(alsa_output_domain, "DoP (DSD over PCM) enabled");
|
||||
#endif
|
||||
|
||||
|
|
|
@ -787,7 +787,7 @@ OSXOutput::Open(AudioFormat &audio_format)
|
|||
#ifdef ENABLE_DSD
|
||||
if (dop && audio_format.format == SampleFormat::DSD) {
|
||||
asbd.mBitsPerChannel = 24;
|
||||
params.dop = true;
|
||||
params.dsd_mode = PcmExport::DsdMode::DOP;
|
||||
asbd.mSampleRate = params.CalcOutputSampleRate(audio_format.sample_rate);
|
||||
asbd.mBytesPerPacket = 4 * audio_format.channels;
|
||||
|
||||
|
@ -802,14 +802,14 @@ OSXOutput::Open(AudioFormat &audio_format)
|
|||
|
||||
#ifdef ENABLE_DSD
|
||||
if(audio_format.format == SampleFormat::DSD && sample_rate != asbd.mSampleRate) { // fall back to PCM in case sample_rate cannot be synchronized
|
||||
params.dop = false;
|
||||
params.dsd_mode = PcmExport::DsdMode::NONE;
|
||||
audio_format.format = SampleFormat::S32;
|
||||
asbd.mBitsPerChannel = 32;
|
||||
asbd.mBytesPerPacket = audio_format.GetFrameSize();
|
||||
asbd.mSampleRate = params.CalcOutputSampleRate(audio_format.sample_rate);
|
||||
asbd.mBytesPerFrame = asbd.mBytesPerPacket;
|
||||
}
|
||||
dop_enabled = params.dop;
|
||||
dop_enabled = params.dsd_mode == PcmExport::DsdMode::DOP;
|
||||
#endif
|
||||
|
||||
OSStatus status =
|
||||
|
|
|
@ -45,28 +45,36 @@ PcmExport::Open(SampleFormat sample_format, unsigned _channels,
|
|||
: SampleFormat::UNDEFINED;
|
||||
|
||||
#ifdef ENABLE_DSD
|
||||
assert((params.dsd_u16 + params.dsd_u32 + params.dop) <= 1);
|
||||
assert(!params.dop || audio_valid_channel_count(_channels));
|
||||
assert(params.dsd_mode != DsdMode::DOP ||
|
||||
audio_valid_channel_count(_channels));
|
||||
|
||||
dsd_u16 = params.dsd_u16 && sample_format == SampleFormat::DSD;
|
||||
if (dsd_u16)
|
||||
dsd_mode = sample_format == SampleFormat::DSD
|
||||
? params.dsd_mode
|
||||
: DsdMode::NONE;
|
||||
|
||||
switch (dsd_mode) {
|
||||
case DsdMode::NONE:
|
||||
break;
|
||||
|
||||
case DsdMode::U16:
|
||||
/* after the conversion to DSD_U16, the DSD samples
|
||||
are stuffed inside fake 16 bit samples */
|
||||
sample_format = SampleFormat::S16;
|
||||
break;
|
||||
|
||||
dsd_u32 = params.dsd_u32 && sample_format == SampleFormat::DSD;
|
||||
if (dsd_u32)
|
||||
case DsdMode::U32:
|
||||
/* after the conversion to DSD_U32, the DSD samples
|
||||
are stuffed inside fake 32 bit samples */
|
||||
sample_format = SampleFormat::S32;
|
||||
break;
|
||||
|
||||
dop = params.dop && sample_format == SampleFormat::DSD;
|
||||
if (dop) {
|
||||
case DsdMode::DOP:
|
||||
dop_converter.Open(_channels);
|
||||
|
||||
/* after the conversion to DoP, the DSD
|
||||
samples are stuffed inside fake 24 bit samples */
|
||||
sample_format = SampleFormat::S24_P32;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -91,8 +99,16 @@ void
|
|||
PcmExport::Reset() noexcept
|
||||
{
|
||||
#ifdef ENABLE_DSD
|
||||
if (dop)
|
||||
switch (dsd_mode) {
|
||||
case DsdMode::NONE:
|
||||
case DsdMode::U16:
|
||||
case DsdMode::U32:
|
||||
break;
|
||||
|
||||
case DsdMode::DOP:
|
||||
dop_converter.Reset();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -104,18 +120,23 @@ PcmExport::GetFrameSize(const AudioFormat &audio_format) const noexcept
|
|||
return audio_format.channels * 3;
|
||||
|
||||
#ifdef ENABLE_DSD
|
||||
if (dsd_u16)
|
||||
switch (dsd_mode) {
|
||||
case DsdMode::NONE:
|
||||
break;
|
||||
|
||||
case DsdMode::U16:
|
||||
return channels * 2;
|
||||
|
||||
if (dsd_u32)
|
||||
case DsdMode::U32:
|
||||
return channels * 4;
|
||||
|
||||
if (dop)
|
||||
case DsdMode::DOP:
|
||||
/* the DSD-over-USB draft says that DSD 1-bit samples
|
||||
are enclosed within 24 bit samples, and MPD's
|
||||
representation of 24 bit is padded to 32 bit (4
|
||||
bytes per sample) */
|
||||
return channels * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
return audio_format.GetFrameSize();
|
||||
|
@ -125,20 +146,28 @@ unsigned
|
|||
PcmExport::Params::CalcOutputSampleRate(unsigned sample_rate) const noexcept
|
||||
{
|
||||
#ifdef ENABLE_DSD
|
||||
if (dsd_u16)
|
||||
switch (dsd_mode) {
|
||||
case DsdMode::NONE:
|
||||
break;
|
||||
|
||||
case DsdMode::U16:
|
||||
/* DSD_U16 combines two 8-bit "samples" in one 16-bit
|
||||
"sample" */
|
||||
sample_rate /= 2;
|
||||
break;
|
||||
|
||||
if (dsd_u32)
|
||||
case DsdMode::U32:
|
||||
/* DSD_U32 combines four 8-bit "samples" in one 32-bit
|
||||
"sample" */
|
||||
sample_rate /= 4;
|
||||
break;
|
||||
|
||||
if (dop)
|
||||
case DsdMode::DOP:
|
||||
/* DoP packs two 8-bit "samples" in one 24-bit
|
||||
"sample" */
|
||||
sample_rate /= 2;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return sample_rate;
|
||||
|
@ -148,14 +177,22 @@ unsigned
|
|||
PcmExport::Params::CalcInputSampleRate(unsigned sample_rate) const noexcept
|
||||
{
|
||||
#ifdef ENABLE_DSD
|
||||
if (dsd_u16)
|
||||
sample_rate *= 2;
|
||||
switch (dsd_mode) {
|
||||
case DsdMode::NONE:
|
||||
break;
|
||||
|
||||
if (dsd_u32)
|
||||
case DsdMode::U16:
|
||||
sample_rate *= 2;
|
||||
break;
|
||||
|
||||
case DsdMode::U32:
|
||||
sample_rate *= 4;
|
||||
break;
|
||||
|
||||
if (dop)
|
||||
case DsdMode::DOP:
|
||||
sample_rate *= 2;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return sample_rate;
|
||||
|
@ -169,19 +206,27 @@ PcmExport::Export(ConstBuffer<void> data) noexcept
|
|||
alsa_channel_order, channels);
|
||||
|
||||
#ifdef ENABLE_DSD
|
||||
if (dsd_u16)
|
||||
switch (dsd_mode) {
|
||||
case DsdMode::NONE:
|
||||
break;
|
||||
|
||||
case DsdMode::U16:
|
||||
data = Dsd8To16(dsd_buffer, channels,
|
||||
ConstBuffer<uint8_t>::FromVoid(data))
|
||||
.ToVoid();
|
||||
break;
|
||||
|
||||
if (dsd_u32)
|
||||
case DsdMode::U32:
|
||||
data = Dsd8To32(dsd_buffer, channels,
|
||||
ConstBuffer<uint8_t>::FromVoid(data))
|
||||
.ToVoid();
|
||||
break;
|
||||
|
||||
if (dop)
|
||||
case DsdMode::DOP:
|
||||
data = dop_converter.Convert(ConstBuffer<uint8_t>::FromVoid(data))
|
||||
.ToVoid();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pack24) {
|
||||
|
@ -228,9 +273,17 @@ PcmExport::CalcSourceSize(size_t size) const noexcept
|
|||
size = (size / 3) * 4;
|
||||
|
||||
#ifdef ENABLE_DSD
|
||||
if (dop)
|
||||
switch (dsd_mode) {
|
||||
case DsdMode::NONE:
|
||||
case DsdMode::U16:
|
||||
case DsdMode::U32:
|
||||
break;
|
||||
|
||||
case DsdMode::DOP:
|
||||
/* DoP doubles the transport size */
|
||||
size /= 2;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return size;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "Dop.hxx"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
template<typename T> struct ConstBuffer;
|
||||
struct AudioFormat;
|
||||
|
||||
|
@ -88,22 +90,30 @@ class PcmExport {
|
|||
SampleFormat alsa_channel_order;
|
||||
|
||||
#ifdef ENABLE_DSD
|
||||
/**
|
||||
* Convert DSD (U8) to DSD_U16?
|
||||
*/
|
||||
bool dsd_u16;
|
||||
public:
|
||||
enum class DsdMode : uint8_t {
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Convert DSD (U8) to DSD_U32?
|
||||
*/
|
||||
bool dsd_u32;
|
||||
/**
|
||||
* Convert DSD (U8) to DSD_U16?
|
||||
*/
|
||||
U16,
|
||||
|
||||
/**
|
||||
* Convert DSD to DSD-over-PCM (DoP)? Input format must be
|
||||
* SampleFormat::DSD and output format must be
|
||||
* SampleFormat::S24_P32.
|
||||
*/
|
||||
bool dop;
|
||||
/**
|
||||
* Convert DSD (U8) to DSD_U32?
|
||||
*/
|
||||
U32,
|
||||
|
||||
/**
|
||||
* Convert DSD to DSD-over-PCM (DoP)? Input format
|
||||
* must be SampleFormat::DSD and output format must be
|
||||
* SampleFormat::S24_P32.
|
||||
*/
|
||||
DOP,
|
||||
};
|
||||
|
||||
private:
|
||||
DsdMode dsd_mode;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -128,9 +138,7 @@ public:
|
|||
struct Params {
|
||||
bool alsa_channel_order = false;
|
||||
#ifdef ENABLE_DSD
|
||||
bool dsd_u16 = false;
|
||||
bool dsd_u32 = false;
|
||||
bool dop = false;
|
||||
DsdMode dsd_mode = DsdMode::NONE;
|
||||
#endif
|
||||
bool shift8 = false;
|
||||
bool pack24 = false;
|
||||
|
|
|
@ -141,7 +141,7 @@ TEST(PcmTest, ExportDsdU16)
|
|||
};
|
||||
|
||||
PcmExport::Params params;
|
||||
params.dsd_u16 = true;
|
||||
params.dsd_mode = PcmExport::DsdMode::U16;
|
||||
|
||||
EXPECT_EQ(params.CalcOutputSampleRate(705600u), 352800u);
|
||||
EXPECT_EQ(params.CalcInputSampleRate(352800u), 705600u);
|
||||
|
@ -171,7 +171,7 @@ TEST(PcmTest, ExportDsdU32)
|
|||
};
|
||||
|
||||
PcmExport::Params params;
|
||||
params.dsd_u32 = true;
|
||||
params.dsd_mode = PcmExport::DsdMode::U32;
|
||||
|
||||
EXPECT_EQ(params.CalcOutputSampleRate(705600u), 176400u);
|
||||
EXPECT_EQ(params.CalcInputSampleRate(176400u), 705600u);
|
||||
|
@ -199,7 +199,7 @@ TEST(PcmTest, ExportDop)
|
|||
};
|
||||
|
||||
PcmExport::Params params;
|
||||
params.dop = true;
|
||||
params.dsd_mode = PcmExport::DsdMode::DOP;
|
||||
|
||||
EXPECT_EQ(params.CalcOutputSampleRate(705600u), 352800u);
|
||||
EXPECT_EQ(params.CalcInputSampleRate(352800u), 705600u);
|
||||
|
|
Loading…
Reference in New Issue