summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2017-01-11 22:33:52 +0100
committerMax Kellermann <max@musicpd.org>2017-01-11 22:47:21 +0100
commit70008c47c9c42a558000615f19a948adfe8739e8 (patch)
tree6c18508291d653ca25c3747c31aa4f993dbae3cf
parent938affef32bc6a2ae7b6bdaa8b22330ebb06d1cd (diff)
output/alsa: support DSD_U16
-rw-r--r--NEWS1
-rw-r--r--src/output/plugins/AlsaOutputPlugin.cxx20
2 files changed, 19 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index a76b21218..e01b5ed6d 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ ver 0.20.2 (not yet released)
* output
- alsa: fix the DSD_U32 sample rate
- alsa: fix the DSD_U32 byte order
+ - alsa: support DSD_U16
ver 0.20.1 (2017/01/09)
* input
diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx
index afac5f6d3..04e2fd852 100644
--- a/src/output/plugins/AlsaOutputPlugin.cxx
+++ b/src/output/plugins/AlsaOutputPlugin.cxx
@@ -385,7 +385,7 @@ AlsaTryFormatOrByteSwap(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
/**
* Attempts to configure the specified sample format. On DSD_U8
- * failure, attempt to switch to DSD_U32.
+ * failure, attempt to switch to DSD_U32 or DSD_U16.
*/
static int
AlsaTryFormatDsd(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
@@ -394,8 +394,10 @@ AlsaTryFormatDsd(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
int err = AlsaTryFormatOrByteSwap(pcm, hwparams, fmt, params);
#if defined(ENABLE_DSD) && defined(HAVE_ALSA_DSD_U32)
- if (err == 0)
+ if (err == 0) {
+ params.dsd_u16 = false;
params.dsd_u32 = false;
+ }
if (err == -EINVAL && fmt == SND_PCM_FORMAT_DSD_U8) {
/* attempt to switch to DSD_U32 */
@@ -405,6 +407,20 @@ AlsaTryFormatDsd(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
err = AlsaTryFormatOrByteSwap(pcm, hwparams, fmt, params);
if (err == 0)
params.dsd_u32 = true;
+ else
+ fmt = SND_PCM_FORMAT_DSD_U8;
+ }
+
+ if (err == -EINVAL && fmt == SND_PCM_FORMAT_DSD_U8) {
+ /* attempt to switch to DSD_U16 */
+ fmt = IsLittleEndian()
+ ? SND_PCM_FORMAT_DSD_U16_LE
+ : SND_PCM_FORMAT_DSD_U16_BE;
+ err = AlsaTryFormatOrByteSwap(pcm, hwparams, fmt, params);
+ if (err == 0)
+ params.dsd_u16 = true;
+ else
+ fmt = SND_PCM_FORMAT_DSD_U8;
}
#endif