aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2012-03-27 01:05:33 +0200
committerMax Kellermann <max@duempel.org>2012-03-27 01:22:50 +0200
commit2803ec2e96096dfc461f3e9a522e27b23453d076 (patch)
treeb622b0fdc5450e8b3c6d73e93dfc04ab7816b021
parentddd4f675a2d42b0c8156e03bf3e93f39df2fe609 (diff)
output/alsa: support 32 bit DSD-over-USB
-rw-r--r--src/output/alsa_output_plugin.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/src/output/alsa_output_plugin.c b/src/output/alsa_output_plugin.c
index c9dd1ee1..9faacb0a 100644
--- a/src/output/alsa_output_plugin.c
+++ b/src/output/alsa_output_plugin.c
@@ -588,7 +588,8 @@ error:
static bool
alsa_setup_dsd(struct alsa_data *ad, struct audio_format *audio_format,
- bool *packed_r, bool *reverse_endian_r, GError **error_r)
+ bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
+ GError **error_r)
{
assert(ad->dsd_usb);
assert(audio_format->format == SAMPLE_FORMAT_DSD);
@@ -604,6 +605,15 @@ alsa_setup_dsd(struct alsa_data *ad, struct audio_format *audio_format,
if (!alsa_setup(ad, &usb_format, packed_r, reverse_endian_r, error_r))
return false;
+ /* if the device allows only 32 bit, shift all DSD-over-USB
+ samples left by 8 bit and leave the lower 8 bit cleared;
+ the DSD-over-USB documentation does not specify whether
+ this is legal, but there is anecdotical evidence that this
+ is possible (and the only option for some devices) */
+ *shift8_r = usb_format.format == SAMPLE_FORMAT_S32;
+ if (usb_format.format == SAMPLE_FORMAT_S32)
+ usb_format.format = SAMPLE_FORMAT_S24_P32;
+
if (!audio_format_equals(&usb_format, &check)) {
/* no bit-perfect playback, which is required
for DSD over USB */
@@ -620,12 +630,13 @@ static bool
alsa_setup_or_dsd(struct alsa_data *ad, struct audio_format *audio_format,
GError **error_r)
{
- bool packed, reverse_endian;
+ bool shift8 = false, packed, reverse_endian;
const bool dsd_usb = ad->dsd_usb &&
audio_format->format == SAMPLE_FORMAT_DSD;
const bool success = dsd_usb
- ? alsa_setup_dsd(ad, audio_format, &packed, &reverse_endian,
+ ? alsa_setup_dsd(ad, audio_format,
+ &shift8, &packed, &reverse_endian,
error_r)
: alsa_setup(ad, audio_format, &packed, &reverse_endian,
error_r);
@@ -634,7 +645,7 @@ alsa_setup_or_dsd(struct alsa_data *ad, struct audio_format *audio_format,
pcm_export_open(&ad->export,
audio_format->format, audio_format->channels,
- dsd_usb, false, packed, reverse_endian);
+ dsd_usb, shift8, packed, reverse_endian);
return true;
}