diff options
author | Max Kellermann <max@duempel.org> | 2012-03-27 01:01:16 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2012-03-27 01:22:50 +0200 |
commit | ddd4f675a2d42b0c8156e03bf3e93f39df2fe609 (patch) | |
tree | 248c44242b11e721eeb03fcb74c601fd12fdec39 | |
parent | d271dd2cce79d1473f43f7ad7e6815b74617dfe3 (diff) | |
download | mpd-ddd4f675a2d42b0c8156e03bf3e93f39df2fe609.tar.gz mpd-ddd4f675a2d42b0c8156e03bf3e93f39df2fe609.tar.xz mpd-ddd4f675a2d42b0c8156e03bf3e93f39df2fe609.zip |
pcm_export: implement 24 to 32 bit conversion
For 32 bit DSD-over-USB support.
-rw-r--r-- | src/output/alsa_output_plugin.c | 2 | ||||
-rw-r--r-- | src/output/oss_output_plugin.c | 2 | ||||
-rw-r--r-- | src/pcm_export.c | 18 | ||||
-rw-r--r-- | src/pcm_export.h | 8 |
4 files changed, 26 insertions, 4 deletions
diff --git a/src/output/alsa_output_plugin.c b/src/output/alsa_output_plugin.c index 00ddbfb5c..c9dd1ee1b 100644 --- a/src/output/alsa_output_plugin.c +++ b/src/output/alsa_output_plugin.c @@ -634,7 +634,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, packed, reverse_endian); + dsd_usb, false, packed, reverse_endian); return true; } diff --git a/src/output/oss_output_plugin.c b/src/output/oss_output_plugin.c index 85bdc37dc..f59ee3b92 100644 --- a/src/output/oss_output_plugin.c +++ b/src/output/oss_output_plugin.c @@ -540,7 +540,7 @@ oss_probe_sample_format(int fd, enum sample_format sample_format, *oss_format_r = oss_format; #ifdef AFMT_S24_PACKED - pcm_export_open(export, sample_format, 0, false, + pcm_export_open(export, sample_format, 0, false, false, oss_format == AFMT_S24_PACKED, oss_format == AFMT_S24_PACKED && G_BYTE_ORDER != G_LITTLE_ENDIAN); diff --git a/src/pcm_export.c b/src/pcm_export.c index 66ed6d351..dbd9f2e8e 100644 --- a/src/pcm_export.c +++ b/src/pcm_export.c @@ -41,7 +41,7 @@ void pcm_export_deinit(struct pcm_export_state *state) void pcm_export_open(struct pcm_export_state *state, enum sample_format sample_format, unsigned channels, - bool dsd_usb, bool pack, bool reverse_endian) + bool dsd_usb, bool shift8, bool pack, bool reverse_endian) { assert(audio_valid_sample_format(sample_format)); assert(!dsd_usb || audio_valid_channel_count(channels)); @@ -53,8 +53,11 @@ pcm_export_open(struct pcm_export_state *state, samples are stuffed inside fake 24 bit samples */ sample_format = SAMPLE_FORMAT_S24_P32; + state->shift8 = shift8 && sample_format == SAMPLE_FORMAT_S24_P32; state->pack24 = pack && (sample_format == SAMPLE_FORMAT_S24_P32 || sample_format == SAMPLE_FORMAT_DSD_OVER_USB); + assert(!state->shift8 || !state->pack24); + state->reverse_endian = 0; if (reverse_endian) { size_t sample_size = state->pack24 @@ -90,8 +93,21 @@ pcm_export(struct pcm_export_state *state, const void *data, size_t size, data = dest; size = dest_size; + } else if (state->shift8) { + assert(size % 4 == 0); + + const uint8_t *src8 = data, *src_end8 = src8 + size; + const uint32_t *src = (const uint32_t *)src8; + const uint32_t *const src_end = (const uint32_t *)src_end8; + + uint32_t *dest = pcm_buffer_get(&state->pack_buffer, size); + data = dest; + + while (src < src_end) + *dest++ = *src++ << 8; } + if (state->reverse_endian > 0) { assert(state->reverse_endian >= 2); diff --git a/src/pcm_export.h b/src/pcm_export.h index c132c7169..418dcdfa3 100644 --- a/src/pcm_export.h +++ b/src/pcm_export.h @@ -69,6 +69,12 @@ struct pcm_export_state { bool dsd_usb; /** + * Convert (padded) 24 bit samples to 32 bit by shifting 8 + * bits to the left? + */ + bool shift8; + + /** * Pack 24 bit samples? */ bool pack24; @@ -106,7 +112,7 @@ pcm_export_deinit(struct pcm_export_state *state); void pcm_export_open(struct pcm_export_state *state, enum sample_format sample_format, unsigned channels, - bool dsd_usb, bool pack, bool reverse_endian); + bool dsd_usb, bool shift8, bool pack, bool reverse_endian); /** * Export a PCM buffer. |