channelmix: Prepare for generating LFE channel

Add channelmix.lfe-cutoff property, 0 is disabled
Disable upmix by default
This commit is contained in:
Wim Taymans 2021-03-17 11:09:19 +01:00
parent 4200ca98d6
commit e51cc5b537
7 changed files with 27 additions and 20 deletions

View file

@ -238,6 +238,7 @@ 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];
const float v2 = (mix->matrix[2][0] + mix->matrix[2][1]) * 0.5f; const float v2 = (mix->matrix[2][0] + mix->matrix[2][1]) * 0.5f;
const float v3 = (mix->matrix[3][0] + mix->matrix[3][1]) * 0.5f;
if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_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++)
@ -245,18 +246,20 @@ channelmix_f32_2_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI
} }
else if (v0 == 1.0f && v1 == 1.0f) { else if (v0 == 1.0f && v1 == 1.0f) {
for (n = 0; n < n_samples; n++) { for (n = 0; n < n_samples; n++) {
float c = s[0][n] + s[1][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];
d[2][n] = (s[0][n] + s[1][n]) * v2; d[2][n] = c * v2;
d[3][n] = 0.0f; d[3][n] = c * v3;
} }
} }
else { else {
for (n = 0; n < n_samples; n++) { for (n = 0; n < n_samples; n++) {
float c = s[0][n] + s[1][n];
d[0][n] = s[0][n] * v0; d[0][n] = s[0][n] * v0;
d[1][n] = s[1][n] * v1; d[1][n] = s[1][n] * v1;
d[2][n] = (d[0][n] + d[1][n]) * v2; d[2][n] = c * v2;
d[3][n] = 0.0f; d[3][n] = c * v3;
} }
} }
} }
@ -272,6 +275,7 @@ channelmix_f32_2_5p1_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];
const float v2 = (mix->matrix[2][0] + mix->matrix[2][1]) * 0.5f; const float v2 = (mix->matrix[2][0] + mix->matrix[2][1]) * 0.5f;
const float v3 = (mix->matrix[3][0] + mix->matrix[3][1]) * 0.5f;
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];
@ -281,18 +285,20 @@ channelmix_f32_2_5p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRI
} }
else if (v0 == 1.0f && v1 == 1.0f && v4 == 1.0f && v5 == 1.0f) { 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++) {
float c = s[0][n] + s[1][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];
d[2][n] = (s[0][n] + s[1][n]) * v2; d[2][n] = c * v2;
d[3][n] = 0.0f; d[3][n] = c * v3;
} }
} }
else { else {
for (n = 0; n < n_samples; n++) { for (n = 0; n < n_samples; n++) {
float c = s[0][n] + s[1][n];
d[0][n] = s[0][n] * v0; d[0][n] = s[0][n] * v0;
d[1][n] = s[1][n] * v1; d[1][n] = s[1][n] * v1;
d[2][n] = (d[0][n] + d[1][n]) * v2; d[2][n] = c * v2;
d[3][n] = 0.0f; d[3][n] = c * v3;
d[4][n] = s[0][n] * v4; d[4][n] = s[0][n] * v4;
d[5][n] = s[1][n] * v5; d[5][n] = s[1][n] * v5;
} }

View file

@ -385,8 +385,7 @@ static int make_matrix(struct channelmix *mix)
spa_log_warn(mix->log, "can't produce FC"); spa_log_warn(mix->log, "can't produce FC");
} }
} }
if (unassigned & _MASK(LFE) && if (unassigned & _MASK(LFE) && mix->lfe_cutoff > 0.0f) {
SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_FILTER_LFE)) {
if ((src_mask & STEREO) == STEREO) { if ((src_mask & STEREO) == STEREO) {
spa_log_debug(mix->log, "produce LFE from STEREO"); spa_log_debug(mix->log, "produce LFE from STEREO");
matrix[LFE][FL] += llev; matrix[LFE][FL] += llev;

View file

@ -49,7 +49,6 @@ struct channelmix {
#define CHANNELMIX_OPTION_MIX_LFE (1<<0) /**< mix LFE */ #define CHANNELMIX_OPTION_MIX_LFE (1<<0) /**< mix LFE */
#define CHANNELMIX_OPTION_NORMALIZE (1<<1) /**< normalize volumes */ #define CHANNELMIX_OPTION_NORMALIZE (1<<1) /**< normalize volumes */
#define CHANNELMIX_OPTION_UPMIX (1<<2) /**< do simple upmixing */ #define CHANNELMIX_OPTION_UPMIX (1<<2) /**< do simple upmixing */
#define CHANNELMIX_OPTION_FILTER_LFE (1<<3) /**< generate and filter LFE */
uint32_t options; uint32_t options;
struct spa_log *log; struct spa_log *log;
@ -62,6 +61,9 @@ struct channelmix {
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];
float freq; /* sample frequency */
float lfe_cutoff; /* in Hz, 0 is disabled */
void (*process) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], void (*process) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst],
uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples); uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples);
void (*set_volume) (struct channelmix *mix, float volume, bool mute, void (*set_volume) (struct channelmix *mix, float volume, bool mute,

View file

@ -303,6 +303,7 @@ static int setup_convert(struct impl *this,
this->mix.dst_mask = dst_mask; this->mix.dst_mask = dst_mask;
this->mix.cpu_flags = this->cpu_flags; this->mix.cpu_flags = this->cpu_flags;
this->mix.log = this->log; this->mix.log = this->log;
this->mix.freq = src_info->info.raw.rate;
if ((res = channelmix_init(&this->mix)) < 0) if ((res = channelmix_init(&this->mix)) < 0)
return res; return res;
@ -1273,9 +1274,8 @@ impl_init(const struct spa_handle_factory *factory,
if ((str = spa_dict_lookup(info, "channelmix.upmix")) != NULL && if ((str = spa_dict_lookup(info, "channelmix.upmix")) != NULL &&
(strcmp(str, "true") == 0 || atoi(str) != 0)) (strcmp(str, "true") == 0 || atoi(str) != 0))
this->mix.options |= CHANNELMIX_OPTION_UPMIX; this->mix.options |= CHANNELMIX_OPTION_UPMIX;
if ((str = spa_dict_lookup(info, "channelmix.filter-lfe")) != NULL && if ((str = spa_dict_lookup(info, "channelmix.lfe-cutoff")) != NULL)
(strcmp(str, "true") == 0 || atoi(str) != 0)) this->mix.lfe_cutoff = atoi(str);
this->mix.options |= CHANNELMIX_OPTION_FILTER_LFE;
if ((str = spa_dict_lookup(info, SPA_KEY_AUDIO_POSITION)) != NULL) { if ((str = spa_dict_lookup(info, SPA_KEY_AUDIO_POSITION)) != NULL) {
size_t len; size_t len;
const char *p = str; const char *p = str;

View file

@ -73,6 +73,6 @@ stream.properties = {
#resample.quality = 4 #resample.quality = 4
#channelmix.normalize = false #channelmix.normalize = false
#channelmix.mix-lfe = true #channelmix.mix-lfe = true
channelmix.upmix = true #channelmix.upmix = false
#channelmix.filter-lfe = false #channelmix.lfe-cutoff = 0
} }

View file

@ -62,6 +62,6 @@ stream.properties = {
#resample.quality = 4 #resample.quality = 4
#channelmix.normalize = false #channelmix.normalize = false
#channelmix.mix-lfe = false #channelmix.mix-lfe = false
channelmix.upmix = true #channelmix.upmix = false
#channelmix.filter-lfe = false #channelmix.lfe-cutoff = 0
} }

View file

@ -49,6 +49,6 @@ stream.properties = {
#resample.quality = 4 #resample.quality = 4
#channelmix.normalize = false #channelmix.normalize = false
#channelmix.mix-lfe = false #channelmix.mix-lfe = false
channelmix.upmix = true #channelmix.upmix = false
#channelmix.filter-lfe = false #channelmix.lfe-cutoff = 0
} }