diff --git a/spa/plugins/audioconvert/channelmix-ops.c b/spa/plugins/audioconvert/channelmix-ops.c index 3d88f5db6..50b8b379d 100644 --- a/spa/plugins/audioconvert/channelmix-ops.c +++ b/spa/plugins/audioconvert/channelmix-ops.c @@ -220,22 +220,6 @@ static int make_matrix(struct channelmix *mix) } } - if (mix->src_chan <= 3 && (src_mask & STEREO) == STEREO && (dst_mask & REAR) == REAR) { - spa_log_debug(mix->log, "copy STEREO to REAR"); - if ((src_mask & _MASK(RL)) == 0) - matrix[RL][FL] = 1.0f; - if ((src_mask & _MASK(RR)) == 0) - matrix[RR][FR] = 1.0f; - - if ((dst_mask & SIDE) == SIDE) { - spa_log_debug(mix->log, "copy STEREO to SIDES"); - if ((src_mask & _MASK(SL)) == 0) - matrix[SL][FL] = 1.0f; - if ((src_mask & _MASK(SR)) == 0) - matrix[SR][FR] = 1.0f; - } - } - if (unassigned & STEREO){ if (dst_mask & _MASK(FC)) { spa_log_debug(mix->log, "assign STEREO to FC"); @@ -384,6 +368,58 @@ static int make_matrix(struct channelmix *mix) spa_log_warn(mix->log, "can't assign LFE"); } } + + if (!SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_UPMIX)) + goto done; + + unassigned = dst_mask & ~src_mask; + + spa_log_debug(mix->log, "unassigned upmix %08" PRIx64, unassigned); + + if (unassigned & _MASK(FC)) { + if ((src_mask & STEREO) == STEREO) { + spa_log_debug(mix->log, "produce FC from STEREO"); + matrix[FC][FL] += clev; + matrix[FC][FR] += clev; + } else { + spa_log_warn(mix->log, "can't produce FC"); + } + } + if (unassigned & _MASK(LFE) && + SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_FILTER_LFE)) { + if ((src_mask & STEREO) == STEREO) { + spa_log_debug(mix->log, "produce LFE from STEREO"); + matrix[LFE][FL] += llev; + matrix[LFE][FR] += llev; + } 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"); + 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"); + matrix[SL][FL] += 1.0f; + matrix[SR][FR] += 1.0f; + } + } + if (unassigned & REAR) { + if ((src_mask & SIDE) == SIDE) { + spa_log_debug(mix->log, "produce REAR from SIDE"); + 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"); + matrix[RL][FL] += 1.0f; + matrix[RR][FR] += 1.0f; + } + } + done: for (jc = 0, ic = 0, i = 0; i < NUM_CHAN; i++) { float sum = 0.0f; diff --git a/spa/plugins/audioconvert/channelmix-ops.h b/spa/plugins/audioconvert/channelmix-ops.h index a89e66a50..23c986a9f 100644 --- a/spa/plugins/audioconvert/channelmix-ops.h +++ b/spa/plugins/audioconvert/channelmix-ops.h @@ -48,6 +48,8 @@ struct channelmix { uint32_t cpu_flags; #define CHANNELMIX_OPTION_MIX_LFE (1<<0) /**< mix LFE */ #define CHANNELMIX_OPTION_NORMALIZE (1<<1) /**< normalize volumes */ +#define CHANNELMIX_OPTION_UPMIX (1<<2) /**< do simple upmixing */ +#define CHANNELMIX_OPTION_FILTER_LFE (1<<3) /**< generate and filter LFE */ uint32_t options; struct spa_log *log; diff --git a/spa/plugins/audioconvert/channelmix.c b/spa/plugins/audioconvert/channelmix.c index 9c3cda79e..2f886fc20 100644 --- a/spa/plugins/audioconvert/channelmix.c +++ b/spa/plugins/audioconvert/channelmix.c @@ -1250,6 +1250,12 @@ impl_init(const struct spa_handle_factory *factory, if ((str = spa_dict_lookup(info, "channelmix.mix-lfe")) != NULL && (strcmp(str, "true") == 0 || atoi(str) != 0)) this->mix.options |= CHANNELMIX_OPTION_MIX_LFE; + if ((str = spa_dict_lookup(info, "channelmix.upmix")) != NULL && + (strcmp(str, "true") == 0 || atoi(str) != 0)) + this->mix.options |= CHANNELMIX_OPTION_UPMIX; + if ((str = spa_dict_lookup(info, "channelmix.filter-lfe")) != NULL && + (strcmp(str, "true") == 0 || atoi(str) != 0)) + this->mix.options |= CHANNELMIX_OPTION_FILTER_LFE; if ((str = spa_dict_lookup(info, SPA_KEY_AUDIO_POSITION)) != NULL) { size_t len; const char *p = str; diff --git a/src/daemon/client-rt.conf.in b/src/daemon/client-rt.conf.in index 3a26cb38a..1a667e9f8 100644 --- a/src/daemon/client-rt.conf.in +++ b/src/daemon/client-rt.conf.in @@ -72,5 +72,7 @@ stream.properties = { #node.latency = 1024/48000 #resample.quality = 4 #channelmix.normalize = false - #channelmix.mix-lfe = false + #channelmix.mix-lfe = true + channelmix.upmix = true + #channelmix.filter-lfe = false } diff --git a/src/daemon/client.conf.in b/src/daemon/client.conf.in index c97c6da0f..83a9270a0 100644 --- a/src/daemon/client.conf.in +++ b/src/daemon/client.conf.in @@ -62,4 +62,6 @@ stream.properties = { #resample.quality = 4 #channelmix.normalize = false #channelmix.mix-lfe = false + channelmix.upmix = true + #channelmix.filter-lfe = false } diff --git a/src/daemon/pipewire-pulse.conf.in b/src/daemon/pipewire-pulse.conf.in index bbf05f56e..4e348bd1b 100644 --- a/src/daemon/pipewire-pulse.conf.in +++ b/src/daemon/pipewire-pulse.conf.in @@ -49,4 +49,6 @@ stream.properties = { #resample.quality = 4 #channelmix.normalize = false #channelmix.mix-lfe = false + channelmix.upmix = true + #channelmix.filter-lfe = false }