diff --git a/spa/plugins/audioconvert/fmt-ops-c.c b/spa/plugins/audioconvert/fmt-ops-c.c index e92b5bf31..800951ce0 100644 --- a/spa/plugins/audioconvert/fmt-ops-c.c +++ b/spa/plugins/audioconvert/fmt-ops-c.c @@ -411,3 +411,53 @@ MAKE_INTERLEAVE(24, 24, uint24_t, (uint24_t)); MAKE_INTERLEAVE(32, 32, uint32_t, (uint32_t)); MAKE_INTERLEAVE(32, 32s, uint32_t, bswap_32); MAKE_INTERLEAVE(64, 64, uint64_t, (uint64_t)); + +#define MAKE_CLEAR(size) \ +void conv_clear_ ##size## d_c(struct convert *conv, \ + void * SPA_RESTRICT dst[], uint32_t n_samples) \ +{ \ + uint32_t i, n_channels = conv->n_channels; \ + for (i = 0; i < n_channels; i++) \ + memset(dst[i], 0, n_samples * (size>>3)); \ +} \ +void conv_clear_ ##size## _c(struct convert *conv, \ + void * SPA_RESTRICT dst[], uint32_t n_samples) \ +{ \ + memset(dst[0], 0, n_samples * conv->n_channels * (size>>3)); \ +} + +MAKE_CLEAR(8); +MAKE_CLEAR(16); +MAKE_CLEAR(24); +MAKE_CLEAR(32); +MAKE_CLEAR(64); + +#define MAKE_CLEAR_VAL(size,dtype,val) \ +void conv_clear_ ##size## d_c(struct convert *conv, \ + void * SPA_RESTRICT dst[], uint32_t n_samples) \ +{ \ + uint32_t i, j, n_channels = conv->n_channels; \ + for (i = 0; i < n_channels; i++) { \ + dtype *d = dst[i]; \ + for (j = 0; j < n_samples; j++) \ + d[j] = val; \ + } \ +} \ +void conv_clear_ ##size## _c(struct convert *conv, \ + void * SPA_RESTRICT dst[], uint32_t n_samples) \ +{ \ + uint32_t j; \ + dtype *d = dst[0]; \ + n_samples *= conv->n_channels; \ + for (j = 0; j < n_samples; j++) \ + d[j] = val; \ +} + +MAKE_CLEAR_VAL(alaw, uint8_t, 0x55); +MAKE_CLEAR_VAL(ulaw, uint8_t, 0xff); +MAKE_CLEAR_VAL(u8, uint8_t, 0x80); +MAKE_CLEAR_VAL(u16, uint16_t, 0x8000); +MAKE_CLEAR_VAL(u24, uint24_t, U32_TO_U24(0x800000)); +MAKE_CLEAR_VAL(u24_32, uint32_t, 0x800000); +MAKE_CLEAR_VAL(u32, uint32_t, 0x80000000); + diff --git a/spa/plugins/audioconvert/fmt-ops.c b/spa/plugins/audioconvert/fmt-ops.c index 4df31323a..3296c220b 100644 --- a/spa/plugins/audioconvert/fmt-ops.c +++ b/spa/plugins/audioconvert/fmt-ops.c @@ -376,6 +376,64 @@ static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt return NULL; } + +typedef void (*clear_func_t) (struct convert *conv, void * SPA_RESTRICT dst[], + uint32_t n_samples); + +struct clear_info { + uint32_t fmt; + + clear_func_t clear; + const char *name; + + uint32_t cpu_flags; +}; + +#define MAKE(fmt,func,...) \ + { SPA_AUDIO_FORMAT_ ##fmt, func, #func , __VA_ARGS__ } + +static struct clear_info clear_table[] = +{ + MAKE(U8, conv_clear_u8_c), + MAKE(U8P, conv_clear_u8d_c), + MAKE(S8, conv_clear_8_c), + MAKE(S8P, conv_clear_8d_c), + MAKE(U16, conv_clear_u16_c), + MAKE(S16, conv_clear_16_c), + MAKE(S16_OE, conv_clear_16_c), + MAKE(S16P, conv_clear_16d_c), + MAKE(U24, conv_clear_u24_c), + MAKE(S24, conv_clear_24_c), + MAKE(S24_OE, conv_clear_24_c), + MAKE(S24P, conv_clear_24d_c), + MAKE(U24_32, conv_clear_u24_32_c), + MAKE(S24_32, conv_clear_32_c), + MAKE(S24_32_OE, conv_clear_32_c), + MAKE(U32, conv_clear_u32_c), + MAKE(S32, conv_clear_32_c), + MAKE(S32_OE, conv_clear_32_c), + MAKE(S32P, conv_clear_32d_c), + MAKE(F32, conv_clear_32_c), + MAKE(F32_OE, conv_clear_32_c), + MAKE(F32P, conv_clear_32d_c), + MAKE(F64, conv_clear_64_c), + MAKE(F64_OE, conv_clear_64_c), + MAKE(F64P, conv_clear_64d_c), + MAKE(ALAW, conv_clear_alaw_c), + MAKE(ULAW, conv_clear_ulaw_c), +}; +#undef MAKE + +static const struct clear_info *find_clear_info(uint32_t fmt, uint32_t cpu_flags) +{ + SPA_FOR_EACH_ELEMENT_VAR(clear_table, c) { + if (c->fmt == fmt && + MATCH_CPU_FLAGS(c->cpu_flags, cpu_flags)) + return c; + } + return NULL; +} + typedef void (*noise_func_t) (struct convert *conv, float * noise, uint32_t n_samples); struct noise_info { @@ -492,6 +550,7 @@ int convert_init(struct convert *conv) const struct conv_info *info; const struct dither_info *dinfo; const struct noise_info *ninfo; + const struct clear_info *cinfo; uint32_t i, conv_flags, data_size[3]; /* we generate int32 bits of random values. With this scale @@ -549,6 +608,8 @@ int convert_init(struct convert *conv) if (ninfo == NULL) return -ENOTSUP; + cinfo = find_clear_info(conv->dst_fmt, conv->cpu_flags); + conv->noise_size = NOISE_SIZE; data_size[0] = SPA_ROUND_UP(conv->noise_size * sizeof(float), FMT_OPS_MAX_ALIGN); @@ -571,6 +632,7 @@ int convert_init(struct convert *conv) conv->cpu_flags = info->cpu_flags; conv->update_noise = ninfo->noise; conv->process = info->process; + conv->clear = cinfo ? cinfo->clear : NULL; conv->free = impl_convert_free; conv->func_name = info->name; diff --git a/spa/plugins/audioconvert/fmt-ops.h b/spa/plugins/audioconvert/fmt-ops.h index 7aed0bc65..9f4655c22 100644 --- a/spa/plugins/audioconvert/fmt-ops.h +++ b/spa/plugins/audioconvert/fmt-ops.h @@ -241,6 +241,7 @@ struct convert { void (*update_noise) (struct convert *conv, float *noise, uint32_t n_samples); void (*process) (struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples); + void (*clear) (struct convert *conv, void * SPA_RESTRICT dst[], uint32_t n_samples); void (*free) (struct convert *conv); void *data; @@ -278,6 +279,7 @@ static inline uint32_t dither_method_from_label(const char *label) #define convert_update_noise(conv,...) (conv)->update_noise(conv, __VA_ARGS__) #define convert_process(conv,...) (conv)->process(conv, __VA_ARGS__) +#define convert_clear(conv,...) (conv)->clear(conv, __VA_ARGS__) #define convert_free(conv) (conv)->free(conv) #define DEFINE_NOISE_FUNCTION(name,arch) \ @@ -490,3 +492,28 @@ DEFINE_FUNCTION(f32d_to_s16, avx2); #endif #undef DEFINE_FUNCTION + +#define DEFINE_CLEAR_FUNCTION(name,arch) \ +void conv_clear_##name##_##arch(struct convert *conv, void * SPA_RESTRICT dst[], \ + uint32_t n_samples) + +DEFINE_CLEAR_FUNCTION(alaw, c); +DEFINE_CLEAR_FUNCTION(ulaw, c); +DEFINE_CLEAR_FUNCTION(8, c); +DEFINE_CLEAR_FUNCTION(8d, c); +DEFINE_CLEAR_FUNCTION(16, c); +DEFINE_CLEAR_FUNCTION(16d, c); +DEFINE_CLEAR_FUNCTION(24, c); +DEFINE_CLEAR_FUNCTION(24d, c); +DEFINE_CLEAR_FUNCTION(32, c); +DEFINE_CLEAR_FUNCTION(32d, c); +DEFINE_CLEAR_FUNCTION(64, c); +DEFINE_CLEAR_FUNCTION(64d, c); +DEFINE_CLEAR_FUNCTION(u8, c); +DEFINE_CLEAR_FUNCTION(u8d, c); +DEFINE_CLEAR_FUNCTION(u16, c); +DEFINE_CLEAR_FUNCTION(u24, c); +DEFINE_CLEAR_FUNCTION(u24_32, c); +DEFINE_CLEAR_FUNCTION(u32, c); + +#undef DEFINE_CLEAR_FUNCTION