diff --git a/spa/plugins/audioconvert/channelmix-ops-c.c b/spa/plugins/audioconvert/channelmix-ops-c.c index b9eed6f6f..710ed384b 100644 --- a/spa/plugins/audioconvert/channelmix-ops-c.c +++ b/spa/plugins/audioconvert/channelmix-ops-c.c @@ -32,11 +32,11 @@ channelmix_copy_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT ds float **d = (float **)dst; const float **s = (const float **)src; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } - else if (mix->identity) { + else if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_IDENTITY)) { for (i = 0; i < n_dst; i++) spa_memcpy(d[i], s[i], n_samples * sizeof(float)); } @@ -81,19 +81,18 @@ channelmix_f32_1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT const float v0 = mix->matrix[0][0]; const float v1 = mix->matrix[1][0]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { memset(d[0], 0, n_samples * sizeof(float)); memset(d[1], 0, n_samples * sizeof(float)); - } - else if (mix->norm) { - for (n = 0; n < n_samples; n++) - d[0][n] = d[1][n] = s[0][n]; - } - else if (mix->equal) { - for (n = 0; n < n_samples; n++) - d[0][n] = d[1][n] = s[0][n] * v0; - } - else { + } else if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_EQUAL)) { + if (v0 == 1.0f) { + for (n = 0; n < n_samples; n++) + d[0][n] = d[1][n] = s[0][n]; + } else { + for (n = 0; n < n_samples; n++) + d[0][n] = d[1][n] = s[0][n] * v0; + } + } else { for (n = 0; n < n_samples; n++) { d[0][n] = s[0][n] * v0; d[1][n] = s[0][n] * v1; @@ -111,10 +110,9 @@ channelmix_f32_2_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT const float v0 = mix->matrix[0][0]; const float v1 = mix->matrix[0][1]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { memset(d[0], 0, n_samples * sizeof(float)); - } - else if (mix->equal) { + } else if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_EQUAL)) { for (n = 0; n < n_samples; n++) d[0][n] = (s[0][n] + s[1][n]) * v0; } @@ -136,10 +134,10 @@ channelmix_f32_4_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT const float v2 = mix->matrix[0][2]; const float v3 = mix->matrix[0][3]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { memset(d[0], 0, n_samples * sizeof(float)); } - else if (mix->equal) { + else if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_EQUAL)) { for (n = 0; n < n_samples; n++) d[0][n] = (s[0][n] + s[1][n] + s[2][n] + s[3][n]) * v0; } @@ -161,10 +159,10 @@ channelmix_f32_3p1_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI const float v1 = mix->matrix[0][1]; const float v2 = mix->matrix[0][2]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { memset(d[0], 0, n_samples * sizeof(float)); } - else if (mix->equal) { + else if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_EQUAL)) { for (n = 0; n < n_samples; n++) d[0][n] = (s[0][n] + s[1][n] + s[2][n] + s[3][n]) * v0; } @@ -189,20 +187,21 @@ channelmix_f32_2_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT const float v2 = mix->matrix[2][0]; const float v3 = mix->matrix[3][1]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } - else if (mix->norm) { - for (n = 0; n < n_samples; n++) { - d[0][n] = d[2][n] = s[0][n]; - d[1][n] = d[3][n] = s[1][n]; - } - } else if (v0 == v2 && v1 == v3) { - for (n = 0; n < n_samples; n++) { - d[0][n] = d[2][n] = s[0][n] * v0; - d[1][n] = d[3][n] = s[1][n] * v1; + if (v0 == 1.0f && v1 == 1.0f) { + for (n = 0; n < n_samples; n++) { + d[0][n] = d[2][n] = s[0][n]; + d[1][n] = d[3][n] = s[1][n]; + } + } else { + for (n = 0; n < n_samples; n++) { + d[0][n] = d[2][n] = s[0][n] * v0; + d[1][n] = d[3][n] = s[1][n] * v1; + } } } else { @@ -226,11 +225,11 @@ channelmix_f32_2_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI const float v0 = mix->matrix[0][0]; const float v1 = mix->matrix[1][1]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } - else if (mix->norm) { + else if (v0 == 1.0f && v1 == 1.0f) { for (n = 0; n < n_samples; n++) { d[0][n] = s[0][n]; d[1][n] = s[1][n]; @@ -261,11 +260,11 @@ channelmix_f32_2_5p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI const float v4 = mix->matrix[4][0]; const float v5 = mix->matrix[5][1]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } - else if (mix->norm) { + else if (v0 == 1.0f && v1 == 1.0f && v4 == 1.0f && v5 == 1.0f) { for (n = 0; n < n_samples; n++) { d[0][n] = d[4][n] = s[0][n]; d[1][n] = d[5][n] = s[1][n]; @@ -300,7 +299,7 @@ channelmix_f32_5p1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI const float slev0 = mix->matrix[0][4]; const float slev1 = mix->matrix[1][5]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { memset(d[0], 0, n_samples * sizeof(float)); memset(d[1], 0, n_samples * sizeof(float)); } @@ -328,7 +327,7 @@ channelmix_f32_5p1_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_REST const float v4 = mix->matrix[0][4]; const float v5 = mix->matrix[1][5]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } @@ -357,7 +356,7 @@ channelmix_f32_5p1_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI const float v4 = mix->matrix[2][4]; const float v5 = mix->matrix[3][5]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } @@ -391,7 +390,7 @@ channelmix_f32_7p1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI const float rlev0 = mix->matrix[0][6]; const float rlev1 = mix->matrix[1][7]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { memset(d[0], 0, n_samples * sizeof(float)); memset(d[1], 0, n_samples * sizeof(float)); } @@ -419,7 +418,7 @@ channelmix_f32_7p1_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_REST const float v4 = (mix->matrix[0][4] + mix->matrix[0][6]) * 0.5f; const float v5 = (mix->matrix[1][5] + mix->matrix[1][6]) * 0.5f; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } @@ -450,7 +449,7 @@ channelmix_f32_7p1_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI const float rlev0 = mix->matrix[0][6]; const float rlev1 = mix->matrix[1][7]; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } diff --git a/spa/plugins/audioconvert/channelmix-ops-sse.c b/spa/plugins/audioconvert/channelmix-ops-sse.c index 84c2e3aa4..ad1bc073b 100644 --- a/spa/plugins/audioconvert/channelmix-ops-sse.c +++ b/spa/plugins/audioconvert/channelmix-ops-sse.c @@ -33,11 +33,11 @@ void channelmix_copy_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_REST float **d = (float **)dst; const float **s = (const float **)src; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } - else if (mix->norm) { + else if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_IDENTITY)) { for (i = 0; i < n_dst; i++) spa_memcpy(d[i], s[i], n_samples * sizeof(float)); } @@ -77,8 +77,8 @@ channelmix_f32_2_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI uint32_t i, n, unrolled; float **d = (float **)dst; const float **s = (const float **)src; - const __m128 v0 = _mm_set1_ps(mix->matrix[0][0]); - const __m128 v1 = _mm_set1_ps(mix->matrix[1][1]); + const float m00 = mix->matrix[0][0]; + const float m11 = mix->matrix[1][1]; __m128 in; const float *sFL = s[0], *sFR = s[1]; float *dFL = d[0], *dFR = d[1], *dRL = d[2], *dRR = d[3]; @@ -93,11 +93,11 @@ channelmix_f32_2_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI else unrolled = 0; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } - else if (mix->norm) { + else if (m00 == 1.0f && m11 == 1.0f) { for(n = 0; n < unrolled; n += 4) { in = _mm_load_ps(&sFL[n]); _mm_store_ps(&dFL[n], in); @@ -116,6 +116,8 @@ channelmix_f32_2_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI } } else { + const __m128 v0 = _mm_set1_ps(m00); + const __m128 v1 = _mm_set1_ps(m11); for(n = 0; n < unrolled; n += 4) { in = _mm_mul_ps(_mm_load_ps(&sFL[n]), v0); _mm_store_ps(&dFL[n], in); @@ -143,8 +145,8 @@ channelmix_f32_5p1_2_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_REST uint32_t n, unrolled; float **d = (float **) dst; const float **s = (const float **) src; - const __m128 v0 = _mm_set1_ps(mix->matrix[0][0]); - const __m128 v1 = _mm_set1_ps(mix->matrix[1][1]); + const float m00 = mix->matrix[0][0]; + const float m11 = mix->matrix[1][1]; const __m128 clev = _mm_set1_ps((mix->matrix[0][2] + mix->matrix[1][2]) * 0.5f); const __m128 llev = _mm_set1_ps((mix->matrix[0][3] + mix->matrix[1][3]) * 0.5f); const __m128 slev0 = _mm_set1_ps(mix->matrix[0][4]); @@ -165,11 +167,11 @@ channelmix_f32_5p1_2_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_REST else unrolled = 0; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { memset(dFL, 0, n_samples * sizeof(float)); memset(dFR, 0, n_samples * sizeof(float)); } - else if (mix->norm) { + else if (m00 == 1.0f && m11 == 1.0f) { for(n = 0; n < unrolled; n += 4) { ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev); ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev)); @@ -196,6 +198,8 @@ channelmix_f32_5p1_2_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_REST } } else { + const __m128 v0 = _mm_set1_ps(m00); + const __m128 v1 = _mm_set1_ps(m11); for(n = 0; n < unrolled; n += 4) { ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev); ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev)); @@ -259,7 +263,7 @@ channelmix_f32_5p1_3p1_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RE else unrolled = 0; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } @@ -315,10 +319,10 @@ channelmix_f32_5p1_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_REST const float **s = (const float **) src; const __m128 clev = _mm_set1_ps(mix->matrix[0][2]); const __m128 llev = _mm_set1_ps(mix->matrix[0][3]); - const __m128 v0 = _mm_set1_ps(mix->matrix[0][0]); - const __m128 v1 = _mm_set1_ps(mix->matrix[1][1]); - const __m128 v4 = _mm_set1_ps(mix->matrix[2][4]); - const __m128 v5 = _mm_set1_ps(mix->matrix[3][5]); + const float m00 = mix->matrix[0][0]; + const float m11 = mix->matrix[1][1]; + const float m24 = mix->matrix[2][4]; + const float m35 = mix->matrix[3][5]; __m128 ctr; const float *sFL = s[0], *sFR = s[1], *sFC = s[2], *sLFE = s[3], *sSL = s[4], *sSR = s[5]; float *dFL = d[0], *dFR = d[1], *dRL = d[2], *dRR = d[3]; @@ -337,11 +341,11 @@ channelmix_f32_5p1_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_REST else unrolled = 0; - if (mix->zero) { + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) memset(d[i], 0, n_samples * sizeof(float)); } - else if (mix->norm) { + else if (m00 == 1.0f && m11 == 1.0f && m24 == 1.0f && m35 == 1.0f) { for(n = 0; n < unrolled; n += 4) { ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev); ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev)); @@ -360,6 +364,11 @@ channelmix_f32_5p1_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_REST } } else { + const __m128 v0 = _mm_set1_ps(m00); + const __m128 v1 = _mm_set1_ps(m11); + const __m128 v4 = _mm_set1_ps(m24); + const __m128 v5 = _mm_set1_ps(m35); + for(n = 0; n < unrolled; n += 4) { ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev); ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev)); diff --git a/spa/plugins/audioconvert/channelmix-ops.c b/spa/plugins/audioconvert/channelmix-ops.c index d506804e9..24c038174 100644 --- a/spa/plugins/audioconvert/channelmix-ops.c +++ b/spa/plugins/audioconvert/channelmix-ops.c @@ -318,7 +318,8 @@ static int make_matrix(struct channelmix *mix) spa_log_warn(mix->log, "can't assign FLC"); } } - if (unassigned & _MASK(LFE)) { + if (unassigned & _MASK(LFE) && + SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_MIX_LFE)) { if (dst_mask & _MASK(FC)) { matrix[FC][LFE] += llev; } else if (dst_mask & _MASK(FL)) { @@ -338,11 +339,9 @@ static int make_matrix(struct channelmix *mix) mix->matrix_orig[ic][jc++] = matrix[i][j]; sum += fabs(matrix[i][j]); } -#if 0 if (sum > 1.0f) for (j = 0; j < jc; j++) mix->matrix_orig[ic][j] /= sum; -#endif ic++; } return 0; @@ -358,13 +357,10 @@ static void impl_channelmix_set_volume(struct channelmix *mix, float volume, boo uint32_t dst_chan = mix->dst_chan; /** apply global volume to channels */ - mix->norm = true; - for (i = 0; i < n_channel_volumes; i++) { + for (i = 0; i < n_channel_volumes; i++) volumes[i] = channel_volumes[i] * vol; - if (volumes[i] != 1.0f) - mix->norm = false; - } + /** apply volumes per channel */ if (n_channel_volumes == src_chan) { for (i = 0; i < dst_chan; i++) { for (j = 0; j < src_chan; j++) { @@ -379,11 +375,11 @@ static void impl_channelmix_set_volume(struct channelmix *mix, float volume, boo } } - mix->zero = true; - mix->equal = true; - mix->identity = dst_chan == src_chan; - t = 0.0; + SPA_FLAG_SET(mix->flags, CHANNELMIX_FLAG_ZERO); + SPA_FLAG_SET(mix->flags, CHANNELMIX_FLAG_EQUAL); + SPA_FLAG_UPDATE(mix->flags, CHANNELMIX_FLAG_IDENTITY, dst_chan == src_chan); + t = 0.0; for (i = 0; i < dst_chan; i++) { for (j = 0; j < src_chan; j++) { float v = mix->matrix[i][j]; @@ -391,15 +387,15 @@ static void impl_channelmix_set_volume(struct channelmix *mix, float volume, boo if (i == 0 && j == 0) t = v; else if (t != v) - mix->equal = false; + SPA_FLAG_CLEAR(mix->flags, CHANNELMIX_FLAG_EQUAL); if (v != 0.0) - mix->zero = false; + SPA_FLAG_CLEAR(mix->flags, CHANNELMIX_FLAG_ZERO); if ((i == j && v != 1.0f) || (i != j && v != 0.0f)) - mix->identity = false; + SPA_FLAG_CLEAR(mix->flags, CHANNELMIX_FLAG_IDENTITY); } } - spa_log_debug(mix->log, "zero:%d norm:%d identity:%d", mix->zero, mix->norm, mix->identity); + spa_log_debug(mix->log, "flags:%08x", mix->flags); } static void impl_channelmix_free(struct channelmix *mix) diff --git a/spa/plugins/audioconvert/channelmix-ops.h b/spa/plugins/audioconvert/channelmix-ops.h index ceec06938..1f9674504 100644 --- a/spa/plugins/audioconvert/channelmix-ops.h +++ b/spa/plugins/audioconvert/channelmix-ops.h @@ -46,13 +46,15 @@ struct channelmix { uint64_t src_mask; uint64_t dst_mask; uint32_t cpu_flags; +#define CHANNELMIX_OPTION_MIX_LFE (1<<0) /**< mix LFE */ + uint32_t options; struct spa_log *log; - unsigned int zero:1; /* all zero components */ - unsigned int identity:1; /* identity matrix */ - unsigned int norm:1; /* all normal values */ - unsigned int equal:1; /* all values are equal */ +#define CHANNELMIX_FLAG_ZERO (1<<0) /**< all zero components */ +#define CHANNELMIX_FLAG_IDENTITY (1<<1) /**< identity matrix */ +#define CHANNELMIX_FLAG_EQUAL (1<<2) /**< all values are equal */ + uint32_t flags; float matrix_orig[SPA_AUDIO_MAX_CHANNELS][SPA_AUDIO_MAX_CHANNELS]; float matrix[SPA_AUDIO_MAX_CHANNELS][SPA_AUDIO_MAX_CHANNELS]; diff --git a/spa/plugins/audioconvert/channelmix.c b/spa/plugins/audioconvert/channelmix.c index 3d6d62b74..d30b397d2 100644 --- a/spa/plugins/audioconvert/channelmix.c +++ b/spa/plugins/audioconvert/channelmix.c @@ -256,11 +256,11 @@ static int setup_convert(struct impl *this, emit_params_changed(this); - spa_log_debug(this->log, NAME " %p: got channelmix features %08x:%08x identity:%d", + spa_log_debug(this->log, NAME " %p: got channelmix features %08x:%08x flags:%08x", this, this->cpu_flags, this->mix.cpu_flags, - this->mix.identity); + this->mix.flags); - this->is_passthrough = this->mix.identity; + this->is_passthrough = SPA_FLAG_IS_SET(this->mix.flags, CHANNELMIX_FLAG_IDENTITY); return 0; } @@ -1057,7 +1057,9 @@ static int impl_node_process(void *object) void *dst_datas[n_dst_datas]; bool is_passthrough; - is_passthrough = this->is_passthrough && this->mix.identity && ctrlport->ctrl == NULL; + is_passthrough = this->is_passthrough && + SPA_FLAG_IS_SET(this->mix.flags, CHANNELMIX_FLAG_IDENTITY) && + ctrlport->ctrl == NULL; n_samples = sb->datas[0].chunk->size / inport->stride;