aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/output/alsa_output_plugin.c2
-rw-r--r--src/output/oss_output_plugin.c1
-rw-r--r--src/pcm_export.c26
-rw-r--r--src/pcm_export.h14
4 files changed, 39 insertions, 4 deletions
diff --git a/src/output/alsa_output_plugin.c b/src/output/alsa_output_plugin.c
index 3788ba0f..f8c34093 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 c32fcead..154930b3 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 68b94b10..0535358f 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 570092eb..7dc9f5f0 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.