From 20e64b39da4b5997b26220fa9424942ca0943db4 Mon Sep 17 00:00:00 2001 From: Julian Bouzas Date: Wed, 8 Sep 2021 09:07:49 -0400 Subject: [PATCH] fmtconvert: add support for U16, U24, U32 and U24_32 formats --- spa/plugins/audioconvert/fmt-ops-c.c | 232 ++++++++++++++++++++++++ spa/plugins/audioconvert/fmt-ops.c | 24 +++ spa/plugins/audioconvert/fmt-ops.h | 64 +++++++ spa/plugins/audioconvert/fmtconvert.c | 7 +- spa/plugins/audioconvert/test-fmt-ops.c | 110 +++++++++++ 5 files changed, 436 insertions(+), 1 deletion(-) diff --git a/spa/plugins/audioconvert/fmt-ops-c.c b/spa/plugins/audioconvert/fmt-ops-c.c index c21602172..401bbeb0b 100644 --- a/spa/plugins/audioconvert/fmt-ops-c.c +++ b/spa/plugins/audioconvert/fmt-ops-c.c @@ -239,6 +239,34 @@ conv_ulaw_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void } } +void +conv_u16_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const uint16_t *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = U16_TO_F32(s[i]); +} + +void +conv_u16_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const uint16_t *s = src[0]; + float **d = (float **) dst; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + d[i][j] = U16_TO_F32(*s++); + } +} + void conv_s16d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) @@ -309,6 +337,34 @@ conv_s16d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * } } +void +conv_u32_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const uint32_t *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = U32_TO_F32(s[i]); +} + +void +conv_u32_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const uint32_t *s = src[0]; + float **d = (float **) dst; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + d[i][j] = U32_TO_F32(*s++); + } +} + void conv_s32d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) @@ -380,6 +436,38 @@ conv_s32d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * } } +void +conv_u24_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const uint8_t *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) { + d[i] = U24_TO_F32(read_u24(s)); + s += 3; + } +} + +void +conv_u24_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const uint8_t *s = src[0]; + float **d = (float **) dst; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) { + d[i][j] = U24_TO_F32(read_u24(s)); + s += 3; + } + } +} + void conv_s24d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) @@ -460,6 +548,35 @@ conv_s24d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * } } +void +conv_u24_32_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const uint32_t *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) { + d[i] = U24_32_TO_F32(s[i]); + } +} + +void +conv_u24_32_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const uint32_t *s = src[0]; + float **d = (float **) dst; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + d[i][j] = U24_32_TO_F32(*s++); + } +} + void conv_s24_32d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) @@ -674,6 +791,33 @@ conv_f32d_to_ulaw_c(struct convert *conv, void * SPA_RESTRICT dst[], const void } } +void +conv_f32_to_u16_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const float *s = src[0]; + uint16_t *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = F32_TO_U16(s[i]); +} +void +conv_f32d_to_u16_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const float **s = (const float **) src; + uint16_t *d = dst[0]; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + *d++ = F32_TO_U16(s[i][j]); + } +} + void conv_f32d_to_s16d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) @@ -745,6 +889,34 @@ conv_f32d_to_s16s_c(struct convert *conv, void * SPA_RESTRICT dst[], const void } } +void +conv_f32_to_u32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const float *s = src[0]; + uint32_t *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = F32_TO_U32(s[i]); +} + +void +conv_f32d_to_u32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const float **s = (const float **) src; + uint32_t *d = dst[0]; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + *d++ = F32_TO_U32(s[i][j]); + } +} + void conv_f32d_to_s32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) @@ -816,6 +988,38 @@ conv_f32d_to_s32s_c(struct convert *conv, void * SPA_RESTRICT dst[], const void } } +void +conv_f32_to_u24_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const float *s = src[0]; + uint8_t *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) { + write_u24(d, F32_TO_U24(s[i])); + d += 3; + } +} + +void +conv_f32d_to_u24_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const float **s = (const float **) src; + uint8_t *d = dst[0]; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) { + write_u24(d, F32_TO_U24(s[i][j])); + d += 3; + } + } +} + void conv_f32d_to_s24d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) @@ -912,6 +1116,34 @@ conv_f32d_to_s24_32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const vo } } +void +conv_f32_to_u24_32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const float *s = src[0]; + uint32_t *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = F32_TO_U24_32(s[i]); +} + +void +conv_f32d_to_u24_32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const float **s = (const float **) src; + uint32_t *d = dst[0]; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + *d++ = F32_TO_U24_32(s[i][j]); + } +} + void conv_f32_to_s24_32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) diff --git a/spa/plugins/audioconvert/fmt-ops.c b/spa/plugins/audioconvert/fmt-ops.c index f8f26cfa6..a8c8cf022 100644 --- a/spa/plugins/audioconvert/fmt-ops.c +++ b/spa/plugins/audioconvert/fmt-ops.c @@ -60,6 +60,9 @@ static struct conv_info conv_table[] = { SPA_AUDIO_FORMAT_ALAW, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_alaw_to_f32d_c }, { SPA_AUDIO_FORMAT_ULAW, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_ulaw_to_f32d_c }, + { SPA_AUDIO_FORMAT_U16, SPA_AUDIO_FORMAT_F32, 0, 0, conv_u16_to_f32_c }, + { SPA_AUDIO_FORMAT_U16, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_u16_to_f32d_c }, + { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32, 0, 0, conv_s16_to_f32_c }, { SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s16d_to_f32d_c }, #if defined (HAVE_NEON) @@ -86,6 +89,9 @@ static struct conv_info conv_table[] = { SPA_AUDIO_FORMAT_F32_OE, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_deinterleave_32s_c }, { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32_OE, 0, 0, conv_interleave_32s_c }, + { SPA_AUDIO_FORMAT_U32, SPA_AUDIO_FORMAT_F32, 0, 0, conv_u32_to_f32_c }, + { SPA_AUDIO_FORMAT_U32, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_u32_to_f32d_c }, + #if defined (HAVE_AVX2) { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32P, 0, SPA_CPU_FLAG_AVX2, conv_s32_to_f32d_avx2 }, #endif @@ -99,6 +105,9 @@ static struct conv_info conv_table[] = { SPA_AUDIO_FORMAT_S32_OE, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s32s_to_f32d_c }, + { SPA_AUDIO_FORMAT_U24, SPA_AUDIO_FORMAT_F32, 0, 0, conv_u24_to_f32_c }, + { SPA_AUDIO_FORMAT_U24, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_u24_to_f32d_c }, + { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32, 0, 0, conv_s24_to_f32_c }, { SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s24d_to_f32d_c }, #if defined (HAVE_AVX2) @@ -118,6 +127,9 @@ static struct conv_info conv_table[] = { SPA_AUDIO_FORMAT_S24_OE, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s24s_to_f32d_c }, + { SPA_AUDIO_FORMAT_U24_32, SPA_AUDIO_FORMAT_F32, 0, 0, conv_u24_32_to_f32_c }, + { SPA_AUDIO_FORMAT_U24_32, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_u24_32_to_f32d_c }, + { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_F32, 0, 0, conv_s24_32_to_f32_c }, { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s24_32d_to_f32d_c }, { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s24_32_to_f32d_c }, @@ -139,6 +151,9 @@ static struct conv_info conv_table[] = { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_ALAW, 0, 0, conv_f32d_to_alaw_c }, { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_ULAW, 0, 0, conv_f32d_to_ulaw_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U16, 0, 0, conv_f32_to_u16_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U16, 0, 0, conv_f32d_to_u16_c }, + #if defined (HAVE_SSE2) { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S16, 0, SPA_CPU_FLAG_SSE2, conv_f32_to_s16_sse2 }, #endif @@ -167,6 +182,9 @@ static struct conv_info conv_table[] = { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S16_OE, 0, 0, conv_f32d_to_s16s_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U32, 0, 0, conv_f32_to_u32_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U32, 0, 0, conv_f32d_to_u32_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S32, 0, 0, conv_f32_to_s32_c }, { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32P, 0, 0, conv_f32d_to_s32d_c }, { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S32P, 0, 0, conv_f32_to_s32d_c }, @@ -180,6 +198,9 @@ static struct conv_info conv_table[] = { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32_OE, 0, 0, conv_f32d_to_s32s_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U24, 0, 0, conv_f32_to_u24_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U24, 0, 0, conv_f32d_to_u24_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24, 0, 0, conv_f32_to_s24_c }, { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24P, 0, 0, conv_f32d_to_s24d_c }, { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24P, 0, 0, conv_f32_to_s24d_c }, @@ -187,6 +208,9 @@ static struct conv_info conv_table[] = { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24_OE, 0, 0, conv_f32d_to_s24s_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U24_32, 0, 0, conv_f32_to_u24_32_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U24_32, 0, 0, conv_f32d_to_u24_32_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24_32, 0, 0, conv_f32_to_s24_32_c }, { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24_32P, 0, 0, conv_f32d_to_s24_32d_c }, { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24_32P, 0, 0, conv_f32_to_s24_32d_c }, diff --git a/spa/plugins/audioconvert/fmt-ops.h b/spa/plugins/audioconvert/fmt-ops.h index ff448d013..235063a00 100644 --- a/spa/plugins/audioconvert/fmt-ops.h +++ b/spa/plugins/audioconvert/fmt-ops.h @@ -41,6 +41,15 @@ #define S8_TO_F32(v) (((int8_t)(v)) * (1.0f / S8_SCALE)) #define F32_TO_S8(v) (int8_t)(SPA_CLAMP(v, -1.0f, 1.0f) * S8_SCALE) +#define U16_MIN 0 +#define U16_MAX 65535 +#define U16_SCALE 32767.5f +#define U16_OFFS 32768 +#define U16_TO_F32(v) ((((uint16_t)(v)) * (1.0f / U16_OFFS)) - 1.0) +#define U16S_TO_F32(v) (((uint16_t)bswap_16((uint16_t)(v)) * (1.0f / U16_OFFS)) - 1.0) +#define F32_TO_U16(v) (uint16_t)((SPA_CLAMP(v, -1.0f, 1.0f) * U16_SCALE) + U16_OFFS) +#define F32_TO_U16S(v) ((uint16_t)bswap_16((uint16_t)((SPA_CLAMP(v, -1.0f, 1.0f) * U16_SCALE) + U16_OFFS))) + #define S16_MIN -32767 #define S16_MAX 32767 #define S16_MAX_F 32767.0f @@ -50,6 +59,13 @@ #define F32_TO_S16(v) (int16_t)(SPA_CLAMP(v, -1.0f, 1.0f) * S16_SCALE) #define F32_TO_S16S(v) ((int16_t)bswap_16((uint16_t)(SPA_CLAMP(v, -1.0f, 1.0f) * S16_SCALE))) +#define U24_MIN 0 +#define U24_MAX 16777215 +#define U24_SCALE 8388607.5f +#define U24_OFFS 8388608 +#define U24_TO_F32(v) ((((uint32_t)(v)) * (1.0f / U24_OFFS)) - 1.0) +#define F32_TO_U24(v) (uint32_t)((SPA_CLAMP(v, -1.0f, 1.0f) * U24_SCALE) + U24_OFFS) + #define S24_MIN -8388607 #define S24_MAX 8388607 #define S24_MAX_F 8388607.0f @@ -57,6 +73,9 @@ #define S24_TO_F32(v) (((int32_t)(v)) * (1.0f / S24_SCALE)) #define F32_TO_S24(v) (int32_t)(SPA_CLAMP(v, -1.0f, 1.0f) * S24_SCALE) +#define U32_TO_F32(v) U24_TO_F32(((uint32_t)(v)) >> 8) +#define F32_TO_U32(v) (F32_TO_U24(v) << 8) + #define S32_SCALE 2147483648.0f #define S32_MIN 2147483520.0f @@ -65,11 +84,26 @@ #define F32_TO_S32(v) (F32_TO_S24(v) << 8) #define F32_TO_S32S(v) bswap_32((F32_TO_S24(v) << 8)) +#define U24_32_TO_F32(v) U32_TO_F32((v)<<8) +#define U24_32S_TO_F32(v) U32_TO_F32(((int32_t)bswap_32(v))<<8) +#define F32_TO_U24_32(v) F32_TO_U24(v) +#define F32_TO_U24_32S(v) bswap_32(F32_TO_U24(v)) + #define S24_32_TO_F32(v) S32_TO_F32((v)<<8) #define S24_32S_TO_F32(v) S32_TO_F32(((int32_t)bswap_32(v))<<8) #define F32_TO_S24_32(v) F32_TO_S24(v) #define F32_TO_S24_32S(v) bswap_32(F32_TO_S24(v)) +static inline uint32_t read_u24(const void *src) +{ + const uint8_t *s = src; +#if __BYTE_ORDER == __LITTLE_ENDIAN + return (((uint32_t)s[2] << 16) | ((uint32_t)(uint8_t)s[1] << 8) | (uint32_t)(uint8_t)s[0]); +#else + return (((uint32_t)s[0] << 16) | ((uint32_t)(uint8_t)s[1] << 8) | (uint32_t)(uint8_t)s[2]); +#endif +} + static inline int32_t read_s24(const void *src) { const int8_t *s = src; @@ -90,6 +124,20 @@ static inline int32_t read_s24s(const void *src) #endif } +static inline void write_u24(void *dst, uint32_t val) +{ + uint8_t *d = dst; +#if __BYTE_ORDER == __LITTLE_ENDIAN + d[0] = (uint8_t) (val); + d[1] = (uint8_t) (val >> 8); + d[2] = (uint8_t) (val >> 16); +#else + d[0] = (uint8_t) (val >> 16); + d[1] = (uint8_t) (val >> 8); + d[2] = (uint8_t) (val); +#endif +} + static inline void write_s24(void *dst, int32_t val) { uint8_t *d = dst; @@ -163,21 +211,29 @@ DEFINE_FUNCTION(s8_to_f32d, c); DEFINE_FUNCTION(s8d_to_f32, c); DEFINE_FUNCTION(ulaw_to_f32d, c); DEFINE_FUNCTION(alaw_to_f32d, c); +DEFINE_FUNCTION(u16_to_f32, c); +DEFINE_FUNCTION(u16_to_f32d, c); DEFINE_FUNCTION(s16d_to_f32d, c); DEFINE_FUNCTION(s16_to_f32, c); DEFINE_FUNCTION(s16_to_f32d, c); DEFINE_FUNCTION(s16s_to_f32d, c); DEFINE_FUNCTION(s16d_to_f32, c); +DEFINE_FUNCTION(u32_to_f32, c); +DEFINE_FUNCTION(u32_to_f32d, c); DEFINE_FUNCTION(s32d_to_f32d, c); DEFINE_FUNCTION(s32_to_f32, c); DEFINE_FUNCTION(s32_to_f32d, c); DEFINE_FUNCTION(s32s_to_f32d, c); DEFINE_FUNCTION(s32d_to_f32, c); +DEFINE_FUNCTION(u24_to_f32, c); +DEFINE_FUNCTION(u24_to_f32d, c); DEFINE_FUNCTION(s24d_to_f32d, c); DEFINE_FUNCTION(s24_to_f32, c); DEFINE_FUNCTION(s24_to_f32d, c); DEFINE_FUNCTION(s24s_to_f32d, c); DEFINE_FUNCTION(s24d_to_f32, c); +DEFINE_FUNCTION(u24_32_to_f32, c); +DEFINE_FUNCTION(u24_32_to_f32d, c); DEFINE_FUNCTION(s24_32d_to_f32d, c); DEFINE_FUNCTION(s24_32_to_f32, c); DEFINE_FUNCTION(s24_32_to_f32d, c); @@ -193,21 +249,29 @@ DEFINE_FUNCTION(f32_to_s8d, c); DEFINE_FUNCTION(f32d_to_s8, c); DEFINE_FUNCTION(f32d_to_alaw, c); DEFINE_FUNCTION(f32d_to_ulaw, c); +DEFINE_FUNCTION(f32_to_u16, c); +DEFINE_FUNCTION(f32d_to_u16, c); DEFINE_FUNCTION(f32d_to_s16d, c); DEFINE_FUNCTION(f32_to_s16, c); DEFINE_FUNCTION(f32_to_s16d, c); DEFINE_FUNCTION(f32d_to_s16, c); DEFINE_FUNCTION(f32d_to_s16s, c); +DEFINE_FUNCTION(f32_to_u32, c); +DEFINE_FUNCTION(f32d_to_u32, c); DEFINE_FUNCTION(f32d_to_s32d, c); DEFINE_FUNCTION(f32_to_s32, c); DEFINE_FUNCTION(f32_to_s32d, c); DEFINE_FUNCTION(f32d_to_s32, c); DEFINE_FUNCTION(f32d_to_s32s, c); +DEFINE_FUNCTION(f32_to_u24, c); +DEFINE_FUNCTION(f32d_to_u24, c); DEFINE_FUNCTION(f32d_to_s24d, c); DEFINE_FUNCTION(f32_to_s24, c); DEFINE_FUNCTION(f32_to_s24d, c); DEFINE_FUNCTION(f32d_to_s24, c); DEFINE_FUNCTION(f32d_to_s24s, c); +DEFINE_FUNCTION(f32_to_u24_32, c); +DEFINE_FUNCTION(f32d_to_u24_32, c); DEFINE_FUNCTION(f32d_to_s24_32d, c); DEFINE_FUNCTION(f32_to_s24_32, c); DEFINE_FUNCTION(f32_to_s24_32d, c); diff --git a/spa/plugins/audioconvert/fmtconvert.c b/spa/plugins/audioconvert/fmtconvert.c index aeeaf8525..ebea18f4c 100644 --- a/spa/plugins/audioconvert/fmtconvert.c +++ b/spa/plugins/audioconvert/fmtconvert.c @@ -398,7 +398,7 @@ static int port_enum_formats(void *object, info.info.raw.format == SPA_AUDIO_FORMAT_F32P || info.info.raw.format == SPA_AUDIO_FORMAT_F32) { spa_pod_builder_add(builder, - SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(22, + SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(26, info.info.raw.format, SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32, @@ -406,15 +406,19 @@ static int port_enum_formats(void *object, SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32_OE, + SPA_AUDIO_FORMAT_U32, SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32_OE, + SPA_AUDIO_FORMAT_U24_32, SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_S24_OE, + SPA_AUDIO_FORMAT_U24, SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16_OE, + SPA_AUDIO_FORMAT_U16, SPA_AUDIO_FORMAT_S8P, SPA_AUDIO_FORMAT_S8, SPA_AUDIO_FORMAT_U8P, @@ -613,6 +617,7 @@ static int calc_width(struct spa_audio_info *info) case SPA_AUDIO_FORMAT_S24P: case SPA_AUDIO_FORMAT_S24: case SPA_AUDIO_FORMAT_S24_OE: + case SPA_AUDIO_FORMAT_U24: return 3; default: return 4; diff --git a/spa/plugins/audioconvert/test-fmt-ops.c b/spa/plugins/audioconvert/test-fmt-ops.c index 7ad73bfa6..46a51ff65 100644 --- a/spa/plugins/audioconvert/test-fmt-ops.c +++ b/spa/plugins/audioconvert/test-fmt-ops.c @@ -152,6 +152,28 @@ static void test_u8_f32(void) false, false, conv_u8d_to_f32d_c); } +static void test_f32_u16(void) +{ + static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; + static const uint16_t out[] = { 32767, 65535, 0, 49150, 16383, 65535, 0 }; + + run_test("test_f32_u16", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_f32_to_u16_c); + run_test("test_f32d_u16", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + false, true, conv_f32d_to_u16_c); +} + +static void test_u16_f32(void) +{ + static const int16_t in[] = { 32767, 65535, 0, 49150, 16383, }; + static const float out[] = { 0.0f, 1.0f, -1.0f, 0.4999847412f, -0.4999847412f }; + + run_test("test_u16_f32d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, false, conv_u16_to_f32d_c); + run_test("test_u16_f32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_u16_to_f32_c); +} + static void test_f32_s16(void) { static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; @@ -194,6 +216,29 @@ static void test_s16_f32(void) #endif } +static void test_f32_u32(void) +{ + static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; + static const uint32_t out[] = { 0, 0x7fffff00, 0x80000100, 0x3fffff00, 0xc0000100, + 0x7fffff00, 0x80000100 }; + + run_test("test_f32_u32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_f32_to_u32_c); + run_test("test_f32d_u32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + false, true, conv_f32d_to_u32_c); +} + +static void test_u32_f32(void) +{ + static const uint32_t in[] = { 0, 0x7fffff00, 0x80000100, 0x3fffff00, 0xc0000100 }; + static const float out[] = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + + run_test("test_u32_f32d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, false, conv_u32_to_f32d_c); + run_test("test_u32_f32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_u32_to_f32_c); +} + static void test_f32_s32(void) { static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; @@ -237,6 +282,40 @@ static void test_s32_f32(void) #endif } +static void test_f32_u24(void) +{ + static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; +#if __BYTE_ORDER == __LITTLE_ENDIAN + static const uint8_t out[] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80, + 0xff, 0xff, 0x3f, 0x01, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80 }; +#else + static const uint8_t out[] = { 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01, + 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x01, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01 }; +#endif + + run_test("test_f32_u24", in, sizeof(in[0]), out, 3, SPA_N_ELEMENTS(in), + true, true, conv_f32_to_u24_c); + run_test("test_f32d_u24", in, sizeof(in[0]), out, 3, SPA_N_ELEMENTS(in), + false, true, conv_f32d_to_u24_c); +} + +static void test_u24_f32(void) +{ +#if __BYTE_ORDER == __LITTLE_ENDIAN + static const uint8_t in[] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x80, + 0xff, 0xff, 0x3f, 0x01, 0x00, 0xc0, }; +#else + static const uint8_t in[] = { 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x01, + 0x3f, 0xff, 0xff, 0xc0, 0x00, 0x01, }; +#endif + static const float out[] = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + + run_test("test_u24_f32d", in, 3, out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, false, conv_u24_to_f32d_c); + run_test("test_u24_f32", in, 3, out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_u24_to_f32_c); +} + static void test_f32_s24(void) { static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; @@ -297,6 +376,29 @@ static void test_s24_f32(void) #endif } +static void test_f32_u24_32(void) +{ + static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; + static const uint32_t out[] = { 0, 0x7fffff, 0xff800001, 0x3fffff, 0xffc00001, + 0x7fffff, 0xff800001 }; + + run_test("test_f32_u24_32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_f32_to_u24_32_c); + run_test("test_f32d_u24_32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + false, true, conv_f32d_to_u24_32_c); +} + +static void test_u24_32_f32(void) +{ + static const uint32_t in[] = { 0, 0x7fffff, 0xff800001, 0x3fffff, 0xffc00001 }; + static const float out[] = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + + run_test("test_u24_32_f32d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, false, conv_u24_32_to_f32d_c); + run_test("test_u24_32_f32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_u24_32_to_f32_c); +} + static void test_f32_s24_32(void) { static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; @@ -335,12 +437,20 @@ int main(int argc, char *argv[]) test_f32_u8(); test_u8_f32(); + test_f32_u16(); + test_u16_f32(); test_f32_s16(); test_s16_f32(); + test_f32_u32(); + test_u32_f32(); test_f32_s32(); test_s32_f32(); + test_f32_u24(); + test_u24_f32(); test_f32_s24(); test_s24_f32(); + test_f32_u24_32(); + test_u24_32_f32(); test_f32_s24_32(); test_s24_32_f32(); return 0;