From d8e399dee926dc309ed9ad2819112c531d44cd0e Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 29 Mar 2019 17:39:59 +0100 Subject: [PATCH] audioconvert: pass state to functions Pass some state to convert and channelmix functions. This makes it possible to select per channel optimized convert functions but also makes it possible to implement noise shaping later. Pass the channelmix matrix and volume in the state. Handle specialized 2 channel s16 -> f32 conversion --- spa/plugins/audioconvert/benchmark-fmt-ops.c | 7 +- spa/plugins/audioconvert/channelmix-ops-c.c | 130 +++---- spa/plugins/audioconvert/channelmix-ops-sse.c | 71 ++-- spa/plugins/audioconvert/channelmix-ops.c | 286 +++++++++++++- spa/plugins/audioconvert/channelmix-ops.h | 38 +- spa/plugins/audioconvert/channelmix.c | 273 ++------------ spa/plugins/audioconvert/fmt-ops-c.c | 354 ++++++++++++------ spa/plugins/audioconvert/fmt-ops-sse2.c | 100 ++--- spa/plugins/audioconvert/fmt-ops-sse41.c | 20 +- spa/plugins/audioconvert/fmt-ops-ssse3.c | 15 +- spa/plugins/audioconvert/fmt-ops.c | 182 +++++---- spa/plugins/audioconvert/fmt-ops.h | 30 +- spa/plugins/audioconvert/fmtconvert.c | 33 +- spa/plugins/audioconvert/merger.c | 35 +- spa/plugins/audioconvert/meson.build | 12 +- spa/plugins/audioconvert/splitter.c | 36 +- spa/plugins/audioconvert/test-fmt-ops.c | 15 +- 17 files changed, 952 insertions(+), 685 deletions(-) diff --git a/spa/plugins/audioconvert/benchmark-fmt-ops.c b/spa/plugins/audioconvert/benchmark-fmt-ops.c index 5304dd978..a7e4ecadd 100644 --- a/spa/plugins/audioconvert/benchmark-fmt-ops.c +++ b/spa/plugins/audioconvert/benchmark-fmt-ops.c @@ -63,6 +63,9 @@ static void run_test1(const char *name, const char *impl, bool in_packed, bool o void *op[n_channels]; struct timespec ts; uint64_t count, t1, t2; + struct convert conv; + + conv.n_channels = n_channels; for (j = 0; j < n_channels; j++) { ip[j] = &samp_in[j * n_samples * 4]; @@ -74,7 +77,7 @@ static void run_test1(const char *name, const char *impl, bool in_packed, bool o count = 0; for (i = 0; i < MAX_COUNT; i++) { - func(NULL, op, ip, n_channels, n_samples); + func(&conv, op, ip, n_samples); count++; } clock_gettime(CLOCK_MONOTONIC, &ts); @@ -223,8 +226,6 @@ int main(int argc, char *argv[]) { uint32_t i; - find_conv_info(0, 0, 0); - test_f32_u8(); test_u8_f32(); test_f32_s16(); diff --git a/spa/plugins/audioconvert/channelmix-ops-c.c b/spa/plugins/audioconvert/channelmix-ops-c.c index 05301cf26..522196158 100644 --- a/spa/plugins/audioconvert/channelmix-ops-c.c +++ b/spa/plugins/audioconvert/channelmix-ops-c.c @@ -25,13 +25,13 @@ #include "channelmix-ops.h" void -channelmix_copy_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_copy_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n; + uint32_t i, n; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; if (v <= VOLUME_MIN) { for (i = 0; i < n_dst; i++) @@ -51,14 +51,14 @@ channelmix_copy_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], #define _M(ch) (1UL << SPA_AUDIO_CHANNEL_ ## ch) void -channelmix_f32_n_m_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_n_m_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, j, n; + uint32_t i, j, n; float **d = (float **) dst; const float **s = (const float **) src; - const float *m = matrix; + const float *m = mix->matrix; + float v = mix->volume; for (n = 0; n < n_samples; n++) { for (i = 0; i < n_dst; i++) { @@ -74,13 +74,13 @@ channelmix_f32_n_m_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], #define MASK_STEREO _M(FL)|_M(FR)|_M(UNKNOWN) void -channelmix_f32_1_2_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int n; + uint32_t n; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; if (v <= VOLUME_MIN) { memset(d[0], 0, n_samples * sizeof(float)); @@ -97,13 +97,13 @@ channelmix_f32_1_2_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], } void -channelmix_f32_2_1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_2_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int n; + uint32_t n; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; if (v <= VOLUME_MIN) { memset(d[0], 0, n_samples * sizeof(float)); @@ -116,13 +116,13 @@ channelmix_f32_2_1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], } void -channelmix_f32_4_1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_4_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int n; + uint32_t n; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; if (v <= VOLUME_MIN) { memset(d[0], 0, n_samples * sizeof(float)); @@ -135,13 +135,13 @@ channelmix_f32_4_1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], } void -channelmix_f32_3p1_1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_3p1_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int n; + uint32_t n; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; if (v <= VOLUME_MIN) { memset(d[0], 0, n_samples * sizeof(float)); @@ -157,13 +157,13 @@ channelmix_f32_3p1_1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], #define MASK_QUAD _M(FL)|_M(FR)|_M(RL)|_M(RR)|_M(UNKNOWN) void -channelmix_f32_2_4_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_2_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n; + uint32_t i, n; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; if (v <= VOLUME_MIN) { for (i = 0; i < n_dst; i++) @@ -185,13 +185,13 @@ channelmix_f32_2_4_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], #define MASK_3_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE) void -channelmix_f32_2_3p1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_2_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n; + uint32_t i, n; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; if (v <= VOLUME_MIN) { for (i = 0; i < n_dst; i++) @@ -218,13 +218,13 @@ channelmix_f32_2_3p1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], #define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) void -channelmix_f32_2_5p1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_2_5p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n; + uint32_t i, n; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; if (v <= VOLUME_MIN) { for (i = 0; i < n_dst; i++) @@ -251,17 +251,17 @@ channelmix_f32_2_5p1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], /* FL+FR+FC+LFE+SL+SR -> FL+FR */ void -channelmix_f32_5p1_2_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_5p1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int n; + uint32_t n; float **d = (float **) dst; const float **s = (const float **) src; - const float *m = matrix; + const float *m = mix->matrix; const float clev = m[2]; const float llev = m[3]; const float slev = m[4]; + float v = mix->volume; if (v <= VOLUME_MIN) { memset(d[0], 0, n_samples * sizeof(float)); @@ -285,13 +285,13 @@ channelmix_f32_5p1_2_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], /* FL+FR+FC+LFE+SL+SR -> FL+FR+FC+LFE*/ void -channelmix_f32_5p1_3p1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_5p1_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n; + uint32_t i, n; float **d = (float **) dst; const float **s = (const float **) src; + float v = mix->volume; if (v <= VOLUME_MIN) { for (i = 0; i < n_dst; i++) @@ -310,16 +310,16 @@ channelmix_f32_5p1_3p1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], /* FL+FR+FC+LFE+SL+SR -> FL+FR+RL+RR*/ void -channelmix_f32_5p1_4_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_5p1_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n; + uint32_t i, n; float **d = (float **) dst; const float **s = (const float **) src; - const float *m = matrix; + const float *m = mix->matrix; const float clev = m[2]; const float llev = m[3]; + float v = mix->volume; if (v <= VOLUME_MIN) { for (i = 0; i < n_dst; i++) @@ -349,17 +349,17 @@ channelmix_f32_5p1_4_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], /* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR */ void -channelmix_f32_7p1_2_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_7p1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int n; + uint32_t n; float **d = (float **) dst; const float **s = (const float **) src; - const float *m = matrix; + const float *m = mix->matrix; const float clev = m[2]; const float llev = m[3]; const float slev = m[4]; + float v = mix->volume; if (v <= VOLUME_MIN) { memset(d[0], 0, n_samples * sizeof(float)); @@ -383,13 +383,13 @@ channelmix_f32_7p1_2_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], /* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR+FC+LFE*/ void -channelmix_f32_7p1_3p1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_7p1_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n; + uint32_t i, n; float **d = (float **) dst; const float **s = (const float **) src; + float v = mix->volume; if (v <= VOLUME_MIN) { for (i = 0; i < n_dst; i++) @@ -408,17 +408,17 @@ channelmix_f32_7p1_3p1_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], /* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR+RL+RR*/ void -channelmix_f32_7p1_4_c(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_7p1_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n; + uint32_t i, n; float **d = (float **) dst; const float **s = (const float **) src; - const float *m = matrix; + const float *m = mix->matrix; const float clev = m[2]; const float llev = m[3]; const float slev = m[4]; + float v = mix->volume; if (v <= VOLUME_MIN) { for (i = 0; i < n_dst; i++) diff --git a/spa/plugins/audioconvert/channelmix-ops-sse.c b/spa/plugins/audioconvert/channelmix-ops-sse.c index 77043e7a4..78e53e298 100644 --- a/spa/plugins/audioconvert/channelmix-ops-sse.c +++ b/spa/plugins/audioconvert/channelmix-ops-sse.c @@ -26,14 +26,13 @@ #include -void -channelmix_copy_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +void channelmix_copy_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n, unrolled; + uint32_t i, n, unrolled; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; const __m128 vol = _mm_set1_ps(v); if (v <= VOLUME_MIN) { @@ -73,13 +72,13 @@ channelmix_copy_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], } void -channelmix_f32_2_4_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_2_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n, unrolled; + uint32_t i, n, unrolled; float **d = (float **)dst; const float **s = (const float **)src; + float v = mix->volume; const __m128 vol = _mm_set1_ps(v); __m128 in; const float *sFL = s[0], *sFR = s[1]; @@ -139,14 +138,14 @@ channelmix_f32_2_4_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], /* FL+FR+FC+LFE+SL+SR -> FL+FR */ void -channelmix_f32_5p1_2_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_5p1_2_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int n, unrolled; + uint32_t n, unrolled; float **d = (float **) dst; const float **s = (const float **) src; - const float *m = matrix; + float v = mix->volume; + const float *m = mix->matrix; const __m128 clev = _mm_set1_ps(m[2]); const __m128 llev = _mm_set1_ps(m[3]); const __m128 slev = _mm_set1_ps(m[4]); @@ -231,14 +230,14 @@ channelmix_f32_5p1_2_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], /* FL+FR+FC+LFE+SL+SR -> FL+FR+FC+LFE*/ void -channelmix_f32_5p1_3p1_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_5p1_3p1_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n, unrolled; + uint32_t i, n, unrolled; float **d = (float **) dst; const float **s = (const float **) src; - const __m128 mix = _mm_set1_ps(v * 0.5f); + float v = mix->volume; + const __m128 slev = _mm_set1_ps(v * 0.5f); const __m128 vol = _mm_set1_ps(v); __m128 avg[2]; const float *sFL = s[0], *sFR = s[1], *sFC = s[2], *sLFE = s[3], *sSL = s[4], *sSR = s[5]; @@ -266,12 +265,12 @@ channelmix_f32_5p1_3p1_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst] for(n = 0; n < unrolled; n += 8) { avg[0] = _mm_add_ps(_mm_load_ps(&sFL[n]), _mm_load_ps(&sSL[n])); avg[1] = _mm_add_ps(_mm_load_ps(&sFL[n+4]), _mm_load_ps(&sSL[n+4])); - _mm_store_ps(&dFL[n], _mm_mul_ps(avg[0], mix)); - _mm_store_ps(&dFL[n+4], _mm_mul_ps(avg[1], mix)); + _mm_store_ps(&dFL[n], _mm_mul_ps(avg[0], slev)); + _mm_store_ps(&dFL[n+4], _mm_mul_ps(avg[1], slev)); avg[0] = _mm_add_ps(_mm_load_ps(&sFR[n]), _mm_load_ps(&sSR[n])); avg[1] = _mm_add_ps(_mm_load_ps(&sFR[n+4]), _mm_load_ps(&sSR[n+4])); - _mm_store_ps(&dFR[n], _mm_mul_ps(avg[0], mix)); - _mm_store_ps(&dFR[n+4], _mm_mul_ps(avg[1], mix)); + _mm_store_ps(&dFR[n], _mm_mul_ps(avg[0], slev)); + _mm_store_ps(&dFR[n+4], _mm_mul_ps(avg[1], slev)); _mm_store_ps(&dFC[n], _mm_load_ps(&sFC[n])); _mm_store_ps(&dFC[n+4], _mm_load_ps(&sFC[n+4])); _mm_store_ps(&dLFE[n], _mm_load_ps(&sLFE[n])); @@ -279,9 +278,9 @@ channelmix_f32_5p1_3p1_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst] } for(; n < n_samples; n++) { avg[0] = _mm_add_ss(_mm_load_ss(&sFL[n]), _mm_load_ss(&sSL[n])); - _mm_store_ss(&dFL[n], _mm_mul_ss(avg[0], mix)); + _mm_store_ss(&dFL[n], _mm_mul_ss(avg[0], slev)); avg[0] = _mm_add_ss(_mm_load_ss(&sFR[n]), _mm_load_ss(&sSR[n])); - _mm_store_ss(&dFR[n], _mm_mul_ss(avg[0], mix)); + _mm_store_ss(&dFR[n], _mm_mul_ss(avg[0], slev)); _mm_store_ss(&dFC[n], _mm_load_ss(&sFC[n])); _mm_store_ss(&dLFE[n], _mm_load_ss(&sLFE[n])); } @@ -290,12 +289,12 @@ channelmix_f32_5p1_3p1_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst] for(n = 0; n < unrolled; n += 8) { avg[0] = _mm_add_ps(_mm_load_ps(&sFL[n]), _mm_load_ps(&sSL[n])); avg[1] = _mm_add_ps(_mm_load_ps(&sFL[n+4]), _mm_load_ps(&sSL[n+4])); - _mm_store_ps(&dFL[n], _mm_mul_ps(avg[0], mix)); - _mm_store_ps(&dFL[n+4], _mm_mul_ps(avg[1], mix)); + _mm_store_ps(&dFL[n], _mm_mul_ps(avg[0], slev)); + _mm_store_ps(&dFL[n+4], _mm_mul_ps(avg[1], slev)); avg[0] = _mm_add_ps(_mm_load_ps(&sFR[n]), _mm_load_ps(&sSR[n])); avg[1] = _mm_add_ps(_mm_load_ps(&sFR[n+4]), _mm_load_ps(&sSR[n+4])); - _mm_store_ps(&dFR[n], _mm_mul_ps(avg[0], mix)); - _mm_store_ps(&dFR[n+4], _mm_mul_ps(avg[1], mix)); + _mm_store_ps(&dFR[n], _mm_mul_ps(avg[0], slev)); + _mm_store_ps(&dFR[n+4], _mm_mul_ps(avg[1], slev)); _mm_store_ps(&dFC[n], _mm_mul_ps(_mm_load_ps(&sFC[n]), vol)); _mm_store_ps(&dFC[n+4], _mm_mul_ps(_mm_load_ps(&sFC[n+4]), vol)); _mm_store_ps(&dLFE[n], _mm_mul_ps(_mm_load_ps(&sLFE[n]), vol)); @@ -303,9 +302,9 @@ channelmix_f32_5p1_3p1_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst] } for(; n < n_samples; n++) { avg[0] = _mm_add_ss(_mm_load_ss(&sFL[n]), _mm_load_ss(&sSL[n])); - _mm_store_ss(&dFL[n], _mm_mul_ss(avg[0], mix)); + _mm_store_ss(&dFL[n], _mm_mul_ss(avg[0], slev)); avg[0] = _mm_add_ss(_mm_load_ss(&sFR[n]), _mm_load_ss(&sSR[n])); - _mm_store_ss(&dFR[n], _mm_mul_ss(avg[0], mix)); + _mm_store_ss(&dFR[n], _mm_mul_ss(avg[0], slev)); _mm_store_ss(&dFC[n], _mm_mul_ss(_mm_load_ss(&sFC[n]), vol)); _mm_store_ss(&dLFE[n], _mm_mul_ss(_mm_load_ss(&sLFE[n]), vol)); } @@ -314,14 +313,14 @@ channelmix_f32_5p1_3p1_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst] /* FL+FR+FC+LFE+SL+SR -> FL+FR+RL+RR*/ void -channelmix_f32_5p1_4_sse(void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void *matrix, float v, int n_samples) +channelmix_f32_5p1_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples) { - int i, n, unrolled; + uint32_t i, n, unrolled; float **d = (float **) dst; const float **s = (const float **) src; - const float *m = matrix; + const float *m = mix->matrix; + float v = mix->volume; const __m128 clev = _mm_set1_ps(m[2]); const __m128 llev = _mm_set1_ps(m[3]); const __m128 vol = _mm_set1_ps(v); diff --git a/spa/plugins/audioconvert/channelmix-ops.c b/spa/plugins/audioconvert/channelmix-ops.c index 6b88d7382..d9b2897d7 100644 --- a/spa/plugins/audioconvert/channelmix-ops.c +++ b/spa/plugins/audioconvert/channelmix-ops.c @@ -24,8 +24,11 @@ #include #include +#include +#include #include +#include #include #define VOLUME_MIN 0.0f @@ -41,29 +44,26 @@ #define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) #define MASK_7_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) -typedef void (*channelmix_func_t) (void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void * SPA_RESTRICT matrix, float v, int n_samples); - - #define ANY ((uint32_t)-1) #define EQ ((uint32_t)-2) +typedef void (*channelmix_func_t) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples); + static const struct channelmix_info { uint32_t src_chan; uint64_t src_mask; uint32_t dst_chan; uint64_t dst_mask; - channelmix_func_t func; -#define FEATURE_SSE SPA_CPU_FLAG_SSE - uint32_t features; + channelmix_func_t process; + uint32_t cpu_flags; } channelmix_table[] = { #if defined (HAVE_SSE) - { 2, MASK_MONO, 2, MASK_MONO, channelmix_copy_sse, FEATURE_SSE }, - { 2, MASK_STEREO, 2, MASK_STEREO, channelmix_copy_sse, FEATURE_SSE }, - { EQ, 0, EQ, 0, channelmix_copy_sse, FEATURE_SSE }, + { 2, MASK_MONO, 2, MASK_MONO, channelmix_copy_sse, SPA_CPU_FLAG_SSE }, + { 2, MASK_STEREO, 2, MASK_STEREO, channelmix_copy_sse, SPA_CPU_FLAG_SSE }, + { EQ, 0, EQ, 0, channelmix_copy_sse, SPA_CPU_FLAG_SSE }, #endif { 2, MASK_MONO, 2, MASK_MONO, channelmix_copy_c, 0 }, { 2, MASK_STEREO, 2, MASK_STEREO, channelmix_copy_c, 0 }, @@ -74,22 +74,22 @@ static const struct channelmix_info { { 4, MASK_QUAD, 1, MASK_MONO, channelmix_f32_4_1_c, 0 }, { 4, MASK_3_1, 1, MASK_MONO, channelmix_f32_3p1_1_c, 0 }, #if defined (HAVE_SSE) - { 2, MASK_STEREO, 4, MASK_QUAD, channelmix_f32_2_4_sse, FEATURE_SSE }, + { 2, MASK_STEREO, 4, MASK_QUAD, channelmix_f32_2_4_sse, SPA_CPU_FLAG_SSE }, #endif { 2, MASK_STEREO, 4, MASK_QUAD, channelmix_f32_2_4_c, 0 }, { 2, MASK_STEREO, 4, MASK_3_1, channelmix_f32_2_3p1_c, 0 }, { 2, MASK_STEREO, 6, MASK_5_1, channelmix_f32_2_5p1_c, 0 }, #if defined (HAVE_SSE) - { 6, MASK_5_1, 2, MASK_STEREO, channelmix_f32_5p1_2_sse, FEATURE_SSE }, + { 6, MASK_5_1, 2, MASK_STEREO, channelmix_f32_5p1_2_sse, SPA_CPU_FLAG_SSE }, #endif { 6, MASK_5_1, 2, MASK_STEREO, channelmix_f32_5p1_2_c, 0 }, #if defined (HAVE_SSE) - { 6, MASK_5_1, 4, MASK_QUAD, channelmix_f32_5p1_4_sse, FEATURE_SSE }, + { 6, MASK_5_1, 4, MASK_QUAD, channelmix_f32_5p1_4_sse, SPA_CPU_FLAG_SSE }, #endif { 6, MASK_5_1, 4, MASK_QUAD, channelmix_f32_5p1_4_c, 0 }, #if defined (HAVE_SSE) - { 6, MASK_5_1, 4, MASK_3_1, channelmix_f32_5p1_3p1_sse, FEATURE_SSE }, + { 6, MASK_5_1, 4, MASK_3_1, channelmix_f32_5p1_3p1_sse, SPA_CPU_FLAG_SSE }, #endif { 6, MASK_5_1, 4, MASK_3_1, channelmix_f32_5p1_3p1_c, 0 }, @@ -101,15 +101,15 @@ static const struct channelmix_info { }; #define MATCH_CHAN(a,b) ((a) == ANY || (a) == (b)) -#define MATCH_FEATURES(a,b) ((a) == 0 || ((a) & (b)) != 0) +#define MATCH_CPU_FLAGS(a,b) ((a) == 0 || ((a) & (b)) == a) #define MATCH_MASK(a,b) ((a) == 0 || ((a) & (b)) == (b)) static const struct channelmix_info *find_channelmix_info(uint32_t src_chan, uint64_t src_mask, - uint32_t dst_chan, uint64_t dst_mask, uint32_t features) + uint32_t dst_chan, uint64_t dst_mask, uint32_t cpu_flags) { size_t i; for (i = 0; i < SPA_N_ELEMENTS(channelmix_table); i++) { - if (!MATCH_FEATURES(channelmix_table[i].features, features)) + if (!MATCH_CPU_FLAGS(channelmix_table[i].cpu_flags, cpu_flags)) continue; if (src_chan == dst_chan && src_mask == dst_mask) @@ -123,3 +123,253 @@ static const struct channelmix_info *find_channelmix_info(uint32_t src_chan, uin } return NULL; } + +#define M 0 +#define FL 1 +#define FR 2 +#define FC 3 +#define LFE 4 +#define SL 5 +#define SR 6 +#define FLC 7 +#define FRC 8 +#define RC 9 +#define RL 10 +#define RR 11 +#define TC 12 +#define TFL 13 +#define TFC 14 +#define TFR 15 +#define TRL 16 +#define TRC 17 +#define TRR 18 +#define NUM_CHAN 19 + +#define SQRT3_2 1.224744871f /* sqrt(3/2) */ +#define SQRT1_2 0.707106781f +#define SQRT2 1.414213562f + +#define MATRIX_NORMAL 0 +#define MATRIX_DOLBY 1 +#define MATRIX_DPLII 2 + +#define _MASK(ch) (1ULL << SPA_AUDIO_CHANNEL_ ## ch) +#define STEREO (_MASK(FL)|_MASK(FR)) + +static int make_matrix(struct channelmix *mix) +{ + float matrix[NUM_CHAN][NUM_CHAN] = {{ 0.0f }}; + uint32_t src_chan = mix->src_chan; + uint64_t src_mask = mix->src_mask; + uint32_t dst_chan = mix->dst_chan; + uint64_t dst_mask = mix->dst_mask; + uint64_t unassigned; + uint32_t i, j, matrix_encoding = MATRIX_NORMAL, c; + float clev = SQRT1_2; + float slev = SQRT1_2; + float llev = 0.5f; + float max = 0.0f; + + for (i = 0; i < NUM_CHAN; i++) { + if (src_mask & dst_mask & (1ULL << (i + 2))) + matrix[i][i]= 1.0f; + } + + if ((dst_mask & _MASK(MONO)) == _MASK(MONO)) + dst_mask = _MASK(FC); + + unassigned = src_mask & ~dst_mask; + + spa_log_debug(mix->log, "unassigned %08lx", unassigned); + + if (unassigned & _MASK(FC)){ + if ((dst_mask & STEREO) == STEREO){ + if(src_mask & STEREO) { + matrix[FL][FC] += clev; + matrix[FR][FC] += clev; + } else { + matrix[FL][FC] += SQRT1_2; + matrix[FR][FC] += SQRT1_2; + } + } else { + spa_log_warn(mix->log, "can't assign FC"); + } + } + + if (unassigned & STEREO){ + if (dst_mask & _MASK(FC)) { + matrix[FC][FL] += SQRT1_2; + matrix[FC][FR] += SQRT1_2; + if (src_mask & _MASK(FC)) + matrix[FC][FC] = clev * SQRT2; + } else { + spa_log_warn(mix->log, "can't assign STEREO"); + } + } + + if (unassigned & _MASK(RC)) { + if (dst_mask & _MASK(RL)){ + matrix[RL][RC] += SQRT1_2; + matrix[RR][RC] += SQRT1_2; + } else if (dst_mask & _MASK(SL)) { + matrix[SL][RC] += SQRT1_2; + matrix[SR][RC] += SQRT1_2; + } else if(dst_mask & _MASK(FL)) { + if (matrix_encoding == MATRIX_DOLBY || + matrix_encoding == MATRIX_DPLII) { + if (unassigned & (_MASK(RL)|_MASK(RR))) { + matrix[FL][RC] -= slev * SQRT1_2; + matrix[FR][RC] += slev * SQRT1_2; + } else { + matrix[FL][RC] -= slev; + matrix[FR][RC] += slev; + } + } else { + matrix[FL][RC] += slev * SQRT1_2; + matrix[FR][RC] += slev * SQRT1_2; + } + } else if (dst_mask & _MASK(FC)) { + matrix[FC][RC] += slev * SQRT1_2; + } else { + spa_log_warn(mix->log, "can't assign RC"); + } + } + + if (unassigned & _MASK(RL)) { + if (dst_mask & _MASK(RC)) { + matrix[RC][RL] += SQRT1_2; + matrix[RC][RR] += SQRT1_2; + } else if (dst_mask & _MASK(SL)) { + if (src_mask & _MASK(SL)) { + matrix[SL][RL] += SQRT1_2; + matrix[SR][RR] += SQRT1_2; + } else { + matrix[SL][RL] += 1.0f; + matrix[SR][RR] += 1.0f; + } + } else if (dst_mask & _MASK(FL)) { + if (matrix_encoding == MATRIX_DOLBY) { + matrix[FL][RL] -= slev * SQRT1_2; + matrix[FL][RR] -= slev * SQRT1_2; + matrix[FR][RL] += slev * SQRT1_2; + matrix[FR][RR] += slev * SQRT1_2; + } else if (matrix_encoding == MATRIX_DPLII) { + matrix[FL][RL] -= slev * SQRT3_2; + matrix[FL][RR] -= slev * SQRT1_2; + matrix[FR][RL] += slev * SQRT1_2; + matrix[FR][RR] += slev * SQRT3_2; + } else { + matrix[FL][RL] += slev; + matrix[FR][RR] += slev; + } + } else if (dst_mask & _MASK(FC)) { + matrix[FC][RL]+= slev * SQRT1_2; + matrix[FC][RR]+= slev * SQRT1_2; + } else { + spa_log_warn(mix->log, "can't assign RL"); + } + } + + if (unassigned & _MASK(SL)) { + if (dst_mask & _MASK(RL)) { + if (src_mask & _MASK(RL)) { + matrix[RL][SL] += SQRT1_2; + matrix[RR][SR] += SQRT1_2; + } else { + matrix[RL][SL] += 1.0f; + matrix[RR][SR] += 1.0f; + } + } else if (dst_mask & _MASK(RC)) { + matrix[RC][SL]+= SQRT1_2; + matrix[RC][SR]+= SQRT1_2; + } else if (dst_mask & _MASK(FL)) { + if (matrix_encoding == MATRIX_DOLBY) { + matrix[FL][SL] -= slev * SQRT1_2; + matrix[FL][SR] -= slev * SQRT1_2; + matrix[FR][SL] += slev * SQRT1_2; + matrix[FR][SR] += slev * SQRT1_2; + } else if (matrix_encoding == MATRIX_DPLII) { + matrix[FL][SL] -= slev * SQRT3_2; + matrix[FL][SR] -= slev * SQRT1_2; + matrix[FR][SL] += slev * SQRT1_2; + matrix[FR][SR] += slev * SQRT3_2; + } else { + matrix[FL][SL] += slev; + matrix[FR][SR] += slev; + } + } else if (dst_mask & _MASK(FC)) { + matrix[FC][SL] += slev * SQRT1_2; + matrix[FC][SR] += slev * SQRT1_2; + } else { + spa_log_warn(mix->log, "can't assign SL"); + } + } + + if (unassigned & _MASK(FLC)) { + if (dst_mask & _MASK(FL)) { + matrix[FC][FLC]+= 1.0f; + matrix[FC][FRC]+= 1.0f; + } else if(dst_mask & _MASK(FC)) { + matrix[FC][FLC]+= SQRT1_2; + matrix[FC][FRC]+= SQRT1_2; + } else { + spa_log_warn(mix->log, "can't assign FLC"); + } + } + if (unassigned & _MASK(LFE)) { + if (dst_mask & _MASK(FC)) { + matrix[FC][LFE] += llev; + } else if (dst_mask & _MASK(FL)) { + matrix[FL][LFE] += llev * SQRT1_2; + matrix[FR][LFE] += llev * SQRT1_2; + } else { + spa_log_warn(mix->log, "can't assign LFE"); + } + } + + c = 0; + for (i = 0; i < NUM_CHAN; i++) { + float sum = 0.0f; + if ((dst_mask & (1UL << (i + 2))) == 0) + continue; + for (j = 0; j < NUM_CHAN; j++) { + if ((src_mask & (1UL << (j + 2))) == 0) + continue; + mix->matrix[c++] = matrix[i][j]; + sum += fabs(matrix[i][j]); + } + max = SPA_MAX(max, sum); + } + + mix->is_identity = dst_chan == src_chan; + for (i = 0; i < dst_chan; i++) { + for (j = 0; j < src_chan; j++) { + float v = mix->matrix[i * src_chan + j]; + spa_log_debug(mix->log, "%d %d: %f", i, j, v); + if ((i == j && v != 1.0f) || + (i != j && v != 0.0f)) + mix->is_identity = false; + } + } + return 0; +} + +static void impl_channelmix_free(struct channelmix *mix) +{ + mix->process = NULL; +} + +int channelmix_init(struct channelmix *mix) +{ + const struct channelmix_info *info; + + info = find_channelmix_info(mix->src_chan, mix->src_mask, mix->dst_chan, mix->dst_mask, + mix->cpu_flags); + if (info == NULL) + return -ENOTSUP; + + mix->free = impl_channelmix_free; + mix->process = info->process; + mix->cpu_flags = info->cpu_flags; + return make_matrix(mix); +} diff --git a/spa/plugins/audioconvert/channelmix-ops.h b/spa/plugins/audioconvert/channelmix-ops.h index 5cde3bfa2..0ca887d7c 100644 --- a/spa/plugins/audioconvert/channelmix-ops.h +++ b/spa/plugins/audioconvert/channelmix-ops.h @@ -30,6 +30,8 @@ #define VOLUME_MIN 0.0f #define VOLUME_NORM 1.0f +#define MAX_CHANNELS 64 + #define _M(ch) (1UL << SPA_AUDIO_CHANNEL_ ## ch) #define MASK_MONO _M(FC)|_M(MONO)|_M(UNKNOWN) #define MASK_STEREO _M(FL)|_M(FR)|_M(UNKNOWN) @@ -38,15 +40,37 @@ #define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) #define MASK_7_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) -typedef void (*channelmix_func_t) (void *data, int n_dst, void * SPA_RESTRICT dst[n_dst], - int n_src, const void * SPA_RESTRICT src[n_src], - const void * SPA_RESTRICT matrix, float v, int n_samples); + +struct channelmix { + uint32_t src_chan; + uint32_t dst_chan; + uint64_t src_mask; + uint64_t dst_mask; + uint32_t cpu_flags; + + struct spa_log *log; + + int is_identity:1; + float volume; + float matrix[MAX_CHANNELS * MAX_CHANNELS]; + + void (*process) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], + uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples); + void (*free) (struct channelmix *mix); + + void *data; +}; + +int channelmix_init(struct channelmix *mix); + +#define channelmix_process(mix,...) (mix)->process(mix, __VA_ARGS__) +#define channelmix_free(mix) (mix)->free(mix) #define DEFINE_FUNCTION(name,arch) \ -void channelmix_##name##_##arch(void *data, \ - int n_dst, void * SPA_RESTRICT dst[n_dst], \ - int n_src, const void * SPA_RESTRICT src[n_src], \ - const void *matrix, float v, int n_samples); +void channelmix_##name##_##arch(struct channelmix *mix, \ + uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], \ + uint32_t n_src, const void * SPA_RESTRICT src[n_src], \ + uint32_t n_samples); DEFINE_FUNCTION(copy, c); DEFINE_FUNCTION(f32_n_m, c); diff --git a/spa/plugins/audioconvert/channelmix.c b/spa/plugins/audioconvert/channelmix.c index 6a96e623f..b6634ce6a 100644 --- a/spa/plugins/audioconvert/channelmix.c +++ b/spa/plugins/audioconvert/channelmix.c @@ -25,9 +25,10 @@ #include #include #include -#include +//#include #include +#include #include #include #include @@ -95,7 +96,7 @@ struct port { struct spa_list queue; }; -#include "channelmix-ops.c" +#include "channelmix-ops.h" struct impl { struct spa_handle handle; @@ -115,12 +116,10 @@ struct impl { struct port in_port; struct port out_port; - channelmix_func_t convert; + struct channelmix mix; int started:1; int is_passthrough:1; uint32_t cpu_flags; - uint32_t n_matrix; - float matrix[4096]; }; #define CHECK_PORT(this,d,id) (id == 0) @@ -131,35 +130,6 @@ struct impl { #define _MASK(ch) (1ULL << SPA_AUDIO_CHANNEL_ ## ch) #define STEREO (_MASK(FL)|_MASK(FR)) -#define M 0 -#define FL 1 -#define FR 2 -#define FC 3 -#define LFE 4 -#define SL 5 -#define SR 6 -#define FLC 7 -#define FRC 8 -#define RC 9 -#define RL 10 -#define RR 11 -#define TC 12 -#define TFL 13 -#define TFC 14 -#define TFR 15 -#define TRL 16 -#define TRC 17 -#define TRR 18 -#define NUM_CHAN 19 - -#define SQRT3_2 1.224744871f /* sqrt(3/2) */ -#define SQRT1_2 0.707106781f -#define SQRT2 1.414213562f - -#define MATRIX_NORMAL 0 -#define MATRIX_DOLBY 1 -#define MATRIX_DPLII 2 - static uint64_t default_mask(uint32_t channels) { uint64_t mask = 0; @@ -193,210 +163,14 @@ static uint64_t default_mask(uint32_t channels) return mask; } -static int make_matrix(struct impl *this, - uint32_t src_chan, uint64_t src_mask, - uint32_t dst_chan, uint64_t dst_mask) -{ - float matrix[NUM_CHAN][NUM_CHAN] = {{ 0.0f }}; - uint64_t unassigned; - uint32_t i, j, matrix_encoding = MATRIX_NORMAL, c; - float clev = SQRT1_2; - float slev = SQRT1_2; - float llev = 0.5f; - float max = 0.0f; - - for (i = 0; i < NUM_CHAN; i++) { - if (src_mask & dst_mask & (1ULL << (i + 2))) - matrix[i][i]= 1.0f; - } - - if ((dst_mask & _MASK(MONO)) == _MASK(MONO)) - dst_mask = _MASK(FC); - - unassigned = src_mask & ~dst_mask; - - spa_log_debug(this->log, "unassigned %08lx", unassigned); - - if (unassigned & _MASK(FC)){ - if ((dst_mask & STEREO) == STEREO){ - if(src_mask & STEREO) { - matrix[FL][FC] += clev; - matrix[FR][FC] += clev; - } else { - matrix[FL][FC] += SQRT1_2; - matrix[FR][FC] += SQRT1_2; - } - } else { - spa_log_warn(this->log, "can't assign FC"); - } - } - - if (unassigned & STEREO){ - if (dst_mask & _MASK(FC)) { - matrix[FC][FL] += SQRT1_2; - matrix[FC][FR] += SQRT1_2; - if (src_mask & _MASK(FC)) - matrix[FC][FC] = clev * SQRT2; - } else { - spa_log_warn(this->log, "can't assign STEREO"); - } - } - - if (unassigned & _MASK(RC)) { - if (dst_mask & _MASK(RL)){ - matrix[RL][RC] += SQRT1_2; - matrix[RR][RC] += SQRT1_2; - } else if (dst_mask & _MASK(SL)) { - matrix[SL][RC] += SQRT1_2; - matrix[SR][RC] += SQRT1_2; - } else if(dst_mask & _MASK(FL)) { - if (matrix_encoding == MATRIX_DOLBY || - matrix_encoding == MATRIX_DPLII) { - if (unassigned & (_MASK(RL)|_MASK(RR))) { - matrix[FL][RC] -= slev * SQRT1_2; - matrix[FR][RC] += slev * SQRT1_2; - } else { - matrix[FL][RC] -= slev; - matrix[FR][RC] += slev; - } - } else { - matrix[FL][RC] += slev * SQRT1_2; - matrix[FR][RC] += slev * SQRT1_2; - } - } else if (dst_mask & _MASK(FC)) { - matrix[FC][RC] += slev * SQRT1_2; - } else { - spa_log_warn(this->log, "can't assign RC"); - } - } - - if (unassigned & _MASK(RL)) { - if (dst_mask & _MASK(RC)) { - matrix[RC][RL] += SQRT1_2; - matrix[RC][RR] += SQRT1_2; - } else if (dst_mask & _MASK(SL)) { - if (src_mask & _MASK(SL)) { - matrix[SL][RL] += SQRT1_2; - matrix[SR][RR] += SQRT1_2; - } else { - matrix[SL][RL] += 1.0f; - matrix[SR][RR] += 1.0f; - } - } else if (dst_mask & _MASK(FL)) { - if (matrix_encoding == MATRIX_DOLBY) { - matrix[FL][RL] -= slev * SQRT1_2; - matrix[FL][RR] -= slev * SQRT1_2; - matrix[FR][RL] += slev * SQRT1_2; - matrix[FR][RR] += slev * SQRT1_2; - } else if (matrix_encoding == MATRIX_DPLII) { - matrix[FL][RL] -= slev * SQRT3_2; - matrix[FL][RR] -= slev * SQRT1_2; - matrix[FR][RL] += slev * SQRT1_2; - matrix[FR][RR] += slev * SQRT3_2; - } else { - matrix[FL][RL] += slev; - matrix[FR][RR] += slev; - } - } else if (dst_mask & _MASK(FC)) { - matrix[FC][RL]+= slev * SQRT1_2; - matrix[FC][RR]+= slev * SQRT1_2; - } else { - spa_log_warn(this->log, "can't assign RL"); - } - } - - if (unassigned & _MASK(SL)) { - if (dst_mask & _MASK(RL)) { - if (src_mask & _MASK(RL)) { - matrix[RL][SL] += SQRT1_2; - matrix[RR][SR] += SQRT1_2; - } else { - matrix[RL][SL] += 1.0f; - matrix[RR][SR] += 1.0f; - } - } else if (dst_mask & _MASK(RC)) { - matrix[RC][SL]+= SQRT1_2; - matrix[RC][SR]+= SQRT1_2; - } else if (dst_mask & _MASK(FL)) { - if (matrix_encoding == MATRIX_DOLBY) { - matrix[FL][SL] -= slev * SQRT1_2; - matrix[FL][SR] -= slev * SQRT1_2; - matrix[FR][SL] += slev * SQRT1_2; - matrix[FR][SR] += slev * SQRT1_2; - } else if (matrix_encoding == MATRIX_DPLII) { - matrix[FL][SL] -= slev * SQRT3_2; - matrix[FL][SR] -= slev * SQRT1_2; - matrix[FR][SL] += slev * SQRT1_2; - matrix[FR][SR] += slev * SQRT3_2; - } else { - matrix[FL][SL] += slev; - matrix[FR][SR] += slev; - } - } else if (dst_mask & _MASK(FC)) { - matrix[FC][SL] += slev * SQRT1_2; - matrix[FC][SR] += slev * SQRT1_2; - } else { - spa_log_warn(this->log, "can't assign SL"); - } - } - - if (unassigned & _MASK(FLC)) { - if (dst_mask & _MASK(FL)) { - matrix[FC][FLC]+= 1.0f; - matrix[FC][FRC]+= 1.0f; - } else if(dst_mask & _MASK(FC)) { - matrix[FC][FLC]+= SQRT1_2; - matrix[FC][FRC]+= SQRT1_2; - } else { - spa_log_warn(this->log, "can't assign FLC"); - } - } - if (unassigned & _MASK(LFE)) { - if (dst_mask & _MASK(FC)) { - matrix[FC][LFE] += llev; - } else if (dst_mask & _MASK(FL)) { - matrix[FL][LFE] += llev * SQRT1_2; - matrix[FR][LFE] += llev * SQRT1_2; - } else { - spa_log_warn(this->log, "can't assign LFE"); - } - } - - c = 0; - for (i = 0; i < NUM_CHAN; i++) { - float sum = 0.0f; - if ((dst_mask & (1UL << (i + 2))) == 0) - continue; - for (j = 0; j < NUM_CHAN; j++) { - if ((src_mask & (1UL << (j + 2))) == 0) - continue; - this->matrix[c++] = matrix[i][j]; - sum += fabs(matrix[i][j]); - } - max = SPA_MAX(max, sum); - } - this->n_matrix = c; - this->is_passthrough = dst_chan == src_chan; - for (i = 0; i < dst_chan; i++) { - for (j = 0; j < src_chan; j++) { - float v = this->matrix[i * src_chan + j]; - spa_log_debug(this->log, "%d %d: %f", i, j, v); - if (i == j && v != 1.0f) - this->is_passthrough = false; - } - } - - return 0; -} - static int setup_convert(struct impl *this, enum spa_direction direction, const struct spa_audio_info *info) { const struct spa_audio_info *src_info, *dst_info; uint32_t i, src_chan, dst_chan; - const struct channelmix_info *chanmix_info; uint64_t src_mask, dst_mask; + int res; if (direction == SPA_DIRECTION_INPUT) { src_info = info; @@ -431,17 +205,21 @@ static int setup_convert(struct impl *this, if (src_info->info.raw.rate != dst_info->info.raw.rate) return -EINVAL; - /* find convert function */ - if ((chanmix_info = find_channelmix_info(src_chan, src_mask, - dst_chan, dst_mask, this->cpu_flags)) == NULL) - return -ENOTSUP; + this->mix.src_chan = src_chan; + this->mix.src_mask = src_mask; + this->mix.dst_chan = dst_chan; + this->mix.dst_mask = dst_mask; + this->mix.cpu_flags = this->cpu_flags; + this->mix.log = this->log; + this->mix.volume = this->props.mute ? 0.0f : this->props.volume; + + if ((res = channelmix_init(&this->mix)) < 0) + return res; spa_log_info(this->log, NAME " %p: got channelmix features %08x:%08x", - this, this->cpu_flags, chanmix_info->features); + this, this->cpu_flags, this->mix.cpu_flags); - this->convert = chanmix_info->func; - - return make_matrix(this, src_chan, src_mask, dst_chan, dst_mask); + return 0; } static int impl_node_enum_params(struct spa_node *node, int seq, @@ -544,6 +322,9 @@ static int apply_props(struct impl *this, const struct spa_pod *param) break; } } + if (changed) + this->mix.volume = p->mute ? 0.0f : p->volume; + return changed; } @@ -850,7 +631,7 @@ static int port_set_format(struct spa_node *node, port->have_format = false; clear_buffers(this, port); } - this->convert = NULL; + channelmix_free(&this->mix); } else { struct spa_audio_info info = { 0 }; @@ -1131,10 +912,11 @@ static int impl_node_process(struct spa_node *node) const void *src_datas[n_src_datas]; void *dst_datas[n_dst_datas]; bool is_passthrough; - float v; - v = this->props.mute ? 0.0f : this->props.volume; - is_passthrough = this->is_passthrough && v == 1.0f; + is_passthrough = this->is_passthrough && + this->mix.volume == 1.0f && + this->mix.is_identity; + n_samples = sb->datas[0].chunk->size / inport->stride; for (i = 0; i < n_src_datas; i++) @@ -1146,9 +928,8 @@ static int impl_node_process(struct spa_node *node) } if (!is_passthrough) - this->convert(this, n_dst_datas, dst_datas, - n_src_datas, src_datas, - this->matrix, v, n_samples); + channelmix_process(&this->mix, n_dst_datas, dst_datas, + n_src_datas, src_datas, n_samples); } outio->status = SPA_STATUS_HAVE_BUFFER; diff --git a/spa/plugins/audioconvert/fmt-ops-c.c b/spa/plugins/audioconvert/fmt-ops-c.c index ddbd5cc01..3dfe511d2 100644 --- a/spa/plugins/audioconvert/fmt-ops-c.c +++ b/spa/plugins/audioconvert/fmt-ops-c.c @@ -33,66 +33,75 @@ #include "fmt-ops.h" void -conv_copy8d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_copy8d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i; + uint32_t i, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) spa_memcpy(dst[i], src[i], n_samples); } void -conv_copy8_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_copy8_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - spa_memcpy(dst[0], src[0], n_samples * n_channels); + spa_memcpy(dst[0], src[0], n_samples * conv->n_channels); } void -conv_copy16d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_copy16d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i; + uint32_t i, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) spa_memcpy(dst[i], src[i], n_samples * sizeof(int16_t)); } void -conv_copy16_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_copy16_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - spa_memcpy(dst[0], src[0], n_samples * sizeof(int16_t) * n_channels); + spa_memcpy(dst[0], src[0], n_samples * sizeof(int16_t) * conv->n_channels); } void -conv_copy24d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_copy24d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i; + uint32_t i, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) spa_memcpy(dst[i], src[i], n_samples * 3); } void -conv_copy24_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_copy24_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - spa_memcpy(dst[0], src[0], n_samples * 3 * n_channels); + spa_memcpy(dst[0], src[0], n_samples * 3 * conv->n_channels); } void -conv_copy32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_copy32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i; + uint32_t i, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) spa_memcpy(dst[i], src[i], n_samples * sizeof(int32_t)); } void -conv_copy32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_copy32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - spa_memcpy(dst[0], src[0], n_samples * sizeof(int32_t) * n_channels); + spa_memcpy(dst[0], src[0], n_samples * sizeof(int32_t) * conv->n_channels); } void -conv_u8d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_u8d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const uint8_t *s = src[i]; @@ -104,17 +113,26 @@ conv_u8d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_u8_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_u8_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_u8d_to_f32d_c(data, dst, src, 1, n_samples * n_channels); + 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] = U8_TO_F32(s[i]); } void -conv_u8_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_u8_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; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -123,11 +141,12 @@ conv_u8_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRI } void -conv_u8d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_u8d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const uint8_t **s = (const uint8_t **) src; float *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -136,9 +155,10 @@ conv_u8d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRI } void -conv_s16d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s16d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const int16_t *s = src[i]; @@ -149,17 +169,26 @@ conv_s16d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_REST } void -conv_s16_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s16_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_s16d_to_f32d_c(data, dst, src, 1, n_samples * n_channels); + uint32_t i, n_channels = conv->n_channels; + const int16_t *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = S16_TO_F32(s[i]); } void -conv_s16_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s16_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int16_t *s = src[0]; float **d = (float **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -168,11 +197,12 @@ conv_s16_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_s16d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s16d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int16_t **s = (const int16_t **) src; float *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -181,9 +211,10 @@ conv_s16d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_s32d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s32d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const int32_t *s = src[i]; @@ -195,17 +226,26 @@ conv_s32d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_REST } void -conv_s32_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s32_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_s32d_to_f32d_c(data, dst, src, 1, n_samples * n_channels); + uint32_t i, n_channels = conv->n_channels; + const int32_t *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = S32_TO_F32(s[i]); } void -conv_s32_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s32_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int32_t *s = src[0]; float **d = (float **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -214,11 +254,12 @@ conv_s32_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_s32d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s32d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int32_t **s = (const int32_t **) src; float *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -227,9 +268,10 @@ conv_s32d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_s24d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const int8_t *s = src[i]; @@ -243,17 +285,28 @@ conv_s24d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_REST } void -conv_s24_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_s24d_to_f32d_c(data, dst, src, 1, n_samples * n_channels); + uint32_t i, n_channels = conv->n_channels; + const int8_t *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) { + d[i] = S24_TO_F32(read_s24(s)); + s += 3; + } } void -conv_s24_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_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; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) { @@ -264,11 +317,12 @@ conv_s24_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_s24d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const uint8_t **s = (const uint8_t **) src; float *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) { @@ -278,9 +332,10 @@ conv_s24d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_s24_32d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_32d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const int32_t *s = src[i]; @@ -292,17 +347,26 @@ conv_s24_32d_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_R } void -conv_s24_32_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_32_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_s24_32d_to_f32d_c(data, dst, src, 1, n_samples * n_channels); + uint32_t i, n_channels = conv->n_channels; + const int32_t *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = S24_TO_F32(s[i]); } void -conv_s24_32_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_32_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int32_t *s = src[0]; float **d = (float **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -311,11 +375,12 @@ conv_s24_32_to_f32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RE } void -conv_s24_32d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_32d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int32_t **s = (const int32_t **) src; float *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -324,9 +389,10 @@ conv_s24_32d_to_f32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RE } void -conv_f32d_to_u8d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_u8d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const float *s = src[i]; @@ -338,17 +404,26 @@ conv_f32d_to_u8d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_f32_to_u8_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_u8_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_f32d_to_u8d_c(data, dst, src, 1, n_samples * n_channels); + 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++) + d[i] = F32_TO_U8(s[i]); } void -conv_f32_to_u8d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_u8d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const float *s = src[0]; uint8_t **d = (uint8_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -357,11 +432,12 @@ conv_f32_to_u8d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRI } void -conv_f32d_to_u8_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_u8_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; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -370,9 +446,10 @@ conv_f32d_to_u8_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRI } void -conv_f32d_to_s16d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s16d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const float *s = src[i]; @@ -384,17 +461,26 @@ conv_f32d_to_s16d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_REST } void -conv_f32_to_s16_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_s16_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_f32d_to_s16d_c(data, dst, src, 1, n_samples * n_channels); + uint32_t i, n_channels = conv->n_channels; + const float *s = src[0]; + int16_t *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = F32_TO_S16(s[i]); } void -conv_f32_to_s16d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_s16d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const float *s = src[0]; int16_t **d = (int16_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -403,11 +489,12 @@ conv_f32_to_s16d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_f32d_to_s16_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s16_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const float **s = (const float **) src; int16_t *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -416,9 +503,10 @@ conv_f32d_to_s16_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_f32d_to_s32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const float *s = src[i]; @@ -430,17 +518,26 @@ conv_f32d_to_s32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_REST } void -conv_f32_to_s32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_s32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_f32d_to_s32d_c(data, dst, src, 1, n_samples * n_channels); + uint32_t i, n_channels = conv->n_channels; + const float *s = src[0]; + int32_t *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = F32_TO_S32(s[i]); } void -conv_f32_to_s32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_s32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const float *s = src[0]; int32_t **d = (int32_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -449,11 +546,12 @@ conv_f32_to_s32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_f32d_to_s32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const float **s = (const float **) src; int32_t *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -464,9 +562,10 @@ conv_f32d_to_s32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR void -conv_f32d_to_s24d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s24d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const float *s = src[i]; @@ -480,17 +579,28 @@ conv_f32d_to_s24d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_REST } void -conv_f32_to_s24_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_s24_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_f32d_to_s24d_c(data, dst, src, 1, n_samples * n_channels); + 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_s24(d, F32_TO_S24(s[i])); + d += 3; + } } void -conv_f32_to_s24d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_s24d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const float *s = src[0]; uint8_t **d = (uint8_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) { @@ -500,11 +610,12 @@ conv_f32_to_s24d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR } void -conv_f32d_to_s24_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s24_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; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) { @@ -516,9 +627,10 @@ conv_f32d_to_s24_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTR void -conv_f32d_to_s24_32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s24_32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (i = 0; i < n_channels; i++) { const float *s = src[i]; @@ -530,17 +642,26 @@ conv_f32d_to_s24_32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_R } void -conv_f32_to_s24_32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_s24_32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - conv_f32d_to_s24_32d_c(data, dst, src, 1, n_samples * n_channels); + uint32_t i, n_channels = conv->n_channels; + const float *s = src[0]; + int32_t *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = F32_TO_S24(s[i]); } void -conv_f32_to_s24_32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32_to_s24_32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const float *s = src[0]; int32_t **d = (int32_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -549,11 +670,12 @@ conv_f32_to_s24_32d_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RE } void -conv_f32d_to_s24_32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s24_32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const float **s = (const float **) src; int32_t *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -562,11 +684,12 @@ conv_f32d_to_s24_32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RE } void -conv_deinterleave_8_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_deinterleave_8_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const uint8_t *s = src[0]; uint8_t **d = (uint8_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -575,11 +698,12 @@ conv_deinterleave_8_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RE } void -conv_deinterleave_16_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_deinterleave_16_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const uint16_t *s = src[0]; uint16_t **d = (uint16_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -588,11 +712,12 @@ conv_deinterleave_16_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_R } void -conv_deinterleave_24_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_deinterleave_24_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const uint8_t *s = src[0]; uint8_t **d = (uint8_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) { @@ -603,11 +728,12 @@ conv_deinterleave_24_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_R } void -conv_deinterleave_32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_deinterleave_32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const uint32_t *s = src[0]; uint32_t **d = (uint32_t **) dst; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -616,11 +742,12 @@ conv_deinterleave_32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_R } void -conv_interleave_8_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_interleave_8_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int8_t **s = (const int8_t **) src; uint8_t *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -629,11 +756,12 @@ conv_interleave_8_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_REST } void -conv_interleave_16_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_interleave_16_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int16_t **s = (const int16_t **) src; uint16_t *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) @@ -642,11 +770,12 @@ conv_interleave_16_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RES } void -conv_interleave_24_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_interleave_24_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int8_t **s = (const int8_t **) src; uint8_t *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) { @@ -657,11 +786,12 @@ conv_interleave_24_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RES } void -conv_interleave_32_c(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_interleave_32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int32_t **s = (const int32_t **) src; uint32_t *d = dst[0]; - uint32_t i, j; + uint32_t i, j, n_channels = conv->n_channels; for (j = 0; j < n_samples; j++) { for (i = 0; i < n_channels; i++) diff --git a/spa/plugins/audioconvert/fmt-ops-sse2.c b/spa/plugins/audioconvert/fmt-ops-sse2.c index 2dd265787..dce2da54b 100644 --- a/spa/plugins/audioconvert/fmt-ops-sse2.c +++ b/spa/plugins/audioconvert/fmt-ops-sse2.c @@ -27,7 +27,8 @@ #include static void -conv_s16_to_f32d_1_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) +conv_s16_to_f32d_1s_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples) { const int16_t *s = src; float **d = (float **) dst; @@ -60,18 +61,29 @@ conv_s16_to_f32d_1_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_ } } -static void -conv_s16_to_f32d_2_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) +void +conv_s16_to_f32d_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { - const int16_t *s = src; + const int16_t *s = src[0]; + uint32_t i = 0, n_channels = conv->n_channels; + + for(; i < n_channels; i++) + conv_s16_to_f32d_1s_sse2(conv, &dst[i], &s[i], n_channels, n_samples); +} + +void +conv_s16_to_f32d_2_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const int16_t *s = src[0]; float **d = (float **) dst; float *d0 = d[0], *d1 = d[1]; uint32_t n, unrolled; __m128i in, t[2]; __m128 out[2], factor = _mm_set1_ps(1.0f / S16_SCALE); - if (n_channels == 2 && - SPA_IS_ALIGNED(s, 16) && + if (SPA_IS_ALIGNED(s, 16) && SPA_IS_ALIGNED(d0, 16) && SPA_IS_ALIGNED(d1, 16)) unrolled = n_samples & ~3; @@ -93,7 +105,7 @@ conv_s16_to_f32d_2_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_ _mm_store_ps(&d0[n], out[0]); _mm_store_ps(&d1[n], out[1]); - s += 4*n_channels; + s += 8; } for(; n < n_samples; n++) { out[0] = _mm_cvtsi32_ss(out[0], s[0]); @@ -102,24 +114,13 @@ conv_s16_to_f32d_2_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_ out[1] = _mm_mul_ss(out[1], factor); _mm_store_ss(&d0[n], out[0]); _mm_store_ss(&d1[n], out[1]); - s += n_channels; + s += 2; } } void -conv_s16_to_f32d_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) -{ - const int16_t *s = src[0]; - uint32_t i = 0; - - for(; i + 1 < n_channels; i += 2) - conv_s16_to_f32d_2_sse2(data, &dst[i], &s[i], n_channels, n_samples); - for(; i < n_channels; i++) - conv_s16_to_f32d_1_sse2(data, &dst[i], &s[i], n_channels, n_samples); -} - -void -conv_s24_to_f32d_1_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32d_1s_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples) { const uint8_t *s = src; float **d = (float **) dst; @@ -158,7 +159,8 @@ conv_s24_to_f32d_1_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_ } static void -conv_s24_to_f32d_2_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32d_2s_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples) { const uint8_t *s = src; float **d = (float **) dst; @@ -217,7 +219,8 @@ conv_s24_to_f32d_2_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_ } } static void -conv_s24_to_f32d_4_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32d_4s_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples) { const uint8_t *s = src; float **d = (float **) dst; @@ -305,21 +308,23 @@ conv_s24_to_f32d_4_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_ } void -conv_s24_to_f32d_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32d_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int8_t *s = src[0]; - uint32_t i = 0; + uint32_t i = 0, n_channels = conv->n_channels; for(; i + 3 < n_channels; i += 4) - conv_s24_to_f32d_4_sse2(data, &dst[i], &s[3*i], n_channels, n_samples); + conv_s24_to_f32d_4s_sse2(conv, &dst[i], &s[3*i], n_channels, n_samples); for(; i + 1 < n_channels; i += 2) - conv_s24_to_f32d_2_sse2(data, &dst[i], &s[3*i], n_channels, n_samples); + conv_s24_to_f32d_2s_sse2(conv, &dst[i], &s[3*i], n_channels, n_samples); for(; i < n_channels; i++) - conv_s24_to_f32d_1_sse2(data, &dst[i], &s[3*i], n_channels, n_samples); + conv_s24_to_f32d_1s_sse2(conv, &dst[i], &s[3*i], n_channels, n_samples); } static void -conv_f32d_to_s32_1_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s32_1s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], + uint32_t n_channels, uint32_t n_samples) { const float **s = (const float **) src; const float *s0 = s[0]; @@ -359,7 +364,8 @@ conv_f32d_to_s32_1_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RE } static void -conv_f32d_to_s32_2_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s32_2s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], + uint32_t n_channels, uint32_t n_samples) { const float **s = (const float **) src; const float *s0 = s[0], *s1 = s[1]; @@ -410,7 +416,8 @@ conv_f32d_to_s32_2_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RE } static void -conv_f32d_to_s32_4_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s32_4s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], + uint32_t n_channels, uint32_t n_samples) { const float **s = (const float **) src; const float *s0 = s[0], *s1 = s[1], *s2 = s[2], *s3 = s[3]; @@ -472,21 +479,23 @@ conv_f32d_to_s32_4_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RE } void -conv_f32d_to_s32_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s32_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { int32_t *d = dst[0]; - uint32_t i = 0; + uint32_t i = 0, n_channels = conv->n_channels; for(; i + 3 < n_channels; i += 4) - conv_f32d_to_s32_4_sse2(data, &d[i], &src[i], n_channels, n_samples); + conv_f32d_to_s32_4s_sse2(conv, &d[i], &src[i], n_channels, n_samples); for(; i + 1 < n_channels; i += 2) - conv_f32d_to_s32_2_sse2(data, &d[i], &src[i], n_channels, n_samples); + conv_f32d_to_s32_2s_sse2(conv, &d[i], &src[i], n_channels, n_samples); for(; i < n_channels; i++) - conv_f32d_to_s32_1_sse2(data, &d[i], &src[i], n_channels, n_samples); + conv_f32d_to_s32_1s_sse2(conv, &d[i], &src[i], n_channels, n_samples); } static void -conv_f32d_to_s16_1_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s16_1s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], + uint32_t n_channels, uint32_t n_samples) { const float **s = (const float **) src; const float *s0 = s[0]; @@ -528,7 +537,8 @@ conv_f32d_to_s16_1_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RE } static void -conv_f32d_to_s16_2_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s16_2s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], + uint32_t n_channels, uint32_t n_samples) { const float **s = (const float **) src; const float *s0 = s[0], *s1 = s[1]; @@ -578,7 +588,8 @@ conv_f32d_to_s16_2_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RE } static void -conv_f32d_to_s16_4_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s16_4s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src[], + uint32_t n_channels, uint32_t n_samples) { const float **s = (const float **) src; const float *s0 = s[0], *s1 = s[1], *s2 = s[2], *s3 = s[3]; @@ -641,15 +652,16 @@ conv_f32d_to_s16_4_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RE } void -conv_f32d_to_s16_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_f32d_to_s16_sse2(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { int16_t *d = dst[0]; - uint32_t i = 0; + uint32_t i = 0, n_channels = conv->n_channels; for(; i + 3 < n_channels; i += 4) - conv_f32d_to_s16_4_sse2(data, &d[i], &src[i], n_channels, n_samples); + conv_f32d_to_s16_4s_sse2(conv, &d[i], &src[i], n_channels, n_samples); for(; i + 1 < n_channels; i += 2) - conv_f32d_to_s16_2_sse2(data, &d[i], &src[i], n_channels, n_samples); + conv_f32d_to_s16_2s_sse2(conv, &d[i], &src[i], n_channels, n_samples); for(; i < n_channels; i++) - conv_f32d_to_s16_1_sse2(data, &d[i], &src[i], n_channels, n_samples); + conv_f32d_to_s16_1s_sse2(conv, &d[i], &src[i], n_channels, n_samples); } diff --git a/spa/plugins/audioconvert/fmt-ops-sse41.c b/spa/plugins/audioconvert/fmt-ops-sse41.c index 3db80caf8..eef05df21 100644 --- a/spa/plugins/audioconvert/fmt-ops-sse41.c +++ b/spa/plugins/audioconvert/fmt-ops-sse41.c @@ -27,7 +27,8 @@ #include static void -conv_s24_to_f32d_1_sse41(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32d_1s_sse41(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples) { const uint8_t *s = src; float **d = (float **) dst; @@ -61,23 +62,26 @@ conv_s24_to_f32d_1_sse41(void *data, void * SPA_RESTRICT dst[], const void * SPA } } -extern void conv_s24_to_f32d_2_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples); -extern void conv_s24_to_f32d_4_ssse3(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples); +extern void conv_s24_to_f32d_2s_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples); +extern void conv_s24_to_f32d_4s_ssse3(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples); void -conv_s24_to_f32d_sse41(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32d_sse41(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int8_t *s = src[0]; - uint32_t i = 0; + uint32_t i = 0, n_channels = conv->n_channels; #if defined (HAVE_SSSE3) for(; i + 3 < n_channels; i += 4) - conv_s24_to_f32d_4_ssse3(data, &dst[i], &s[3*i], n_channels, n_samples); + conv_s24_to_f32d_4s_ssse3(conv, &dst[i], &s[3*i], n_channels, n_samples); #endif #if defined (HAVE_SSE2) for(; i + 1 < n_channels; i += 2) - conv_s24_to_f32d_2_sse2(data, &dst[i], &s[3*i], n_channels, n_samples); + conv_s24_to_f32d_2s_sse2(conv, &dst[i], &s[3*i], n_channels, n_samples); #endif for(; i < n_channels; i++) - conv_s24_to_f32d_1_sse41(data, &dst[i], &s[3*i], n_channels, n_samples); + conv_s24_to_f32d_1s_sse41(conv, &dst[i], &s[3*i], n_channels, n_samples); } diff --git a/spa/plugins/audioconvert/fmt-ops-ssse3.c b/spa/plugins/audioconvert/fmt-ops-ssse3.c index aa7f51d9e..6383147fc 100644 --- a/spa/plugins/audioconvert/fmt-ops-ssse3.c +++ b/spa/plugins/audioconvert/fmt-ops-ssse3.c @@ -27,7 +27,8 @@ #include static void -conv_s24_to_f32d_4_ssse3(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32d_4s_ssse3(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples) { const uint8_t *s = src; float **d = (float **) dst; @@ -94,16 +95,18 @@ conv_s24_to_f32d_4_ssse3(void *data, void * SPA_RESTRICT dst[], const void * SPA } void -conv_s24_to_f32d_1_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples); +conv_s24_to_f32d_1s_sse2(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src, + uint32_t n_channels, uint32_t n_samples); void -conv_s24_to_f32d_ssse3(void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_channels, uint32_t n_samples) +conv_s24_to_f32d_ssse3(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) { const int8_t *s = src[0]; - uint32_t i = 0; + uint32_t i = 0, n_channels = conv->n_channels; for(; i + 3 < n_channels; i += 4) - conv_s24_to_f32d_4_ssse3(data, &dst[i], &s[3*i], n_channels, n_samples); + conv_s24_to_f32d_4s_ssse3(conv, &dst[i], &s[3*i], n_channels, n_samples); for(; i < n_channels; i++) - conv_s24_to_f32d_1_sse2(data, &dst[i], &s[3*i], n_channels, n_samples); + conv_s24_to_f32d_1s_sse2(conv, &dst[i], &s[3*i], n_channels, n_samples); } diff --git a/spa/plugins/audioconvert/fmt-ops.c b/spa/plugins/audioconvert/fmt-ops.c index 506faaac3..1c572199e 100644 --- a/spa/plugins/audioconvert/fmt-ops.c +++ b/spa/plugins/audioconvert/fmt-ops.c @@ -32,135 +32,163 @@ #include "fmt-ops.h" +typedef void (*convert_func_t) (struct convert *conv, void * SPA_RESTRICT dst[], + const void * SPA_RESTRICT src[], uint32_t n_samples); + struct conv_info { uint32_t src_fmt; uint32_t dst_fmt; -#define FEATURE_SSE2 SPA_CPU_FLAG_SSE2 -#define FEATURE_SSE41 SPA_CPU_FLAG_SSE41 -#define FEATURE_SSSE3 SPA_CPU_FLAG_SSSE3 - uint32_t features; + uint32_t n_channels; + uint32_t cpu_flags; - convert_func_t func; + convert_func_t process; }; static struct conv_info conv_table[] = { /* to f32 */ - { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_F32, 0, conv_u8_to_f32_c }, - { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_F32P, 0, conv_u8d_to_f32d_c }, - { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_F32P, 0, conv_u8_to_f32d_c }, - { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_F32, 0, conv_u8d_to_f32_c }, + { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_F32, 0, 0, conv_u8_to_f32_c }, + { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_u8d_to_f32d_c }, + { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_u8_to_f32d_c }, + { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_F32, 0, 0, conv_u8d_to_f32_c }, - { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32, 0, conv_s16_to_f32_c }, - { SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_F32P, 0, conv_s16d_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_SSE2) - { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32P, FEATURE_SSE2, conv_s16_to_f32d_sse2 }, + { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32P, 2, SPA_CPU_FLAG_SSE2, conv_s16_to_f32d_2_sse2 }, + { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32P, 0, SPA_CPU_FLAG_SSE2, conv_s16_to_f32d_sse2 }, #endif - { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32P, 0, conv_s16_to_f32d_c }, - { SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_F32, 0, conv_s16d_to_f32_c }, + { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s16_to_f32d_c }, + { SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_F32, 0, 0, conv_s16d_to_f32_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32, 0, conv_copy32_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32P, 0, conv_copy32d_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32P, 0, conv_deinterleave_32_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32, 0, conv_interleave_32_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32, 0, 0, conv_copy32_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_copy32d_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_deinterleave_32_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32, 0, 0, conv_interleave_32_c }, - { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32, 0, conv_s32_to_f32_c }, - { SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_F32P, 0, conv_s32d_to_f32d_c }, - { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32P, 0, conv_s32_to_f32d_c }, - { SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_F32, 0, conv_s32d_to_f32_c }, + { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32, 0, 0, conv_s32_to_f32_c }, + { SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s32d_to_f32d_c }, + { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s32_to_f32d_c }, + { SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_F32, 0, 0, conv_s32d_to_f32_c }, - { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32, 0, conv_s24_to_f32_c }, - { SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_F32P, 0, conv_s24d_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_SSSE3) -// { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, FEATURE_SSSE3, conv_s24_to_f32d_ssse3 }, +// { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, 0, SPA_CPU_FLAG_SSSE3, conv_s24_to_f32d_ssse3 }, #endif #if defined (HAVE_SSE41) - { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, FEATURE_SSE41, conv_s24_to_f32d_sse41 }, + { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, 0, SPA_CPU_FLAG_SSE41, conv_s24_to_f32d_sse41 }, #endif #if defined (HAVE_SSE2) - { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, FEATURE_SSE2, conv_s24_to_f32d_sse2 }, + { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, 0, SPA_CPU_FLAG_SSE2, conv_s24_to_f32d_sse2 }, #endif - { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, 0, conv_s24_to_f32d_c }, - { SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_F32, 0, conv_s24d_to_f32_c }, + { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s24_to_f32d_c }, + { SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_F32, 0, 0, conv_s24d_to_f32_c }, - { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_F32, 0, conv_s24_32_to_f32_c }, - { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_F32P, 0, conv_s24_32d_to_f32d_c }, - { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_F32P, 0, conv_s24_32_to_f32d_c }, - { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_F32, 0, conv_s24_32d_to_f32_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 }, + { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_F32, 0, 0, conv_s24_32d_to_f32_c }, /* from f32 */ - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8, 0, conv_f32_to_u8_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U8P, 0, conv_f32d_to_u8d_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8P, 0, conv_f32_to_u8d_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U8, 0, conv_f32d_to_u8_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8, 0, 0, conv_f32_to_u8_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U8P, 0, 0, conv_f32d_to_u8d_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8P, 0, 0, conv_f32_to_u8d_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U8, 0, 0, conv_f32d_to_u8_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S16, 0, conv_f32_to_s16_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S16P, 0, conv_f32d_to_s16d_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S16P, 0, conv_f32_to_s16d_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S16, 0, 0, conv_f32_to_s16_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S16P, 0, 0, conv_f32d_to_s16d_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S16P, 0, 0, conv_f32_to_s16d_c }, #if defined (HAVE_SSE2) - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S16, FEATURE_SSE2, conv_f32d_to_s16_sse2 }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S16, 0, SPA_CPU_FLAG_SSE2, conv_f32d_to_s16_sse2 }, #endif - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S16, 0, conv_f32d_to_s16_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S16, 0, 0, conv_f32d_to_s16_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S32, 0, conv_f32_to_s32_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32P, 0, conv_f32d_to_s32d_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S32P, 0, conv_f32_to_s32d_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 }, #if defined (HAVE_SSE2) - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32, FEATURE_SSE2, conv_f32d_to_s32_sse2 }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32, 0, SPA_CPU_FLAG_SSE2, conv_f32d_to_s32_sse2 }, #endif - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32, 0, conv_f32d_to_s32_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S32, 0, 0, conv_f32d_to_s32_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24, 0, conv_f32_to_s24_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24P, 0, conv_f32d_to_s24d_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24P, 0, conv_f32_to_s24d_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24, 0, conv_f32d_to_s24_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 }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24, 0, 0, conv_f32d_to_s24_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24_32, 0, conv_f32_to_s24_32_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24_32P, 0, conv_f32d_to_s24_32d_c }, - { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_S24_32P, 0, conv_f32_to_s24_32d_c }, - { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24_32, 0, conv_f32d_to_s24_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 }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24_32, 0, 0, conv_f32d_to_s24_32_c }, /* u8 */ - { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8, 0, conv_copy8_c }, - { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_U8P, 0, conv_copy8d_c }, - { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8P, 0, conv_deinterleave_8_c }, - { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_U8, 0, conv_interleave_8_c }, + { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8, 0, 0, conv_copy8_c }, + { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_U8P, 0, 0, conv_copy8d_c }, + { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8P, 0, 0, conv_deinterleave_8_c }, + { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_U8, 0, 0, conv_interleave_8_c }, /* s16 */ - { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16, 0, conv_copy16_c }, - { SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_S16P, 0, conv_copy16d_c }, - { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16P, 0, conv_deinterleave_16_c }, - { SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_S16, 0, conv_interleave_16_c }, + { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16, 0, 0, conv_copy16_c }, + { SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_S16P, 0, 0, conv_copy16d_c }, + { SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16P, 0, 0, conv_deinterleave_16_c }, + { SPA_AUDIO_FORMAT_S16P, SPA_AUDIO_FORMAT_S16, 0, 0, conv_interleave_16_c }, /* s32 */ - { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32, 0, conv_copy32_c }, - { SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32P, 0, conv_copy32d_c }, - { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32P, 0, conv_deinterleave_32_c }, - { SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32, 0, conv_interleave_32_c }, + { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32, 0, 0, conv_copy32_c }, + { SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32P, 0, 0, conv_copy32d_c }, + { SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32P, 0, 0, conv_deinterleave_32_c }, + { SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32, 0, 0, conv_interleave_32_c }, /* s24 */ - { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_S24, 0, conv_copy24_c }, - { SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_S24P, 0, conv_copy24d_c }, - { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_S24P, 0, conv_deinterleave_24_c }, - { SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_S24, 0, conv_interleave_24_c }, + { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_S24, 0, 0, conv_copy24_c }, + { SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_S24P, 0, 0, conv_copy24d_c }, + { SPA_AUDIO_FORMAT_S24, SPA_AUDIO_FORMAT_S24P, 0, 0, conv_deinterleave_24_c }, + { SPA_AUDIO_FORMAT_S24P, SPA_AUDIO_FORMAT_S24, 0, 0, conv_interleave_24_c }, /* s24_32 */ - { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32, 0, conv_copy32_c }, - { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32P, 0, conv_copy32d_c }, - { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32P, 0, conv_deinterleave_32_c }, - { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32, 0, conv_interleave_32_c }, + { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32, 0, 0, conv_copy32_c }, + { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32P, 0, 0, conv_copy32d_c }, + { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32P, 0, 0, conv_deinterleave_32_c }, + { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32, 0, 0, conv_interleave_32_c }, }; -static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt, uint32_t features) +#define MATCH_CHAN(a,b) ((a) == 0 || (a) == (b)) +#define MATCH_CPU_FLAGS(a,b) ((a) == 0 || ((a) & (b)) == a) + +static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt, + uint32_t n_channels, uint32_t cpu_flags) { size_t i; for (i = 0; i < SPA_N_ELEMENTS(conv_table); i++) { if (conv_table[i].src_fmt == src_fmt && conv_table[i].dst_fmt == dst_fmt && - (conv_table[i].features == 0 || (conv_table[i].features & features) != 0)) + MATCH_CHAN(conv_table[i].n_channels, n_channels) && + MATCH_CPU_FLAGS(conv_table[i].cpu_flags, cpu_flags)) return &conv_table[i]; } return NULL; } + +static void impl_convert_free(struct convert *conv) +{ + conv->process = NULL; +} + +int convert_init(struct convert *conv) +{ + const struct conv_info *info; + + info = find_conv_info(conv->src_fmt, conv->dst_fmt, conv->n_channels, conv->cpu_flags); + if (info == NULL) + return -ENOTSUP; + + conv->is_passthrough = conv->src_fmt == conv->dst_fmt; + conv->cpu_flags = info->cpu_flags; + conv->process = info->process; + conv->free = impl_convert_free; + + return 0; +} diff --git a/spa/plugins/audioconvert/fmt-ops.h b/spa/plugins/audioconvert/fmt-ops.h index 1fb657309..d9dcd5780 100644 --- a/spa/plugins/audioconvert/fmt-ops.h +++ b/spa/plugins/audioconvert/fmt-ops.h @@ -77,13 +77,32 @@ static inline void write_s24(void *dst, int32_t val) #endif } -typedef void (*convert_func_t) (void *data, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], - uint32_t n_channels, uint32_t n_samples); +#define MAX_NS 64 + +struct convert { + uint32_t src_fmt; + uint32_t dst_fmt; + uint32_t n_channels; + uint32_t cpu_flags; + + int is_passthrough:1; + float ns_data[MAX_NS]; + uint32_t ns_idx; + uint32_t ns_size; + + void (*process) (struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples); + void (*free) (struct convert *conv); +}; + +int convert_init(struct convert *conv); + +#define convert_process(conv,...) (conv)->process(conv, __VA_ARGS__) +#define convert_free(conv) (conv)->free(conv) #define DEFINE_FUNCTION(name,arch) \ -void conv_##name##_##arch(void *data, void * SPA_RESTRICT dst[], \ - const void * SPA_RESTRICT src[], \ - uint32_t n_channels, uint32_t n_samples) +void conv_##name##_##arch(struct convert *conv, void * SPA_RESTRICT dst[], \ + const void * SPA_RESTRICT src[], uint32_t n_samples) \ DEFINE_FUNCTION(copy8d, c); DEFINE_FUNCTION(copy8, c); @@ -143,6 +162,7 @@ DEFINE_FUNCTION(interleave_24, c); DEFINE_FUNCTION(interleave_32, c); #if defined(HAVE_SSE2) +DEFINE_FUNCTION(s16_to_f32d_2, sse2); DEFINE_FUNCTION(s16_to_f32d, sse2); DEFINE_FUNCTION(s24_to_f32d, sse2); DEFINE_FUNCTION(f32d_to_s32, sse2); diff --git a/spa/plugins/audioconvert/fmtconvert.c b/spa/plugins/audioconvert/fmtconvert.c index 44c67fd3d..5326deb03 100644 --- a/spa/plugins/audioconvert/fmtconvert.c +++ b/spa/plugins/audioconvert/fmtconvert.c @@ -39,6 +39,8 @@ #include #include +#include "fmt-ops.h" + #define NAME "fmtconvert" #define DEFAULT_RATE 48000 @@ -97,8 +99,6 @@ struct port { struct spa_list queue; }; -#include "fmt-ops.c" - struct impl { struct spa_handle handle; struct spa_node node; @@ -120,7 +120,7 @@ struct impl { bool started; uint32_t cpu_flags; - convert_func_t convert; + struct convert conv; int is_passthrough:1; }; @@ -143,8 +143,8 @@ static int setup_convert(struct impl *this) uint32_t src_fmt, dst_fmt; struct spa_audio_info informat, outformat; struct port *inport, *outport; - const struct conv_info *conv; uint32_t i, j; + int res; inport = GET_IN_PORT(this, 0); outport = GET_OUT_PORT(this, 0); @@ -181,16 +181,19 @@ static int setup_convert(struct impl *this) } } - /* find fast path */ - conv = find_conv_info(src_fmt, dst_fmt, this->cpu_flags); - if (conv == NULL) - return -ENOTSUP; + this->conv.src_fmt = src_fmt; + this->conv.dst_fmt = dst_fmt; + this->conv.n_channels = outformat.info.raw.channels; + this->conv.cpu_flags = this->cpu_flags; + + if ((res = convert_init(&this->conv)) < 0) + return res; spa_log_info(this->log, NAME " %p: got converter features %08x:%08x", this, - this->cpu_flags, conv->features); + this->cpu_flags, this->conv.cpu_flags); + + this->is_passthrough = this->conv.is_passthrough; - this->convert = conv->func; - this->is_passthrough = src_fmt == dst_fmt; return 0; } @@ -556,7 +559,7 @@ static int port_set_format(struct spa_node *node, if (port->have_format) { port->have_format = false; clear_buffers(this, port); - this->convert = NULL; + convert_free(&this->conv); } } else { struct spa_audio_info info = { 0 }; @@ -801,7 +804,7 @@ static int impl_node_process(struct spa_node *node) struct spa_buffer *inb, *outb; const void **src_datas; void **dst_datas; - uint32_t i, n_src_datas, n_dst_datas, n_datas; + uint32_t i, n_src_datas, n_dst_datas; int res = 0; uint32_t n_samples, size, maxsize, offs; @@ -863,8 +866,6 @@ static int impl_node_process(struct spa_node *node) spa_log_trace_fp(this->log, NAME " %p: n_src:%d n_dst:%d size:%d maxsize:%d n_samples:%d", this, n_src_datas, n_dst_datas, size, maxsize, n_samples); - n_datas = SPA_MAX(n_src_datas, n_dst_datas); - for (i = 0; i < n_dst_datas; i++) { dst_datas[i] = this->is_passthrough ? (void*)src_datas[i] : @@ -875,7 +876,7 @@ static int impl_node_process(struct spa_node *node) } if (!this->is_passthrough) - this->convert(this, dst_datas, src_datas, n_datas, n_samples); + convert_process(&this->conv, dst_datas, src_datas, n_samples); inio->status = SPA_STATUS_NEED_BUFFER; res |= SPA_STATUS_NEED_BUFFER; diff --git a/spa/plugins/audioconvert/merger.c b/spa/plugins/audioconvert/merger.c index dd6c5531b..670dabae8 100644 --- a/spa/plugins/audioconvert/merger.c +++ b/spa/plugins/audioconvert/merger.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,8 @@ #include #include +#include "fmt-ops.h" + #define NAME "merger" #define DEFAULT_RATE 48000 @@ -81,8 +84,6 @@ struct port { struct spa_list queue; }; -#include "fmt-ops.c" - struct impl { struct spa_handle handle; struct spa_node node; @@ -101,7 +102,7 @@ struct impl { struct port in_ports[MAX_PORTS]; struct port out_ports[MAX_PORTS + 1]; - convert_func_t convert; + struct convert conv; uint32_t cpu_flags; int is_passthrough:1; int started:1; @@ -543,9 +544,9 @@ static int clear_buffers(struct impl *this, struct port *port) static int setup_convert(struct impl *this) { - const struct conv_info *conv; struct port *outport; uint32_t src_fmt, dst_fmt; + int res; outport = GET_OUT_PORT(this, 0); @@ -561,16 +562,20 @@ static int setup_convert(struct impl *this) outport->format.info.raw.channels, outport->format.info.raw.rate); - conv = find_conv_info(src_fmt, dst_fmt, this->cpu_flags); - if (conv != NULL) { - spa_log_info(this->log, NAME " %p: got converter features %08x:%08x", this, - this->cpu_flags, conv->features); + this->conv.src_fmt = src_fmt; + this->conv.dst_fmt = dst_fmt; + this->conv.n_channels = outport->format.info.raw.channels; + this->conv.cpu_flags = this->cpu_flags; - this->convert = conv->func; - this->is_passthrough = src_fmt == dst_fmt; - return 0; - } - return -ENOTSUP; + if ((res = convert_init(&this->conv)) < 0) + return res; + + spa_log_info(this->log, NAME " %p: got converter features %08x:%08x", this, + this->cpu_flags, this->conv.cpu_flags); + + this->is_passthrough = src_fmt == dst_fmt; + + return 0; } static int calc_width(struct spa_audio_info *info) @@ -942,7 +947,7 @@ static int impl_node_process(struct spa_node *node) outport = GET_OUT_PORT(this, 0); outio = outport->io; spa_return_val_if_fail(outio != NULL, -EIO); - spa_return_val_if_fail(this->convert != NULL, -EIO); + spa_return_val_if_fail(this->conv.process != NULL, -EIO); spa_log_trace_fp(this->log, NAME " %p: status %d %d", this, outio->status, outio->buffer_id); @@ -995,7 +1000,7 @@ static int impl_node_process(struct spa_node *node) n_samples * outport->stride); } if (!this->is_passthrough) - this->convert(this, dst_datas, src_datas, SPA_MAX(n_dst_datas, n_src_datas), n_samples); + convert_process(&this->conv, dst_datas, src_datas, n_samples); return res | SPA_STATUS_HAVE_BUFFER; } diff --git a/spa/plugins/audioconvert/meson.build b/spa/plugins/audioconvert/meson.build index bd8acd61e..4517677e4 100644 --- a/spa/plugins/audioconvert/meson.build +++ b/spa/plugins/audioconvert/meson.build @@ -1,5 +1,7 @@ audioconvert_sources = ['fmtconvert.c', + 'fmt-ops.c', 'channelmix.c', + 'channelmix-ops.c', 'resample.c', 'splitter.c', 'merger.c', @@ -23,7 +25,7 @@ if have_sse audioconvert_sse = static_library('audioconvert_sse', ['resample-native-sse.c', 'channelmix-ops-sse.c' ], - c_args : [sse_args, '-O3'], + c_args : [sse_args, '-O3', '-DHAVE_SSE'], include_directories : [spa_inc], install : false ) @@ -33,7 +35,7 @@ endif if have_sse2 audioconvert_sse2 = static_library('audioconvert_sse2', ['fmt-ops-sse2.c' ], - c_args : [sse2_args, '-O3'], + c_args : [sse2_args, '-O3', '-DHAVE_SSE2'], include_directories : [spa_inc], install : false ) @@ -44,7 +46,7 @@ if have_ssse3 audioconvert_ssse3 = static_library('audioconvert_ssse3', ['fmt-ops-ssse3.c', 'resample-native-ssse3.c' ], - c_args : [ssse3_args, '-O3'], + c_args : [ssse3_args, '-O3', '-DHAVE_SSSE3'], include_directories : [spa_inc], install : false ) @@ -54,7 +56,7 @@ endif if have_sse41 audioconvert_sse41 = static_library('audioconvert_sse41', ['fmt-ops-sse41.c'], - c_args : [sse41_args, '-O3'], + c_args : [sse41_args, '-O3', '-DHAVE_SSE41'], include_directories : [spa_inc], install : false ) @@ -64,7 +66,7 @@ endif if have_avx and have_fma audioconvert_avx = static_library('audioconvert_avx', ['resample-native-avx.c'], - c_args : [avx2_args, fma_args, '-O3'], + c_args : [avx2_args, fma_args, '-O3', '-DHAVE_AVX', '-DHAVE_FMA'], include_directories : [spa_inc], install : false ) diff --git a/spa/plugins/audioconvert/splitter.c b/spa/plugins/audioconvert/splitter.c index 78b198fb7..50cbefa0c 100644 --- a/spa/plugins/audioconvert/splitter.c +++ b/spa/plugins/audioconvert/splitter.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,8 @@ #include #include +#include "fmt-ops.h" + #define NAME "splitter" #define DEFAULT_RATE 48000 @@ -84,8 +87,6 @@ struct port { struct spa_list queue; }; -#include "fmt-ops.c" - struct impl { struct spa_handle handle; struct spa_node node; @@ -104,7 +105,7 @@ struct impl { uint32_t port_count; uint32_t cpu_flags; - convert_func_t convert; + struct convert conv; int is_passthrough:1; int started:1; @@ -530,9 +531,9 @@ static int clear_buffers(struct impl *this, struct port *port) static int setup_convert(struct impl *this) { - const struct conv_info *conv; struct port *inport; uint32_t src_fmt, dst_fmt; + int res; inport = GET_IN_PORT(this, 0); @@ -548,16 +549,21 @@ static int setup_convert(struct impl *this) inport->format.info.raw.rate, this->port_count); - conv = find_conv_info(src_fmt, dst_fmt, this->cpu_flags); - if (conv != NULL) { - spa_log_info(this->log, NAME " %p: got converter features %08x:%08x", this, - this->cpu_flags, conv->features); - this->convert = conv->func; - this->is_passthrough = src_fmt == dst_fmt; - return 0; - } - return -ENOTSUP; + this->conv.src_fmt = src_fmt; + this->conv.dst_fmt = dst_fmt; + this->conv.n_channels = inport->format.info.raw.channels; + this->conv.cpu_flags = this->cpu_flags; + + if ((res = convert_init(&this->conv)) < 0) + return res; + + spa_log_info(this->log, NAME " %p: got converter features %08x:%08x", this, + this->cpu_flags, this->conv.cpu_flags); + + this->is_passthrough = this->conv.is_passthrough; + + return 0; } static int calc_width(struct spa_audio_info *info) @@ -846,7 +852,7 @@ static int impl_node_process(struct spa_node *node) inport = GET_IN_PORT(this, 0); inio = inport->io; spa_return_val_if_fail(inio != NULL, -EIO); - spa_return_val_if_fail(this->convert != NULL, -EIO); + spa_return_val_if_fail(this->conv.process != NULL, -EIO); spa_log_trace_fp(this->log, NAME " %p: status %p %d %d", this, inio, inio->status, inio->buffer_id); @@ -924,7 +930,7 @@ static int impl_node_process(struct spa_node *node) n_src_datas, n_dst_datas, n_samples, maxsize, inport->stride); if (!this->is_passthrough) - this->convert(this, dst_datas, src_datas, SPA_MAX(n_dst_datas, n_src_datas), n_samples); + convert_process(&this->conv, dst_datas, src_datas, n_samples); inio->status = SPA_STATUS_NEED_BUFFER; res |= SPA_STATUS_NEED_BUFFER; diff --git a/spa/plugins/audioconvert/test-fmt-ops.c b/spa/plugins/audioconvert/test-fmt-ops.c index 677804dad..9985d0f31 100644 --- a/spa/plugins/audioconvert/test-fmt-ops.c +++ b/spa/plugins/audioconvert/test-fmt-ops.c @@ -49,6 +49,9 @@ static void run_test(const char *name, void *tp[N_CHANNELS]; int i, j; const uint8_t *in8 = in, *out8 = out; + struct convert conv; + + conv.n_channels = N_CHANNELS; for (j = 0; j < N_SAMPLES; j++) { memcpy(&samp_in[j * in_size], &in8[(j % n_samples) * in_size], in_size); @@ -62,16 +65,16 @@ static void run_test(const char *name, tp[0] = temp_in; switch(in_size) { case 1: - conv_interleave_8_c(NULL, tp, ip, N_CHANNELS, N_SAMPLES); + conv_interleave_8_c(&conv, tp, ip, N_SAMPLES); break; case 2: - conv_interleave_16_c(NULL, tp, ip, N_CHANNELS, N_SAMPLES); + conv_interleave_16_c(&conv, tp, ip, N_SAMPLES); break; case 3: - conv_interleave_24_c(NULL, tp, ip, N_CHANNELS, N_SAMPLES); + conv_interleave_24_c(&conv, tp, ip, N_SAMPLES); break; case 4: - conv_interleave_32_c(NULL, tp, ip, N_CHANNELS, N_SAMPLES); + conv_interleave_32_c(&conv, tp, ip, N_SAMPLES); break; default: fprintf(stderr, "unknown size %zd\n", in_size); @@ -84,7 +87,7 @@ static void run_test(const char *name, for (j = 0; j < N_CHANNELS; j++) tp[j] = &temp_out[j * N_SAMPLES * out_size]; - func(NULL, tp, ip, N_CHANNELS, N_SAMPLES); + func(&conv, tp, ip, N_SAMPLES); fprintf(stderr, "test %s:\n", name); if (out_packed) { @@ -260,8 +263,6 @@ static void test_s24_32_f32(void) int main(int argc, char *argv[]) { - find_conv_info(0, 0, 0); - test_f32_u8(); test_u8_f32(); test_f32_s16();