channelmix: normalize volumes

Normalize the volumes.
Don't mix in LFE by default but add an option
Move some booleans to flags
Improve some checks for fastpaths.
This commit is contained in:
Wim Taymans 2020-09-03 13:20:36 +02:00
parent 289a8e86ca
commit f7d8fef070
5 changed files with 89 additions and 81 deletions

View file

@ -32,11 +32,11 @@ channelmix_copy_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT ds
float **d = (float **)dst; float **d = (float **)dst;
const float **s = (const float **)src; 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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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++) for (i = 0; i < n_dst; i++)
spa_memcpy(d[i], s[i], n_samples * sizeof(float)); 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 v0 = mix->matrix[0][0];
const float v1 = mix->matrix[1][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[0], 0, n_samples * sizeof(float));
memset(d[1], 0, n_samples * sizeof(float)); memset(d[1], 0, n_samples * sizeof(float));
} } else if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_EQUAL)) {
else if (mix->norm) { if (v0 == 1.0f) {
for (n = 0; n < n_samples; n++) for (n = 0; n < n_samples; n++)
d[0][n] = d[1][n] = s[0][n]; d[0][n] = d[1][n] = s[0][n];
} } else {
else if (mix->equal) { for (n = 0; n < n_samples; n++)
for (n = 0; n < n_samples; n++) d[0][n] = d[1][n] = s[0][n] * v0;
d[0][n] = d[1][n] = s[0][n] * v0; }
} } else {
else {
for (n = 0; n < n_samples; n++) { for (n = 0; n < n_samples; n++) {
d[0][n] = s[0][n] * v0; d[0][n] = s[0][n] * v0;
d[1][n] = s[0][n] * v1; 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 v0 = mix->matrix[0][0];
const float v1 = mix->matrix[0][1]; 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)); memset(d[0], 0, n_samples * sizeof(float));
} } else if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_EQUAL)) {
else if (mix->equal) {
for (n = 0; n < n_samples; n++) for (n = 0; n < n_samples; n++)
d[0][n] = (s[0][n] + s[1][n]) * v0; 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 v2 = mix->matrix[0][2];
const float v3 = mix->matrix[0][3]; 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)); 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++) for (n = 0; n < n_samples; n++)
d[0][n] = (s[0][n] + s[1][n] + s[2][n] + s[3][n]) * v0; 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 v1 = mix->matrix[0][1];
const float v2 = mix->matrix[0][2]; 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)); 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++) for (n = 0; n < n_samples; n++)
d[0][n] = (s[0][n] + s[1][n] + s[2][n] + s[3][n]) * v0; 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 v2 = mix->matrix[2][0];
const float v3 = mix->matrix[3][1]; 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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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) { else if (v0 == v2 && v1 == v3) {
for (n = 0; n < n_samples; n++) { if (v0 == 1.0f && v1 == 1.0f) {
d[0][n] = d[2][n] = s[0][n] * v0; for (n = 0; n < n_samples; n++) {
d[1][n] = d[3][n] = s[1][n] * v1; 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 { 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 v0 = mix->matrix[0][0];
const float v1 = mix->matrix[1][1]; 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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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++) { for (n = 0; n < n_samples; n++) {
d[0][n] = s[0][n]; d[0][n] = s[0][n];
d[1][n] = s[1][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 v4 = mix->matrix[4][0];
const float v5 = mix->matrix[5][1]; 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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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++) { for (n = 0; n < n_samples; n++) {
d[0][n] = d[4][n] = s[0][n]; d[0][n] = d[4][n] = s[0][n];
d[1][n] = d[5][n] = s[1][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 slev0 = mix->matrix[0][4];
const float slev1 = mix->matrix[1][5]; 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[0], 0, n_samples * sizeof(float));
memset(d[1], 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 v4 = mix->matrix[0][4];
const float v5 = mix->matrix[1][5]; 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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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 v4 = mix->matrix[2][4];
const float v5 = mix->matrix[3][5]; 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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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 rlev0 = mix->matrix[0][6];
const float rlev1 = mix->matrix[1][7]; 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[0], 0, n_samples * sizeof(float));
memset(d[1], 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 v4 = (mix->matrix[0][4] + mix->matrix[0][6]) * 0.5f;
const float v5 = (mix->matrix[1][5] + mix->matrix[1][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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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 rlev0 = mix->matrix[0][6];
const float rlev1 = mix->matrix[1][7]; 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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); memset(d[i], 0, n_samples * sizeof(float));
} }

View file

@ -33,11 +33,11 @@ void channelmix_copy_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_REST
float **d = (float **)dst; float **d = (float **)dst;
const float **s = (const float **)src; 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++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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++) for (i = 0; i < n_dst; i++)
spa_memcpy(d[i], s[i], n_samples * sizeof(float)); 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; uint32_t i, n, unrolled;
float **d = (float **)dst; float **d = (float **)dst;
const float **s = (const float **)src; const float **s = (const float **)src;
const __m128 v0 = _mm_set1_ps(mix->matrix[0][0]); const float m00 = mix->matrix[0][0];
const __m128 v1 = _mm_set1_ps(mix->matrix[1][1]); const float m11 = mix->matrix[1][1];
__m128 in; __m128 in;
const float *sFL = s[0], *sFR = s[1]; const float *sFL = s[0], *sFR = s[1];
float *dFL = d[0], *dFR = d[1], *dRL = d[2], *dRR = d[3]; 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 else
unrolled = 0; unrolled = 0;
if (mix->zero) { if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
for (i = 0; i < n_dst; i++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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) { for(n = 0; n < unrolled; n += 4) {
in = _mm_load_ps(&sFL[n]); in = _mm_load_ps(&sFL[n]);
_mm_store_ps(&dFL[n], in); _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 { else {
const __m128 v0 = _mm_set1_ps(m00);
const __m128 v1 = _mm_set1_ps(m11);
for(n = 0; n < unrolled; n += 4) { for(n = 0; n < unrolled; n += 4) {
in = _mm_mul_ps(_mm_load_ps(&sFL[n]), v0); in = _mm_mul_ps(_mm_load_ps(&sFL[n]), v0);
_mm_store_ps(&dFL[n], in); _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; uint32_t n, unrolled;
float **d = (float **) dst; float **d = (float **) dst;
const float **s = (const float **) src; const float **s = (const float **) src;
const __m128 v0 = _mm_set1_ps(mix->matrix[0][0]); const float m00 = mix->matrix[0][0];
const __m128 v1 = _mm_set1_ps(mix->matrix[1][1]); 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 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 llev = _mm_set1_ps((mix->matrix[0][3] + mix->matrix[1][3]) * 0.5f);
const __m128 slev0 = _mm_set1_ps(mix->matrix[0][4]); 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 else
unrolled = 0; unrolled = 0;
if (mix->zero) { if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
memset(dFL, 0, n_samples * sizeof(float)); memset(dFL, 0, n_samples * sizeof(float));
memset(dFR, 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) { for(n = 0; n < unrolled; n += 4) {
ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev); ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev);
ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev)); 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 { else {
const __m128 v0 = _mm_set1_ps(m00);
const __m128 v1 = _mm_set1_ps(m11);
for(n = 0; n < unrolled; n += 4) { for(n = 0; n < unrolled; n += 4) {
ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev); ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev);
ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev)); 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 else
unrolled = 0; unrolled = 0;
if (mix->zero) { if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
for (i = 0; i < n_dst; i++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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 float **s = (const float **) src;
const __m128 clev = _mm_set1_ps(mix->matrix[0][2]); const __m128 clev = _mm_set1_ps(mix->matrix[0][2]);
const __m128 llev = _mm_set1_ps(mix->matrix[0][3]); const __m128 llev = _mm_set1_ps(mix->matrix[0][3]);
const __m128 v0 = _mm_set1_ps(mix->matrix[0][0]); const float m00 = mix->matrix[0][0];
const __m128 v1 = _mm_set1_ps(mix->matrix[1][1]); const float m11 = mix->matrix[1][1];
const __m128 v4 = _mm_set1_ps(mix->matrix[2][4]); const float m24 = mix->matrix[2][4];
const __m128 v5 = _mm_set1_ps(mix->matrix[3][5]); const float m35 = mix->matrix[3][5];
__m128 ctr; __m128 ctr;
const float *sFL = s[0], *sFR = s[1], *sFC = s[2], *sLFE = s[3], *sSL = s[4], *sSR = s[5]; 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]; 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 else
unrolled = 0; unrolled = 0;
if (mix->zero) { if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
for (i = 0; i < n_dst; i++) for (i = 0; i < n_dst; i++)
memset(d[i], 0, n_samples * sizeof(float)); 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) { for(n = 0; n < unrolled; n += 4) {
ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev); ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev);
ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev)); 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 { 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) { for(n = 0; n < unrolled; n += 4) {
ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev); ctr = _mm_mul_ps(_mm_load_ps(&sFC[n]), clev);
ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev)); ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFE[n]), llev));

View file

@ -318,7 +318,8 @@ static int make_matrix(struct channelmix *mix)
spa_log_warn(mix->log, "can't assign FLC"); 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)) { if (dst_mask & _MASK(FC)) {
matrix[FC][LFE] += llev; matrix[FC][LFE] += llev;
} else if (dst_mask & _MASK(FL)) { } 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]; mix->matrix_orig[ic][jc++] = matrix[i][j];
sum += fabs(matrix[i][j]); sum += fabs(matrix[i][j]);
} }
#if 0
if (sum > 1.0f) if (sum > 1.0f)
for (j = 0; j < jc; j++) for (j = 0; j < jc; j++)
mix->matrix_orig[ic][j] /= sum; mix->matrix_orig[ic][j] /= sum;
#endif
ic++; ic++;
} }
return 0; 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; uint32_t dst_chan = mix->dst_chan;
/** apply global volume to channels */ /** 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; volumes[i] = channel_volumes[i] * vol;
if (volumes[i] != 1.0f)
mix->norm = false;
}
/** apply volumes per channel */
if (n_channel_volumes == src_chan) { if (n_channel_volumes == src_chan) {
for (i = 0; i < dst_chan; i++) { for (i = 0; i < dst_chan; i++) {
for (j = 0; j < src_chan; j++) { 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; SPA_FLAG_SET(mix->flags, CHANNELMIX_FLAG_ZERO);
mix->equal = true; SPA_FLAG_SET(mix->flags, CHANNELMIX_FLAG_EQUAL);
mix->identity = dst_chan == src_chan; SPA_FLAG_UPDATE(mix->flags, CHANNELMIX_FLAG_IDENTITY, dst_chan == src_chan);
t = 0.0;
t = 0.0;
for (i = 0; i < dst_chan; i++) { for (i = 0; i < dst_chan; i++) {
for (j = 0; j < src_chan; j++) { for (j = 0; j < src_chan; j++) {
float v = mix->matrix[i][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) if (i == 0 && j == 0)
t = v; t = v;
else if (t != v) else if (t != v)
mix->equal = false; SPA_FLAG_CLEAR(mix->flags, CHANNELMIX_FLAG_EQUAL);
if (v != 0.0) if (v != 0.0)
mix->zero = false; SPA_FLAG_CLEAR(mix->flags, CHANNELMIX_FLAG_ZERO);
if ((i == j && v != 1.0f) || if ((i == j && v != 1.0f) ||
(i != j && v != 0.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) static void impl_channelmix_free(struct channelmix *mix)

View file

@ -46,13 +46,15 @@ struct channelmix {
uint64_t src_mask; uint64_t src_mask;
uint64_t dst_mask; uint64_t dst_mask;
uint32_t cpu_flags; uint32_t cpu_flags;
#define CHANNELMIX_OPTION_MIX_LFE (1<<0) /**< mix LFE */
uint32_t options;
struct spa_log *log; struct spa_log *log;
unsigned int zero:1; /* all zero components */ #define CHANNELMIX_FLAG_ZERO (1<<0) /**< all zero components */
unsigned int identity:1; /* identity matrix */ #define CHANNELMIX_FLAG_IDENTITY (1<<1) /**< identity matrix */
unsigned int norm:1; /* all normal values */ #define CHANNELMIX_FLAG_EQUAL (1<<2) /**< all values are equal */
unsigned int equal:1; /* all values are equal */ uint32_t flags;
float matrix_orig[SPA_AUDIO_MAX_CHANNELS][SPA_AUDIO_MAX_CHANNELS]; float matrix_orig[SPA_AUDIO_MAX_CHANNELS][SPA_AUDIO_MAX_CHANNELS];
float matrix[SPA_AUDIO_MAX_CHANNELS][SPA_AUDIO_MAX_CHANNELS]; float matrix[SPA_AUDIO_MAX_CHANNELS][SPA_AUDIO_MAX_CHANNELS];

View file

@ -256,11 +256,11 @@ static int setup_convert(struct impl *this,
emit_params_changed(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, 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; return 0;
} }
@ -1057,7 +1057,9 @@ static int impl_node_process(void *object)
void *dst_datas[n_dst_datas]; void *dst_datas[n_dst_datas];
bool is_passthrough; 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; n_samples = sb->datas[0].chunk->size / inport->stride;