diff options
-rw-r--r-- | src/output/alsa_output_plugin.c | 2 | ||||
-rw-r--r-- | src/output/oss_output_plugin.c | 1 | ||||
-rw-r--r-- | src/pcm_export.c | 26 | ||||
-rw-r--r-- | src/pcm_export.h | 14 |
4 files changed, 39 insertions, 4 deletions
diff --git a/src/output/alsa_output_plugin.c b/src/output/alsa_output_plugin.c index 3788ba0f2..f8c34093b 100644 --- a/src/output/alsa_output_plugin.c +++ b/src/output/alsa_output_plugin.c @@ -525,7 +525,7 @@ configure_hw: ad->period_position = 0; pcm_export_open(&ad->export, audio_format->format, - reverse_endian); + false, reverse_endian); return true; diff --git a/src/output/oss_output_plugin.c b/src/output/oss_output_plugin.c index c32fceade..154930b38 100644 --- a/src/output/oss_output_plugin.c +++ b/src/output/oss_output_plugin.c @@ -536,6 +536,7 @@ oss_probe_sample_format(int fd, enum sample_format sample_format, #ifdef AFMT_S24_PACKED pcm_export_open(export, sample_format, + false, oss_format == AFMT_S24_PACKED && G_BYTE_ORDER != G_LITTLE_ENDIAN); #endif diff --git a/src/pcm_export.c b/src/pcm_export.c index 68b94b10a..0535358fc 100644 --- a/src/pcm_export.c +++ b/src/pcm_export.c @@ -19,6 +19,7 @@ #include "config.h" #include "pcm_export.h" +#include "pcm_pack.h" #include "util/byte_reverse.h" void @@ -35,11 +36,15 @@ void pcm_export_deinit(struct pcm_export_state *state) void pcm_export_open(struct pcm_export_state *state, enum sample_format sample_format, - bool reverse_endian) + bool pack, bool reverse_endian) { + state->pack24 = pack && sample_format == SAMPLE_FORMAT_S24_P32; + state->reverse_endian = 0; if (reverse_endian) { - size_t sample_size = sample_format_size(sample_format); + size_t sample_size = state->pack24 + ? 3 + : sample_format_size(sample_format); assert(sample_size <= 0xff); if (sample_size > 1) @@ -51,6 +56,23 @@ const void * pcm_export(struct pcm_export_state *state, const void *data, size_t size, size_t *dest_size_r) { + if (state->pack24) { + assert(size % 4 == 0); + + const size_t num_samples = size / 4; + const size_t dest_size = num_samples * 3; + + const uint8_t *src8 = data, *src_end8 = src8 + size; + uint8_t *dest = pcm_buffer_get(&state->pack_buffer, dest_size); + assert(dest != NULL); + + pcm_pack_24(dest, (const int32_t *)src8, + (const int32_t *)src_end8); + + data = dest; + size = dest_size; + } + if (state->reverse_endian > 0) { assert(state->reverse_endian >= 2); diff --git a/src/pcm_export.h b/src/pcm_export.h index 570092eb9..7dc9f5f03 100644 --- a/src/pcm_export.h +++ b/src/pcm_export.h @@ -35,6 +35,13 @@ struct audio_format; */ struct pcm_export_state { /** + * The buffer used to pack samples, removing padding. + * + * @see #reverse_endian + */ + struct pcm_buffer pack_buffer; + + /** * The buffer used to reverse the byte order. * * @see #reverse_endian @@ -42,6 +49,11 @@ struct pcm_export_state { struct pcm_buffer reverse_buffer; /** + * Pack 24 bit samples? + */ + bool pack24; + + /** * Export the samples in reverse byte order? A non-zero value * means the option is enabled and represents the size of each * sample (2 or bigger). @@ -72,7 +84,7 @@ pcm_export_deinit(struct pcm_export_state *state); void pcm_export_open(struct pcm_export_state *state, enum sample_format sample_format, - bool reverse_endian); + bool pack, bool reverse_endian); /** * Export a PCM buffer. |