output/alsa: add option to enable DSD over USB
This commit is contained in:
parent
81208d78ac
commit
167242fec0
1
NEWS
1
NEWS
|
@ -17,6 +17,7 @@ ver 0.17 (2011/??/??)
|
||||||
- oggflac: delete this obsolete plugin
|
- oggflac: delete this obsolete plugin
|
||||||
- dsdiff: new decoder plugin
|
- dsdiff: new decoder plugin
|
||||||
* output:
|
* output:
|
||||||
|
- alsa: support DSD-over-USB (dCS suggested standard)
|
||||||
- httpd: support for streaming to a DLNA client
|
- httpd: support for streaming to a DLNA client
|
||||||
- openal: improve buffer cancellation
|
- openal: improve buffer cancellation
|
||||||
- osx: allow user to specify other audio devices
|
- osx: allow user to specify other audio devices
|
||||||
|
|
17
doc/user.xml
17
doc/user.xml
|
@ -1119,6 +1119,23 @@ systemctl start mpd.socket</programlisting>
|
||||||
bit, floating point, ...).
|
bit, floating point, ...).
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<varname>dsd_usb</varname>
|
||||||
|
<parameter>yes|no</parameter>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
If set to <parameter>yes</parameter>, then DSD over
|
||||||
|
USB according to the <ulink
|
||||||
|
url="http://www.dcsltd.co.uk/page/assets/DSDoverUSB.pdf">dCS
|
||||||
|
suggested standard</ulink> is enabled. This wrapsa
|
||||||
|
DSD samples in fake 24 bit PCM, and is understood by
|
||||||
|
some DSD capable products, but may be harmful to
|
||||||
|
other hardware. Therefore, the default is
|
||||||
|
<parameter>no</parameter> and you can enable the
|
||||||
|
option at your own risk.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</informaltable>
|
</informaltable>
|
||||||
|
|
|
@ -55,6 +55,14 @@ struct alsa_data {
|
||||||
/** use memory mapped I/O? */
|
/** use memory mapped I/O? */
|
||||||
bool use_mmap;
|
bool use_mmap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable DSD over USB according to the dCS suggested
|
||||||
|
* standard?
|
||||||
|
*
|
||||||
|
* @see http://www.dcsltd.co.uk/page/assets/DSDoverUSB.pdf
|
||||||
|
*/
|
||||||
|
bool dsd_usb;
|
||||||
|
|
||||||
/** libasound's buffer_time setting (in microseconds) */
|
/** libasound's buffer_time setting (in microseconds) */
|
||||||
unsigned int buffer_time;
|
unsigned int buffer_time;
|
||||||
|
|
||||||
|
@ -128,6 +136,8 @@ alsa_configure(struct alsa_data *ad, const struct config_param *param)
|
||||||
|
|
||||||
ad->use_mmap = config_get_block_bool(param, "use_mmap", false);
|
ad->use_mmap = config_get_block_bool(param, "use_mmap", false);
|
||||||
|
|
||||||
|
ad->dsd_usb = config_get_block_bool(param, "dsd_usb", false);
|
||||||
|
|
||||||
ad->buffer_time = config_get_block_unsigned(param, "buffer_time",
|
ad->buffer_time = config_get_block_unsigned(param, "buffer_time",
|
||||||
MPD_ALSA_BUFFER_TIME_US);
|
MPD_ALSA_BUFFER_TIME_US);
|
||||||
ad->period_time = config_get_block_unsigned(param, "period_time", 0);
|
ad->period_time = config_get_block_unsigned(param, "period_time", 0);
|
||||||
|
@ -575,6 +585,49 @@ error:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
alsa_setup_dsd(struct alsa_data *ad, struct audio_format *audio_format,
|
||||||
|
GError **error_r)
|
||||||
|
{
|
||||||
|
assert(ad->dsd_usb);
|
||||||
|
assert(audio_format->format == SAMPLE_FORMAT_DSD);
|
||||||
|
|
||||||
|
/* pass 24 bit to alsa_setup() */
|
||||||
|
|
||||||
|
audio_format->format = SAMPLE_FORMAT_S24_P32;
|
||||||
|
audio_format->sample_rate /= 2;
|
||||||
|
|
||||||
|
const struct audio_format check = *audio_format;
|
||||||
|
|
||||||
|
if (!alsa_setup(ad, audio_format, error_r))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!audio_format_equals(audio_format, &check)) {
|
||||||
|
/* no bit-perfect playback, which is required
|
||||||
|
for DSD over USB */
|
||||||
|
g_set_error(error_r, alsa_output_quark(), 0,
|
||||||
|
"Failed to configure DSD-over-USB on ALSA device \"%s\"",
|
||||||
|
alsa_device(ad));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the ALSA device has accepted 24 bit playback,
|
||||||
|
return DSD_OVER_USB to the caller */
|
||||||
|
|
||||||
|
audio_format->format = SAMPLE_FORMAT_DSD_OVER_USB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
alsa_setup_or_dsd(struct alsa_data *ad, struct audio_format *audio_format,
|
||||||
|
GError **error_r)
|
||||||
|
{
|
||||||
|
if (ad->dsd_usb && audio_format->format == SAMPLE_FORMAT_DSD)
|
||||||
|
return alsa_setup_dsd(ad, audio_format, error_r);
|
||||||
|
|
||||||
|
return alsa_setup(ad, audio_format, error_r);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **error)
|
alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **error)
|
||||||
{
|
{
|
||||||
|
@ -591,7 +644,7 @@ alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **e
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
success = alsa_setup(ad, audio_format, error);
|
success = alsa_setup_or_dsd(ad, audio_format, error);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
snd_pcm_close(ad->pcm);
|
snd_pcm_close(ad->pcm);
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue