From 25164969932590894671895944f30743d344e541 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 1 Mar 2012 00:25:08 +0100 Subject: audio_format: add DSD sample format Basic support for Direct Stream Digital. No conversion yet, and no decoder/output plugin support. --- src/audio_format.c | 6 ++++++ src/audio_format.h | 19 +++++++++++++++++++ src/audio_parser.c | 12 ++++++++++++ src/decoder/flac_pcm.c | 2 ++ src/output/alsa_output_plugin.c | 2 ++ src/output/oss_output_plugin.c | 2 ++ src/pcm_byteswap.c | 2 ++ src/pcm_convert.c | 2 ++ src/pcm_format.c | 8 ++++++++ src/pcm_mix.c | 4 ++++ src/pcm_volume.c | 2 ++ 11 files changed, 61 insertions(+) diff --git a/src/audio_format.c b/src/audio_format.c index 8c40457ec..c9ee27fa1 100644 --- a/src/audio_format.c +++ b/src/audio_format.c @@ -71,6 +71,12 @@ sample_format_to_string(enum sample_format format) case SAMPLE_FORMAT_FLOAT: return "f"; + + case SAMPLE_FORMAT_DSD: + return "dsd"; + + case SAMPLE_FORMAT_DSD_LSBFIRST: + return "dsdl"; } /* unreachable */ diff --git a/src/audio_format.h b/src/audio_format.h index 4f7dbfb1a..2c86b70b9 100644 --- a/src/audio_format.h +++ b/src/audio_format.h @@ -49,6 +49,18 @@ enum sample_format { * range is -1.0f to +1.0f. */ SAMPLE_FORMAT_FLOAT, + + /** + * Direct Stream Digital. 1-bit samples; each frame has one + * byte (8 samples) per channel. + */ + SAMPLE_FORMAT_DSD, + + /** + * Same as #SAMPLE_FORMAT_DSD, but the least significant bit + * comes first. + */ + SAMPLE_FORMAT_DSD_LSBFIRST, }; static const unsigned MAX_CHANNELS = 8; @@ -175,6 +187,8 @@ audio_valid_sample_format(enum sample_format format) case SAMPLE_FORMAT_S24_P32: case SAMPLE_FORMAT_S32: case SAMPLE_FORMAT_FLOAT: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: return true; case SAMPLE_FORMAT_UNDEFINED: @@ -251,6 +265,11 @@ sample_format_size(enum sample_format format) case SAMPLE_FORMAT_FLOAT: return 4; + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: + /* each frame has 8 samples per channel */ + return 1; + case SAMPLE_FORMAT_UNDEFINED: return 0; } diff --git a/src/audio_parser.c b/src/audio_parser.c index 8875239e1..7061e0e00 100644 --- a/src/audio_parser.c +++ b/src/audio_parser.c @@ -87,6 +87,18 @@ parse_sample_format(const char *src, bool mask, return true; } + if (memcmp(src, "dsd", 3) == 0) { + if (src[3] == 'l') { + *sample_format_r = SAMPLE_FORMAT_DSD_LSBFIRST; + *endptr_r = src + 4; + } else { + *sample_format_r = SAMPLE_FORMAT_DSD; + *endptr_r = src + 3; + } + + return true; + } + value = strtoul(src, &endptr, 10); if (endptr == src) { g_set_error(error_r, audio_parser_quark(), 0, diff --git a/src/decoder/flac_pcm.c b/src/decoder/flac_pcm.c index c479ebfd4..4d35b118e 100644 --- a/src/decoder/flac_pcm.c +++ b/src/decoder/flac_pcm.c @@ -103,6 +103,8 @@ flac_convert(void *dest, case SAMPLE_FORMAT_S24: case SAMPLE_FORMAT_FLOAT: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: case SAMPLE_FORMAT_UNDEFINED: /* unreachable */ assert(false); diff --git a/src/output/alsa_output_plugin.c b/src/output/alsa_output_plugin.c index f939ba5b4..58f73d67d 100644 --- a/src/output/alsa_output_plugin.c +++ b/src/output/alsa_output_plugin.c @@ -194,6 +194,8 @@ get_bitformat(enum sample_format sample_format) { switch (sample_format) { case SAMPLE_FORMAT_UNDEFINED: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: return SND_PCM_FORMAT_UNKNOWN; case SAMPLE_FORMAT_S8: diff --git a/src/output/oss_output_plugin.c b/src/output/oss_output_plugin.c index 46505873b..b2b491c9c 100644 --- a/src/output/oss_output_plugin.c +++ b/src/output/oss_output_plugin.c @@ -396,6 +396,8 @@ sample_format_to_oss(enum sample_format format) switch (format) { case SAMPLE_FORMAT_UNDEFINED: case SAMPLE_FORMAT_FLOAT: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: return AFMT_QUERY; case SAMPLE_FORMAT_S8: diff --git a/src/pcm_byteswap.c b/src/pcm_byteswap.c index a1315c475..741c6510f 100644 --- a/src/pcm_byteswap.c +++ b/src/pcm_byteswap.c @@ -74,6 +74,8 @@ pcm_byteswap(struct pcm_buffer *buffer, enum sample_format format, return NULL; case SAMPLE_FORMAT_S8: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: return src; case SAMPLE_FORMAT_S16: diff --git a/src/pcm_convert.c b/src/pcm_convert.c index a3b3bb446..0c4e19b9c 100644 --- a/src/pcm_convert.c +++ b/src/pcm_convert.c @@ -77,6 +77,8 @@ pcm_convert_channels(struct pcm_buffer *buffer, enum sample_format format, case SAMPLE_FORMAT_S8: case SAMPLE_FORMAT_S24: case SAMPLE_FORMAT_FLOAT: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: g_set_error(error_r, pcm_convert_quark(), 0, "Channel conversion not implemented for format '%s'", sample_format_to_string(format)); diff --git a/src/pcm_format.c b/src/pcm_format.c index a20d8bb8d..c7cf910ed 100644 --- a/src/pcm_format.c +++ b/src/pcm_format.c @@ -147,6 +147,8 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, switch (src_format) { case SAMPLE_FORMAT_UNDEFINED: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: break; case SAMPLE_FORMAT_S8: @@ -265,6 +267,8 @@ pcm_convert_to_24(struct pcm_buffer *buffer, switch (src_format) { case SAMPLE_FORMAT_UNDEFINED: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: break; case SAMPLE_FORMAT_S8: @@ -389,6 +393,8 @@ pcm_convert_to_32(struct pcm_buffer *buffer, switch (src_format) { case SAMPLE_FORMAT_UNDEFINED: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: break; case SAMPLE_FORMAT_S8: @@ -524,6 +530,8 @@ pcm_convert_to_float(struct pcm_buffer *buffer, { switch (src_format) { case SAMPLE_FORMAT_UNDEFINED: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: break; case SAMPLE_FORMAT_S8: diff --git a/src/pcm_mix.c b/src/pcm_mix.c index 9f76d568f..84bb5526d 100644 --- a/src/pcm_mix.c +++ b/src/pcm_mix.c @@ -120,6 +120,8 @@ pcm_add_vol(void *buffer1, const void *buffer2, size_t size, switch (format) { case SAMPLE_FORMAT_UNDEFINED: case SAMPLE_FORMAT_S24: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: /* not implemented */ return false; @@ -229,6 +231,8 @@ pcm_add(void *buffer1, const void *buffer2, size_t size, switch (format) { case SAMPLE_FORMAT_UNDEFINED: case SAMPLE_FORMAT_S24: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: /* not implemented */ return false; diff --git a/src/pcm_volume.c b/src/pcm_volume.c index de4bda6c9..d8da570aa 100644 --- a/src/pcm_volume.c +++ b/src/pcm_volume.c @@ -159,6 +159,8 @@ pcm_volume(void *buffer, size_t length, switch (format) { case SAMPLE_FORMAT_UNDEFINED: case SAMPLE_FORMAT_S24: + case SAMPLE_FORMAT_DSD: + case SAMPLE_FORMAT_DSD_LSBFIRST: /* not implemented */ return false; -- cgit v1.2.3