From d7137586a991d19662bfe5d2fb14529ede799545 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 17 Jan 2017 09:25:18 +0100 Subject: [PATCH] Audio{Format,Parser}: use shortcuts such as "dsd64" in log messages --- NEWS | 1 + doc/user.xml | 6 +++++- src/AudioFormat.cxx | 11 +++++++++++ src/AudioParser.cxx | 20 ++++++++++++++++++++ test/TestAudioFormat.cxx | 3 ++- 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index c17b563f2..bf6e1a6e3 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.20.3 (not yet released) * protocol - "playlistadd" creates new playlist if it does not exist, as documented +* use shortcuts such as "dsd64" in log messages ver 0.20.2 (2017/01/15) * input diff --git a/doc/user.xml b/doc/user.xml index 8124462ed..e75777448 100644 --- a/doc/user.xml +++ b/doc/user.xml @@ -598,7 +598,11 @@ systemctl start mpd.socket 32 (signed 32 bit integer samples), f (32 bit floating point, -1.0 to 1.0), "dsd" means - DSD (Direct Stream Digital). + DSD (Direct Stream Digital). For DSD, there are + special cases such as "dsd64", + which allows you to omit the sample rate + (e.g. dsd512:2 for stereo + DSD512, i.e. 22.5792 MHz). The sample rate is special for DSD: diff --git a/src/AudioFormat.cxx b/src/AudioFormat.cxx index c3ebb2e6f..9a9f8ab5e 100644 --- a/src/AudioFormat.cxx +++ b/src/AudioFormat.cxx @@ -45,6 +45,17 @@ StringBuffer<24> ToString(const AudioFormat af) { StringBuffer<24> buffer; + + if (af.format == SampleFormat::DSD && af.sample_rate > 0 && + af.sample_rate % 44100 == 0) { + /* use shortcuts such as "dsd64" which implies the + sample rate */ + snprintf(buffer.data(), buffer.capacity(), "dsd%u:%u", + af.sample_rate * 8 / 44100, + af.channels); + return buffer; + } + snprintf(buffer.data(), buffer.capacity(), "%u:%s:%u", af.sample_rate, sample_format_to_string(af.format), af.channels); diff --git a/src/AudioParser.cxx b/src/AudioParser.cxx index 55e01b0cc..b2811cd94 100644 --- a/src/AudioParser.cxx +++ b/src/AudioParser.cxx @@ -137,6 +137,26 @@ ParseAudioFormat(const char *src, bool mask) AudioFormat dest; dest.Clear(); + if (strncmp(src, "dsd", 3) == 0) { + /* allow format specifications such as "dsd64" which + implies the sample rate */ + + char *endptr; + auto dsd = strtoul(src + 3, &endptr, 10); + if (endptr > src + 3 && *endptr == ':' && + dsd >= 32 && dsd <= 4096 && dsd % 2 == 0) { + dest.sample_rate = dsd * 44100 / 8; + dest.format = SampleFormat::DSD; + + src = endptr + 1; + dest.channels = ParseChannelCount(src, mask, &src); + if (*src != 0) + throw FormatRuntimeError("Extra data after channel count: %s", src); + + return dest; + } + } + /* parse sample rate */ dest.sample_rate = ParseSampleRate(src, mask, &src); diff --git a/test/TestAudioFormat.cxx b/test/TestAudioFormat.cxx index a29bf1b9d..e5a5041b9 100644 --- a/test/TestAudioFormat.cxx +++ b/test/TestAudioFormat.cxx @@ -67,7 +67,8 @@ static constexpr AudioFormatStringTest af_string_tests[] = { { AudioFormat(44100, SampleFormat::S16, 2), "44100:16:2" }, { AudioFormat(48000, SampleFormat::S24_P32, 6), "48000:24:6" }, { AudioFormat(192000, SampleFormat::FLOAT, 2), "192000:f:2" }, - { AudioFormat(352800, SampleFormat::DSD, 2), "352800:dsd:2" }, + { AudioFormat(352801, SampleFormat::DSD, 2), "352801:dsd:2" }, + { AudioFormat(352800, SampleFormat::DSD, 2), "dsd64:2" }, }; static constexpr AudioFormatStringTest af_mask_tests[] = {