mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-04-14 08:21:47 -04:00
channelmix: make up/downmix levels configurable
Add channelmix.center-level, channelmix.surround-level and channelmix.lfe-level to control how center, surround and LFE is up/downmixed. Fixes #5198
This commit is contained in:
parent
03f894bab0
commit
18c97222c4
12 changed files with 119 additions and 25 deletions
|
|
@ -80,6 +80,9 @@ stream.properties = {
|
||||||
#channelmix.fc-cutoff = 12000.0
|
#channelmix.fc-cutoff = 12000.0
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
|
#channelmix.center-level = 0.707106781
|
||||||
|
#channelmix.surround-level = 0.707106781
|
||||||
|
#channelmix.lfe-level = 0.5
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
#dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5
|
#dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5
|
||||||
|
|
|
||||||
|
|
@ -783,6 +783,15 @@ more to the center speaker and leaves the ambient sound in the stereo channels.
|
||||||
This is only active when up-mix is enabled and a Front Center channel is mixed.
|
This is only active when up-mix is enabled and a Front Center channel is mixed.
|
||||||
\endparblock
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop channelmix.center-level = 0.707106781
|
||||||
|
The level of the center channel when up/downmixing.
|
||||||
|
|
||||||
|
@PAR@ node-prop channelmix.surround-level = 0.707106781
|
||||||
|
The level of the surround channels when up/downmixing.
|
||||||
|
|
||||||
|
@PAR@ node-prop channelmix.lfe-level = 0.5
|
||||||
|
The level of the LFE channel when up/downmixing.
|
||||||
|
|
||||||
@PAR@ node-prop channelmix.hilbert-taps = 0
|
@PAR@ node-prop channelmix.hilbert-taps = 0
|
||||||
\parblock
|
\parblock
|
||||||
This option will apply a 90 degree phase shift to the rear channels to improve specialization.
|
This option will apply a 90 degree phase shift to the rear channels to improve specialization.
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,9 @@ stream.properties = {
|
||||||
#channelmix.fc-cutoff = 12000.0
|
#channelmix.fc-cutoff = 12000.0
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
|
#channelmix.center-level = 0.707106781
|
||||||
|
#channelmix.surround-level = 0.707106781
|
||||||
|
#channelmix.lfe-level = 0.5
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
#dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5
|
#dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5
|
||||||
|
|
|
||||||
|
|
@ -724,6 +724,34 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 19:
|
case 19:
|
||||||
|
*param = spa_pod_builder_add_object(b,
|
||||||
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.center-level"),
|
||||||
|
SPA_PROP_INFO_description, SPA_POD_String("Center up/downmix level"),
|
||||||
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
|
||||||
|
this->mix.center_level, 0.0, 10.0),
|
||||||
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
*param = spa_pod_builder_add_object(b,
|
||||||
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.surround-level"),
|
||||||
|
SPA_PROP_INFO_description, SPA_POD_String("Surround up/downmix level"),
|
||||||
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
|
||||||
|
this->mix.surround_level, 0.0, 10.0),
|
||||||
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
*param = spa_pod_builder_add_object(b,
|
||||||
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.lfe-level"),
|
||||||
|
SPA_PROP_INFO_description, SPA_POD_String("LFE up/downmix level"),
|
||||||
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
|
||||||
|
this->mix.lfe_level, 0.0, 10.0),
|
||||||
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 22:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("channelmix.hilbert-taps"),
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.hilbert-taps"),
|
||||||
|
|
@ -732,7 +760,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
this->mix.hilbert_taps, 0, MAX_TAPS),
|
this->mix.hilbert_taps, 0, MAX_TAPS),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 20:
|
case 23:
|
||||||
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
||||||
spa_pod_builder_add(b,
|
spa_pod_builder_add(b,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("channelmix.upmix-method"),
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.upmix-method"),
|
||||||
|
|
@ -751,14 +779,14 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
spa_pod_builder_pop(b, &f[1]);
|
spa_pod_builder_pop(b, &f[1]);
|
||||||
*param = spa_pod_builder_pop(b, &f[0]);
|
*param = spa_pod_builder_pop(b, &f[0]);
|
||||||
break;
|
break;
|
||||||
case 21:
|
case 24:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_rate),
|
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_rate),
|
||||||
SPA_PROP_INFO_description, SPA_POD_String("Rate scaler"),
|
SPA_PROP_INFO_description, SPA_POD_String("Rate scaler"),
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Double(p->rate, 0.0, 10.0));
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Double(p->rate, 0.0, 10.0));
|
||||||
break;
|
break;
|
||||||
case 22:
|
case 25:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_quality),
|
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_quality),
|
||||||
|
|
@ -767,7 +795,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->resample_quality, 0, 14),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->resample_quality, 0, 14),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 23:
|
case 26:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("resample.disable"),
|
SPA_PROP_INFO_name, SPA_POD_String("resample.disable"),
|
||||||
|
|
@ -775,7 +803,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->resample_disabled),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->resample_disabled),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 27:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("dither.noise"),
|
SPA_PROP_INFO_name, SPA_POD_String("dither.noise"),
|
||||||
|
|
@ -783,7 +811,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(this->dir[1].conv.noise_bits, 0, 16),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(this->dir[1].conv.noise_bits, 0, 16),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 25:
|
case 28:
|
||||||
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
||||||
spa_pod_builder_add(b,
|
spa_pod_builder_add(b,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("dither.method"),
|
SPA_PROP_INFO_name, SPA_POD_String("dither.method"),
|
||||||
|
|
@ -801,7 +829,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
spa_pod_builder_pop(b, &f[1]);
|
spa_pod_builder_pop(b, &f[1]);
|
||||||
*param = spa_pod_builder_pop(b, &f[0]);
|
*param = spa_pod_builder_pop(b, &f[0]);
|
||||||
break;
|
break;
|
||||||
case 26:
|
case 29:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("debug.wav-path"),
|
SPA_PROP_INFO_name, SPA_POD_String("debug.wav-path"),
|
||||||
|
|
@ -809,7 +837,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_String(p->wav_path),
|
SPA_PROP_INFO_type, SPA_POD_String(p->wav_path),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 27:
|
case 30:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("channelmix.lock-volumes"),
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.lock-volumes"),
|
||||||
|
|
@ -817,7 +845,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->lock_volumes),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->lock_volumes),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 28:
|
case 31:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("audioconvert.filter-graph.disable"),
|
SPA_PROP_INFO_name, SPA_POD_String("audioconvert.filter-graph.disable"),
|
||||||
|
|
@ -825,7 +853,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->filter_graph_disabled),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->filter_graph_disabled),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 29:
|
case 32:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("audioconvert.filter-graph.N"),
|
SPA_PROP_INFO_name, SPA_POD_String("audioconvert.filter-graph.N"),
|
||||||
|
|
@ -836,7 +864,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
default:
|
default:
|
||||||
if (this->filter_graph[0] && this->filter_graph[0]->graph) {
|
if (this->filter_graph[0] && this->filter_graph[0]->graph) {
|
||||||
return spa_filter_graph_enum_prop_info(this->filter_graph[0]->graph,
|
return spa_filter_graph_enum_prop_info(this->filter_graph[0]->graph,
|
||||||
index - 30, b, param);
|
index - 33, b, param);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -903,6 +931,12 @@ static int node_param_props(struct impl *this, uint32_t id, uint32_t index,
|
||||||
spa_pod_builder_float(b, this->mix.rear_delay);
|
spa_pod_builder_float(b, this->mix.rear_delay);
|
||||||
spa_pod_builder_string(b, "channelmix.stereo-widen");
|
spa_pod_builder_string(b, "channelmix.stereo-widen");
|
||||||
spa_pod_builder_float(b, this->mix.widen);
|
spa_pod_builder_float(b, this->mix.widen);
|
||||||
|
spa_pod_builder_string(b, "channelmix.center-level");
|
||||||
|
spa_pod_builder_float(b, this->mix.center_level);
|
||||||
|
spa_pod_builder_string(b, "channelmix.surround-level");
|
||||||
|
spa_pod_builder_float(b, this->mix.surround_level);
|
||||||
|
spa_pod_builder_string(b, "channelmix.lfe-level");
|
||||||
|
spa_pod_builder_float(b, this->mix.lfe_level);
|
||||||
spa_pod_builder_string(b, "channelmix.hilbert-taps");
|
spa_pod_builder_string(b, "channelmix.hilbert-taps");
|
||||||
spa_pod_builder_int(b, this->mix.hilbert_taps);
|
spa_pod_builder_int(b, this->mix.hilbert_taps);
|
||||||
spa_pod_builder_string(b, "channelmix.upmix-method");
|
spa_pod_builder_string(b, "channelmix.upmix-method");
|
||||||
|
|
@ -1490,6 +1524,12 @@ static int audioconvert_set_param(struct impl *this, const char *k, const char *
|
||||||
spa_atof(s, &this->mix.rear_delay);
|
spa_atof(s, &this->mix.rear_delay);
|
||||||
else if (spa_streq(k, "channelmix.stereo-widen"))
|
else if (spa_streq(k, "channelmix.stereo-widen"))
|
||||||
spa_atof(s, &this->mix.widen);
|
spa_atof(s, &this->mix.widen);
|
||||||
|
else if (spa_streq(k, "channelmix.center-level"))
|
||||||
|
spa_atof(s, &this->mix.center_level);
|
||||||
|
else if (spa_streq(k, "channelmix.surround-level"))
|
||||||
|
spa_atof(s, &this->mix.surround_level);
|
||||||
|
else if (spa_streq(k, "channelmix.lfe-level"))
|
||||||
|
spa_atof(s, &this->mix.lfe_level);
|
||||||
else if (spa_streq(k, "channelmix.hilbert-taps"))
|
else if (spa_streq(k, "channelmix.hilbert-taps"))
|
||||||
spa_atou32(s, &this->mix.hilbert_taps, 0);
|
spa_atou32(s, &this->mix.hilbert_taps, 0);
|
||||||
else if (spa_streq(k, "channelmix.upmix-method"))
|
else if (spa_streq(k, "channelmix.upmix-method"))
|
||||||
|
|
@ -4320,13 +4360,7 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
this->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
|
this->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
|
||||||
this->rate_limit.burst = 1;
|
this->rate_limit.burst = 1;
|
||||||
|
|
||||||
this->mix.options = CHANNELMIX_OPTION_UPMIX | CHANNELMIX_OPTION_MIX_LFE;
|
channelmix_reset(&this->mix);
|
||||||
this->mix.upmix = CHANNELMIX_UPMIX_NONE;
|
|
||||||
this->mix.log = this->log;
|
|
||||||
this->mix.lfe_cutoff = 0.0f;
|
|
||||||
this->mix.fc_cutoff = 0.0f;
|
|
||||||
this->mix.rear_delay = 0.0f;
|
|
||||||
this->mix.widen = 0.0f;
|
|
||||||
|
|
||||||
for (i = 0; info && i < info->n_items; i++) {
|
for (i = 0; info && i < info->n_items; i++) {
|
||||||
const char *k = info->items[i].key;
|
const char *k = info->items[i].key;
|
||||||
|
|
|
||||||
|
|
@ -198,9 +198,9 @@ static int make_matrix(struct channelmix *mix)
|
||||||
uint32_t dst_chan = mix->dst_chan;
|
uint32_t dst_chan = mix->dst_chan;
|
||||||
uint64_t unassigned, keep;
|
uint64_t unassigned, keep;
|
||||||
uint32_t i, j, ic, jc, matrix_encoding = MATRIX_NORMAL;
|
uint32_t i, j, ic, jc, matrix_encoding = MATRIX_NORMAL;
|
||||||
float clev = SQRT1_2;
|
float clev = mix->center_level;
|
||||||
float slev = SQRT1_2;
|
float slev = mix->surround_level;
|
||||||
float llev = 0.5f;
|
float llev = mix->lfe_level;
|
||||||
float maxsum = 0.0f;
|
float maxsum = 0.0f;
|
||||||
bool filter_fc = false, filter_lfe = false, matched = false, normalize;
|
bool filter_fc = false, filter_lfe = false, matched = false, normalize;
|
||||||
#define _MATRIX(s,d) matrix[_CH(s)][_CH(d)]
|
#define _MATRIX(s,d) matrix[_CH(s)][_CH(d)]
|
||||||
|
|
@ -874,6 +874,21 @@ static void impl_channelmix_free(struct channelmix *mix)
|
||||||
mix->process = NULL;
|
mix->process = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void channelmix_reset(struct channelmix *mix)
|
||||||
|
{
|
||||||
|
spa_zero(*mix);
|
||||||
|
mix->options = CHANNELMIX_DEFAULT_OPTIONS;
|
||||||
|
mix->upmix = CHANNELMIX_DEFAULT_UPMIX;
|
||||||
|
mix->lfe_cutoff = CHANNELMIX_DEFAULT_LFE_CUTOFF;
|
||||||
|
mix->fc_cutoff = CHANNELMIX_DEFAULT_FC_CUTOFF;
|
||||||
|
mix->rear_delay = CHANNELMIX_DEFAULT_REAR_DELAY;
|
||||||
|
mix->center_level = CHANNELMIX_DEFAULT_CENTER_LEVEL;
|
||||||
|
mix->surround_level = CHANNELMIX_DEFAULT_SURROUND_LEVEL;
|
||||||
|
mix->lfe_level = CHANNELMIX_DEFAULT_LFE_LEVEL;
|
||||||
|
mix->widen = CHANNELMIX_DEFAULT_WIDEN;
|
||||||
|
mix->hilbert_taps = CHANNELMIX_DEFAULT_HILBERT_TAPS;
|
||||||
|
}
|
||||||
|
|
||||||
int channelmix_init(struct channelmix *mix)
|
int channelmix_init(struct channelmix *mix)
|
||||||
{
|
{
|
||||||
const struct channelmix_info *info;
|
const struct channelmix_info *info;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,17 @@
|
||||||
|
|
||||||
#define CHANNELMIX_OPS_MAX_ALIGN 16
|
#define CHANNELMIX_OPS_MAX_ALIGN 16
|
||||||
|
|
||||||
|
#define CHANNELMIX_DEFAULT_OPTIONS (CHANNELMIX_OPTION_UPMIX | CHANNELMIX_OPTION_MIX_LFE)
|
||||||
|
#define CHANNELMIX_DEFAULT_UPMIX CHANNELMIX_UPMIX_NONE
|
||||||
|
#define CHANNELMIX_DEFAULT_LFE_CUTOFF 0.0f
|
||||||
|
#define CHANNELMIX_DEFAULT_FC_CUTOFF 0.0f
|
||||||
|
#define CHANNELMIX_DEFAULT_REAR_DELAY 0.0f
|
||||||
|
#define CHANNELMIX_DEFAULT_CENTER_LEVEL 0.707106781f
|
||||||
|
#define CHANNELMIX_DEFAULT_SURROUND_LEVEL 0.707106781f
|
||||||
|
#define CHANNELMIX_DEFAULT_LFE_LEVEL 0.5f
|
||||||
|
#define CHANNELMIX_DEFAULT_WIDEN 0.0f
|
||||||
|
#define CHANNELMIX_DEFAULT_HILBERT_TAPS 0
|
||||||
|
|
||||||
struct channelmix {
|
struct channelmix {
|
||||||
uint32_t src_chan;
|
uint32_t src_chan;
|
||||||
uint32_t dst_chan;
|
uint32_t dst_chan;
|
||||||
|
|
@ -60,6 +71,9 @@ struct channelmix {
|
||||||
float fc_cutoff; /* in Hz, 0 is disabled */
|
float fc_cutoff; /* in Hz, 0 is disabled */
|
||||||
float rear_delay; /* in ms, 0 is disabled */
|
float rear_delay; /* in ms, 0 is disabled */
|
||||||
float widen; /* stereo widen. 0 is disabled */
|
float widen; /* stereo widen. 0 is disabled */
|
||||||
|
float center_level; /* center down/upmix level, sqrt(1/2) */
|
||||||
|
float lfe_level; /* lfe down/upmix level, 1/2 */
|
||||||
|
float surround_level; /* surround down/upmix level, sqrt(1/2) */
|
||||||
uint32_t hilbert_taps; /* to phase shift, 0 disabled */
|
uint32_t hilbert_taps; /* to phase shift, 0 disabled */
|
||||||
struct lr4 lr4[MAX_CHANNELS];
|
struct lr4 lr4[MAX_CHANNELS];
|
||||||
|
|
||||||
|
|
@ -80,6 +94,7 @@ struct channelmix {
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void channelmix_reset(struct channelmix *mix);
|
||||||
int channelmix_init(struct channelmix *mix);
|
int channelmix_init(struct channelmix *mix);
|
||||||
|
|
||||||
static const struct channelmix_upmix_info {
|
static const struct channelmix_upmix_info {
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ static int setup_context(struct context *ctx)
|
||||||
size_t size;
|
size_t size;
|
||||||
int res;
|
int res;
|
||||||
struct spa_support support[1];
|
struct spa_support support[1];
|
||||||
struct spa_dict_item items[6];
|
struct spa_dict_item items[9];
|
||||||
const struct spa_handle_factory *factory;
|
const struct spa_handle_factory *factory;
|
||||||
void *iface;
|
void *iface;
|
||||||
|
|
||||||
|
|
@ -76,10 +76,13 @@ static int setup_context(struct context *ctx)
|
||||||
items[3] = SPA_DICT_ITEM_INIT("channelmix.lfe-cutoff", "150");
|
items[3] = SPA_DICT_ITEM_INIT("channelmix.lfe-cutoff", "150");
|
||||||
items[4] = SPA_DICT_ITEM_INIT("channelmix.fc-cutoff", "12000");
|
items[4] = SPA_DICT_ITEM_INIT("channelmix.fc-cutoff", "12000");
|
||||||
items[5] = SPA_DICT_ITEM_INIT("channelmix.rear-delay", "12.0");
|
items[5] = SPA_DICT_ITEM_INIT("channelmix.rear-delay", "12.0");
|
||||||
|
items[6] = SPA_DICT_ITEM_INIT("channelmix.center-level", "0.707106781");
|
||||||
|
items[7] = SPA_DICT_ITEM_INIT("channelmix.surround-level", "0.707106781");
|
||||||
|
items[8] = SPA_DICT_ITEM_INIT("channelmix.lfe-level", "0.5");
|
||||||
|
|
||||||
res = spa_handle_factory_init(factory,
|
res = spa_handle_factory_init(factory,
|
||||||
ctx->convert_handle,
|
ctx->convert_handle,
|
||||||
&SPA_DICT_INIT(items, 6),
|
&SPA_DICT_INIT(items, 9),
|
||||||
support, 1);
|
support, 1);
|
||||||
spa_assert_se(res >= 0);
|
spa_assert_se(res >= 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ static void test_mix(uint32_t src_chan, uint32_t src_mask, uint32_t dst_chan, ui
|
||||||
|
|
||||||
spa_log_debug(&logger.log, "start %d->%d (%08x -> %08x)", src_chan, dst_chan, src_mask, dst_mask);
|
spa_log_debug(&logger.log, "start %d->%d (%08x -> %08x)", src_chan, dst_chan, src_mask, dst_mask);
|
||||||
|
|
||||||
spa_zero(mix);
|
channelmix_reset(&mix);
|
||||||
mix.options = options;
|
mix.options = options;
|
||||||
mix.src_chan = src_chan;
|
mix.src_chan = src_chan;
|
||||||
mix.dst_chan = dst_chan;
|
mix.dst_chan = dst_chan;
|
||||||
|
|
@ -340,7 +340,7 @@ static void test_n_m_impl(void)
|
||||||
src[i] = src_data[i];
|
src[i] = src_data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_zero(mix);
|
channelmix_reset(&mix);
|
||||||
mix.src_chan = 16;
|
mix.src_chan = 16;
|
||||||
mix.dst_chan = 12;
|
mix.dst_chan = 12;
|
||||||
mix.log = &logger.log;
|
mix.log = &logger.log;
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,9 @@ stream.properties = {
|
||||||
#channelmix.lfe-cutoff = 150
|
#channelmix.lfe-cutoff = 150
|
||||||
#channelmix.fc-cutoff = 12000
|
#channelmix.fc-cutoff = 12000
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
|
#channelmix.center-level = 0.707106781
|
||||||
|
#channelmix.surround-level = 0.707106781
|
||||||
|
#channelmix.lfe-level = 0.5
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,9 @@ context.objects = [
|
||||||
#channelmix.fc-cutoff = 12000
|
#channelmix.fc-cutoff = 12000
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
|
#channelmix.center-level = 0.707106781
|
||||||
|
#channelmix.surround-level = 0.707106781
|
||||||
|
#channelmix.lfe-level = 0.5
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
#channelmix.disable = false
|
#channelmix.disable = false
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@ stream.properties = {
|
||||||
#channelmix.fc-cutoff = 6000
|
#channelmix.fc-cutoff = 6000
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.1
|
#channelmix.stereo-widen = 0.1
|
||||||
|
#channelmix.center-level = 0.707106781
|
||||||
|
#channelmix.surround-level = 0.707106781
|
||||||
|
#channelmix.lfe-level = 0.5
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,9 @@ stream.properties = {
|
||||||
#channelmix.fc-cutoff = 12000
|
#channelmix.fc-cutoff = 12000
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
|
#channelmix.center-level = 0.707106781
|
||||||
|
#channelmix.surround-level = 0.707106781
|
||||||
|
#channelmix.lfe-level = 0.5
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue