channelmix: improve mixing setup

Handle MONO layout as a real layout, not just like FC. This means it
does not share the FC mixing weights.
Only distribute and combine MONO channels when the target is also
MONO, enable normalization in this case.
Otherwise downmix and upmix the mono channels like any other channel,
which will make it respect the upmix and other settings.
Change some tests with this new way of doing things.

Fixes #3010
This commit is contained in:
Wim Taymans 2023-02-06 21:05:23 +01:00
parent 987b772b97
commit b9999b292d
3 changed files with 191 additions and 89 deletions

View file

@ -142,7 +142,8 @@ static const struct channelmix_info *find_channelmix_info(uint32_t src_chan, uin
#define MATRIX_DOLBY 1
#define MATRIX_DPLII 2
#define _CH(ch) ((SPA_AUDIO_CHANNEL_ ## ch)-3)
#define _SH 2
#define _CH(ch) ((SPA_AUDIO_CHANNEL_ ## ch)-_SH)
#define _MASK(ch) (1ULL << _CH(ch))
#define FRONT (_MASK(FC))
#define STEREO (_MASK(FL)|_MASK(FR))
@ -162,57 +163,49 @@ static int make_matrix(struct channelmix *mix)
float slev = SQRT1_2;
float llev = 0.5f;
float maxsum = 0.0f;
bool filter_fc = false, filter_lfe = false;
bool filter_fc = false, filter_lfe = false, matched = false, normalize;
#define _MATRIX(s,d) matrix[_CH(s)][_CH(d)]
normalize = SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_NORMALIZE);
spa_log_debug(mix->log, "src-mask:%08"PRIx64" dst-mask:%08"PRIx64
" options:%08x", src_mask, dst_mask, mix->options);
/* move the MONO mask to FRONT so that the lower bits can be shifted
* away. */
if ((src_mask & (1Ull << SPA_AUDIO_CHANNEL_MONO)) != 0) {
if (src_chan == 1)
src_mask = 0;
else
src_mask |= (1ULL << SPA_AUDIO_CHANNEL_FC);
}
if ((dst_mask & (1Ull << SPA_AUDIO_CHANNEL_MONO)) != 0)
dst_mask |= (1ULL << SPA_AUDIO_CHANNEL_FC);
/* shift so that bit 0 is MONO */
src_mask >>= _SH;
dst_mask >>= _SH;
/* shift so that bit 0 is FL */
src_mask >>= 3;
dst_mask >>= 3;
if (src_mask == 0)
src_mask = _MASK(MONO);
if (dst_mask == 0)
dst_mask = _MASK(MONO);
/* unknown channels or just 1 channel */
if (src_mask == 0 || dst_mask == 0) {
/* unknown channels or just mono channels */
if (src_mask & _MASK(MONO) && dst_mask & _MASK(MONO)) {
if (src_chan == 1) {
/* one FC/MONO src goes everywhere */
spa_log_debug(mix->log, "distribute FC/MONO (%f)", 1.0f);
/* one MONO src goes everywhere */
spa_log_info(mix->log, "distribute MONO (%f)", 1.0f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
matrix[i][0]= 1.0f;
} else if (dst_chan == 1) {
/* one FC/MONO dst get average of everything */
spa_log_debug(mix->log, "average FC/MONO (%f)", 1.0f / src_chan);
/* one MONO dst get average of everything */
spa_log_info(mix->log, "average MONO (%f)", 1.0f / src_chan);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
matrix[0][i]= 1.0f / src_chan;
} else {
/* just pair channels */
spa_log_debug(mix->log, "pairing channels (%f)", 1.0f);
spa_log_info(mix->log, "pairing channels (%f)", 1.0f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
matrix[i][i]= 1.0f;
}
if (dst_mask & FRONT)
filter_fc = true;
if (dst_mask & _MASK(LFE))
filter_lfe = true;
src_mask = dst_mask = ~0LU;
goto done;
} else {
spa_log_debug(mix->log, "matching channels");
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
if ((src_mask & dst_mask & (1ULL << i))) {
spa_log_debug(mix->log, "matched channel %u (%f)", i, 1.0f);
spa_log_info(mix->log, "matched channel %u (%f)", i, 1.0f);
matrix[i][i]= 1.0f;
matched = true;
}
}
}
@ -221,30 +214,60 @@ static int make_matrix(struct channelmix *mix)
keep = dst_mask & ~src_mask;
if (!SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_UPMIX)) {
/* upmix completely disabled */
keep = 0;
} else {
/* some upmixing (FC and LFE) enabled. */
if (mix->upmix == CHANNELMIX_UPMIX_NONE)
keep = 0;
keep |= FRONT;
if (mix->fc_cutoff > 0.0f)
keep |= FRONT;
else
keep &= ~FRONT;
if (mix->lfe_cutoff > 0.0f)
keep |= _MASK(LFE);
else
keep &= ~_MASK(LFE);
}
/* if we have no channel matched, try to upmix or keep the stereo
* pair or else we might end up with silence. */
if (dst_mask & STEREO && !matched)
keep |= STEREO;
spa_log_debug(mix->log, "unassigned downmix %08" PRIx64 " %08" PRIx64, unassigned, keep);
spa_log_info(mix->log, "unassigned downmix %08" PRIx64 " %08" PRIx64, unassigned, keep);
if (unassigned & FRONT){
if (unassigned & _MASK(MONO)) {
if ((dst_mask & STEREO) == STEREO) {
spa_log_info(mix->log, "assign MONO to STEREO (%f)", 1.0f);
_MATRIX(FL,MONO) += 1.0f;
_MATRIX(FR,MONO) += 1.0f;
keep &= ~STEREO;
} else if ((dst_mask & FRONT) == FRONT) {
spa_log_info(mix->log, "assign MONO to FRONT (%f)", 1.0f);
_MATRIX(FC,MONO) += 1.0f;
normalize = true;
} else {
spa_log_warn(mix->log, "can't assign MONO");
}
}
if (unassigned & FRONT) {
if ((dst_mask & STEREO) == STEREO){
if(src_mask & STEREO) {
spa_log_debug(mix->log, "assign FC to STEREO (%f)", clev);
if (src_mask & STEREO) {
spa_log_info(mix->log, "assign FC to STEREO (%f)", clev);
_MATRIX(FL,FC) += clev;
_MATRIX(FR,FC) += clev;
} else {
spa_log_debug(mix->log, "assign FC to STEREO (%f)", SQRT1_2);
spa_log_info(mix->log, "assign FC to STEREO (%f)", SQRT1_2);
_MATRIX(FL,FC) += SQRT1_2;
_MATRIX(FR,FC) += SQRT1_2;
}
keep &= ~STEREO;
} else if (dst_mask & _MASK(MONO)){
spa_log_info(mix->log, "assign FC to MONO (%f)", 1.0f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
matrix[i][_CH(FC)]= 1.0f;
normalize = true;
} else {
spa_log_warn(mix->log, "can't assign FC");
}
@ -252,14 +275,21 @@ static int make_matrix(struct channelmix *mix)
if (unassigned & STEREO){
if (dst_mask & FRONT) {
spa_log_debug(mix->log, "assign STEREO to FC (%f)", SQRT1_2);
spa_log_info(mix->log, "assign STEREO to FC (%f)", SQRT1_2);
_MATRIX(FC,FL) += SQRT1_2;
_MATRIX(FC,FR) += SQRT1_2;
if (src_mask & FRONT) {
spa_log_debug(mix->log, "assign FC to FC (%f)", clev * SQRT2);
spa_log_info(mix->log, "assign FC to FC (%f)", clev * SQRT2);
_MATRIX(FC,FC) = clev * SQRT2;
}
keep &= ~FRONT;
} else if ((dst_mask & _MASK(MONO))){
spa_log_info(mix->log, "assign STEREO to MONO (%f)", 0.5f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
matrix[i][_CH(FL)]= 1.0f;
matrix[i][_CH(FR)]= 1.0f;
}
normalize = true;
} else {
spa_log_warn(mix->log, "can't assign STEREO");
}
@ -267,15 +297,15 @@ static int make_matrix(struct channelmix *mix)
if (unassigned & _MASK(RC)) {
if (dst_mask & REAR){
spa_log_debug(mix->log, "assign RC to RL+RR (%f)", SQRT1_2);
spa_log_info(mix->log, "assign RC to RL+RR (%f)", SQRT1_2);
_MATRIX(RL,RC) += SQRT1_2;
_MATRIX(RR,RC) += SQRT1_2;
} else if (dst_mask & SIDE) {
spa_log_debug(mix->log, "assign RC to SL+SR (%f)", SQRT1_2);
spa_log_info(mix->log, "assign RC to SL+SR (%f)", SQRT1_2);
_MATRIX(SL,RC) += SQRT1_2;
_MATRIX(SR,RC) += SQRT1_2;
} else if(dst_mask & STEREO) {
spa_log_debug(mix->log, "assign RC to FL+FR");
spa_log_info(mix->log, "assign RC to FL+FR");
if (matrix_encoding == MATRIX_DOLBY ||
matrix_encoding == MATRIX_DPLII) {
if (unassigned & (_MASK(RL)|_MASK(RR))) {
@ -290,8 +320,13 @@ static int make_matrix(struct channelmix *mix)
_MATRIX(FR,RC) += slev * SQRT1_2;
}
} else if (dst_mask & FRONT) {
spa_log_debug(mix->log, "assign RC to FC (%f)", slev * SQRT1_2);
spa_log_info(mix->log, "assign RC to FC (%f)", slev * SQRT1_2);
_MATRIX(FC,RC) += slev * SQRT1_2;
} else if (dst_mask & _MASK(MONO)){
spa_log_info(mix->log, "assign RC to MONO (%f)", 1.0f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
matrix[i][_CH(RC)]= 1.0f;
normalize = true;
} else {
spa_log_warn(mix->log, "can't assign RC");
}
@ -299,11 +334,11 @@ static int make_matrix(struct channelmix *mix)
if (unassigned & REAR) {
if (dst_mask & _MASK(RC)) {
spa_log_debug(mix->log, "assign RL+RR to RC");
spa_log_info(mix->log, "assign RL+RR to RC");
_MATRIX(RC,RL) += SQRT1_2;
_MATRIX(RC,RR) += SQRT1_2;
} else if (dst_mask & SIDE) {
spa_log_debug(mix->log, "assign RL+RR to SL+SR");
spa_log_info(mix->log, "assign RL+RR to SL+SR");
if (src_mask & SIDE) {
_MATRIX(SL,RL) += SQRT1_2;
_MATRIX(SR,RR) += SQRT1_2;
@ -313,7 +348,7 @@ static int make_matrix(struct channelmix *mix)
}
keep &= ~SIDE;
} else if (dst_mask & STEREO) {
spa_log_debug(mix->log, "assign RL+RR to FL+FR (%f)", slev);
spa_log_info(mix->log, "assign RL+RR to FL+FR (%f)", slev);
if (matrix_encoding == MATRIX_DOLBY) {
_MATRIX(FL,RL) -= slev * SQRT1_2;
_MATRIX(FL,RR) -= slev * SQRT1_2;
@ -329,10 +364,17 @@ static int make_matrix(struct channelmix *mix)
_MATRIX(FR,RR) += slev;
}
} else if (dst_mask & FRONT) {
spa_log_debug(mix->log, "assign RL+RR to FC (%f)",
spa_log_info(mix->log, "assign RL+RR to FC (%f)",
slev * SQRT1_2);
_MATRIX(FC,RL)+= slev * SQRT1_2;
_MATRIX(FC,RR)+= slev * SQRT1_2;
} else if (dst_mask & _MASK(MONO)){
spa_log_info(mix->log, "assign RL+RR to MONO (%f)", 1.0f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
matrix[i][_CH(RL)]= 1.0f;
matrix[i][_CH(RR)]= 1.0f;
}
normalize = true;
} else {
spa_log_warn(mix->log, "can't assign RL");
}
@ -341,43 +383,50 @@ static int make_matrix(struct channelmix *mix)
if (unassigned & SIDE) {
if (dst_mask & REAR) {
if (src_mask & _MASK(RL)) {
spa_log_debug(mix->log, "assign SL+SR to RL+RR (%f)", SQRT1_2);
spa_log_info(mix->log, "assign SL+SR to RL+RR (%f)", SQRT1_2);
_MATRIX(RL,SL) += SQRT1_2;
_MATRIX(RR,SR) += SQRT1_2;
} else {
spa_log_debug(mix->log, "assign SL+SR to RL+RR (%f)", 1.0f);
spa_log_info(mix->log, "assign SL+SR to RL+RR (%f)", 1.0f);
_MATRIX(RL,SL) += 1.0f;
_MATRIX(RR,SR) += 1.0f;
}
keep &= ~REAR;
} else if (dst_mask & _MASK(RC)) {
spa_log_debug(mix->log, "assign SL+SR to RC (%f)", SQRT1_2);
spa_log_info(mix->log, "assign SL+SR to RC (%f)", SQRT1_2);
_MATRIX(RC,SL)+= SQRT1_2;
_MATRIX(RC,SR)+= SQRT1_2;
} else if (dst_mask & STEREO) {
if (matrix_encoding == MATRIX_DOLBY) {
spa_log_debug(mix->log, "assign SL+SR to FL+FR (%f)",
spa_log_info(mix->log, "assign SL+SR to FL+FR (%f)",
slev * SQRT1_2);
_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) {
spa_log_debug(mix->log, "assign SL+SR to FL+FR (%f / %f)",
spa_log_info(mix->log, "assign SL+SR to FL+FR (%f / %f)",
slev * SQRT3_2, slev * SQRT1_2);
_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 {
spa_log_debug(mix->log, "assign SL+SR to FL+FR (%f)", slev);
spa_log_info(mix->log, "assign SL+SR to FL+FR (%f)", slev);
_MATRIX(FL,SL) += slev;
_MATRIX(FR,SR) += slev;
}
} else if (dst_mask & FRONT) {
spa_log_debug(mix->log, "assign SL+SR to FC (%f)", slev * SQRT1_2);
spa_log_info(mix->log, "assign SL+SR to FC (%f)", slev * SQRT1_2);
_MATRIX(FC,SL) += slev * SQRT1_2;
_MATRIX(FC,SR) += slev * SQRT1_2;
} else if (dst_mask & _MASK(MONO)){
spa_log_info(mix->log, "assign SL+SR to MONO (%f)", 1.0f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
matrix[i][_CH(SL)]= 1.0f;
matrix[i][_CH(SR)]= 1.0f;
}
normalize = true;
} else {
spa_log_warn(mix->log, "can't assign SL");
}
@ -385,13 +434,20 @@ static int make_matrix(struct channelmix *mix)
if (unassigned & _MASK(FLC)) {
if (dst_mask & STEREO) {
spa_log_debug(mix->log, "assign FLC+FRC to FL+FR (%f)", 1.0f);
spa_log_info(mix->log, "assign FLC+FRC to FL+FR (%f)", 1.0f);
_MATRIX(FL,FLC)+= 1.0f;
_MATRIX(FR,FRC)+= 1.0f;
} else if(dst_mask & FRONT) {
spa_log_debug(mix->log, "assign FLC+FRC to FC (%f)", SQRT1_2);
spa_log_info(mix->log, "assign FLC+FRC to FC (%f)", SQRT1_2);
_MATRIX(FC,FLC)+= SQRT1_2;
_MATRIX(FC,FRC)+= SQRT1_2;
} else if (dst_mask & _MASK(MONO)){
spa_log_info(mix->log, "assign FLC+FRC to MONO (%f)", 1.0f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
matrix[i][_CH(FLC)]= 1.0f;
matrix[i][_CH(FRC)]= 1.0f;
}
normalize = true;
} else {
spa_log_warn(mix->log, "can't assign FLC");
}
@ -399,13 +455,18 @@ static int make_matrix(struct channelmix *mix)
if (unassigned & _MASK(LFE) &&
SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_MIX_LFE)) {
if (dst_mask & FRONT) {
spa_log_debug(mix->log, "assign LFE to FC (%f)", llev);
spa_log_info(mix->log, "assign LFE to FC (%f)", llev);
_MATRIX(FC,LFE) += llev;
} else if (dst_mask & STEREO) {
spa_log_debug(mix->log, "assign LFE to FL+FR (%f)",
spa_log_info(mix->log, "assign LFE to FL+FR (%f)",
llev * SQRT1_2);
_MATRIX(FL,LFE) += llev * SQRT1_2;
_MATRIX(FR,LFE) += llev * SQRT1_2;
} else if ((dst_mask & _MASK(MONO))){
spa_log_info(mix->log, "assign LFE to MONO (%f)", 0.5f);
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
matrix[i][_CH(LFE)]= 1.0f;
normalize = true;
} else {
spa_log_warn(mix->log, "can't assign LFE");
}
@ -413,101 +474,132 @@ static int make_matrix(struct channelmix *mix)
unassigned = dst_mask & ~src_mask & keep;
spa_log_debug(mix->log, "unassigned upmix %08"PRIx64" lfe:%f",
spa_log_info(mix->log, "unassigned upmix %08"PRIx64" lfe:%f",
unassigned, mix->lfe_cutoff);
if (unassigned & STEREO) {
if ((src_mask & FRONT) == FRONT) {
spa_log_debug(mix->log, "produce STEREO from FC (%f)", clev);
spa_log_info(mix->log, "produce STEREO from FC (%f)", clev);
_MATRIX(FL,FC) += clev;
_MATRIX(FR,FC) += clev;
} else if (src_mask & _MASK(MONO)) {
spa_log_info(mix->log, "produce STEREO from MONO (%f)", 1.0f);
_MATRIX(FL,MONO) += 1.0f;
_MATRIX(FR,MONO) += 1.0f;
} else {
spa_log_warn(mix->log, "can't produce STEREO");
}
}
if (unassigned & FRONT) {
if ((src_mask & STEREO) == STEREO) {
spa_log_debug(mix->log, "produce FC from STEREO (%f)", clev);
spa_log_info(mix->log, "produce FC from STEREO (%f)", clev);
_MATRIX(FC,FL) += clev;
_MATRIX(FC,FR) += clev;
filter_fc = true;
} else if (src_mask & _MASK(MONO)) {
spa_log_info(mix->log, "produce FC from MONO (%f)", 1.0f);
_MATRIX(FC,MONO) += 1.0f;
filter_fc = true;
} else {
spa_log_warn(mix->log, "can't produce FC");
}
}
if (unassigned & _MASK(LFE)) {
if ((src_mask & STEREO) == STEREO) {
spa_log_debug(mix->log, "produce LFE from STEREO (%f)", llev);
spa_log_info(mix->log, "produce LFE from STEREO (%f)", llev);
_MATRIX(LFE,FL) += llev;
_MATRIX(LFE,FR) += llev;
filter_lfe = true;
} else if ((src_mask & FRONT) == FRONT) {
spa_log_debug(mix->log, "produce LFE from FC (%f)", llev);
spa_log_info(mix->log, "produce LFE from FC (%f)", llev);
_MATRIX(LFE,FC) += llev;
filter_lfe = true;
} else if (src_mask & _MASK(MONO)) {
spa_log_info(mix->log, "produce LFE from MONO (%f)", 1.0f);
_MATRIX(LFE,MONO) += 1.0f;
filter_lfe = true;
} else {
spa_log_warn(mix->log, "can't produce LFE");
}
}
if (unassigned & SIDE) {
if ((src_mask & REAR) == REAR) {
spa_log_debug(mix->log, "produce SIDE from REAR (%f)", 1.0f);
spa_log_info(mix->log, "produce SIDE from REAR (%f)", 1.0f);
_MATRIX(SL,RL) += 1.0f;
_MATRIX(SR,RR) += 1.0f;
} else if ((src_mask & STEREO) == STEREO) {
spa_log_debug(mix->log, "produce SIDE from STEREO (%f)", slev);
spa_log_info(mix->log, "produce SIDE from STEREO (%f)", slev);
_MATRIX(SL,FL) += slev;
_MATRIX(SR,FR) += slev;
} else if ((src_mask & FRONT) == FRONT &&
mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
spa_log_debug(mix->log, "produce SIDE from FC (%f)", clev);
spa_log_info(mix->log, "produce SIDE from FC (%f)", clev);
_MATRIX(SL,FC) += clev;
_MATRIX(SR,FC) += clev;
} else if (src_mask & _MASK(MONO) &&
mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
spa_log_info(mix->log, "produce SIDE from MONO (%f)", 1.0f);
_MATRIX(SL,MONO) += 1.0f;
_MATRIX(SR,MONO) += 1.0f;
} else {
spa_log_debug(mix->log, "won't produce SIDE");
spa_log_info(mix->log, "won't produce SIDE");
}
}
if (unassigned & REAR) {
if ((src_mask & SIDE) == SIDE) {
spa_log_debug(mix->log, "produce REAR from SIDE (%f)", 1.0f);
spa_log_info(mix->log, "produce REAR from SIDE (%f)", 1.0f);
_MATRIX(RL,SL) += 1.0f;
_MATRIX(RR,SR) += 1.0f;
} else if ((src_mask & STEREO) == STEREO) {
spa_log_debug(mix->log, "produce REAR from STEREO (%f)", slev);
spa_log_info(mix->log, "produce REAR from STEREO (%f)", slev);
_MATRIX(RL,FL) += slev;
_MATRIX(RR,FR) += slev;
} else if ((src_mask & FRONT) == FRONT &&
mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
spa_log_debug(mix->log, "produce REAR from FC (%f)", clev);
spa_log_info(mix->log, "produce REAR from FC (%f)", clev);
_MATRIX(RL,FC) += clev;
_MATRIX(RR,FC) += clev;
} else if (src_mask & _MASK(MONO) &&
mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
spa_log_info(mix->log, "produce REAR from MONO (%f)", 1.0f);
_MATRIX(RL,MONO) += 1.0f;
_MATRIX(RR,MONO) += 1.0f;
} else {
spa_log_debug(mix->log, "won't produce SIDE");
spa_log_info(mix->log, "won't produce SIDE");
}
}
if (unassigned & _MASK(RC)) {
if ((src_mask & REAR) == REAR) {
spa_log_debug(mix->log, "produce RC from REAR (%f)", 0.5f);
spa_log_info(mix->log, "produce RC from REAR (%f)", 0.5f);
_MATRIX(RC,RL) += 0.5f;
_MATRIX(RC,RR) += 0.5f;
} else if ((src_mask & SIDE) == SIDE) {
spa_log_debug(mix->log, "produce RC from SIDE (%f)", 0.5f);
spa_log_info(mix->log, "produce RC from SIDE (%f)", 0.5f);
_MATRIX(RC,SL) += 0.5f;
_MATRIX(RC,SR) += 0.5f;
} else if ((src_mask & STEREO) == STEREO) {
spa_log_debug(mix->log, "produce RC from STEREO (%f)", 0.5f);
spa_log_info(mix->log, "produce RC from STEREO (%f)", 0.5f);
_MATRIX(RC,FL) += 0.5f;
_MATRIX(RC,FR) += 0.5f;
} else if ((src_mask & FRONT) == FRONT &&
mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
spa_log_debug(mix->log, "produce RC from FC (%f)", slev);
spa_log_info(mix->log, "produce RC from FC (%f)", slev);
_MATRIX(RC,FC) += slev;
} else if (src_mask & _MASK(MONO) &&
mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
spa_log_info(mix->log, "produce RC from MONO (%f)", 1.0f);
_MATRIX(RC,MONO) += 1.0f;
} else {
spa_log_debug(mix->log, "won't produce RC");
spa_log_info(mix->log, "won't produce RC");
}
}
done:
if (dst_mask & _MASK(MONO))
dst_mask = ~0LU;
if (src_mask & _MASK(MONO))
src_mask = ~0LU;
for (jc = 0, ic = 0, i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
float sum = 0.0f;
char str[1024], str2[1024];
@ -523,7 +615,7 @@ done:
if (ic == 0)
idx2 += snprintf(str2 + idx2, sizeof(str2) - idx2, "%-4.4s ",
src_mask == ~0LU ? "MONO" :
spa_debug_type_find_short_name(spa_type_audio_channel, j + 3));
spa_debug_type_find_short_name(spa_type_audio_channel, j + _SH));
mix->matrix_orig[ic][jc++] = matrix[i][j];
sum += fabs(matrix[i][j]);
@ -538,7 +630,7 @@ done:
if (idx > 0) {
spa_log_info(mix->log, "%-4.4s %s %f",
dst_mask == ~0LU ? "MONO" :
spa_debug_type_find_short_name(spa_type_audio_channel, i + 3),
spa_debug_type_find_short_name(spa_type_audio_channel, i + _SH),
str, sum);
}
@ -554,9 +646,8 @@ done:
}
ic++;
}
if (SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_NORMALIZE) &&
maxsum > 1.0f) {
spa_log_debug(mix->log, "normalize %f", maxsum);
if (normalize && maxsum > 1.0f) {
spa_log_info(mix->log, "normalize %f", maxsum);
for (i = 0; i < dst_chan; i++)
for (j = 0; j < src_chan; j++)
mix->matrix_orig[i][j] /= maxsum;