channelmix: apply channel volumes correctly

This commit is contained in:
Wim Taymans 2019-08-14 14:56:16 +02:00
parent 449d98910b
commit 87ae7a8011
5 changed files with 270 additions and 253 deletions

View file

@ -162,7 +162,7 @@ static int make_matrix(struct channelmix *mix)
uint64_t src_mask = mix->src_mask;
uint64_t dst_mask = mix->dst_mask;
uint64_t unassigned;
uint32_t i, j, matrix_encoding = MATRIX_NORMAL, c;
uint32_t i, j, ic, jc, matrix_encoding = MATRIX_NORMAL;
float clev = SQRT1_2;
float slev = SQRT1_2;
float llev = 0.5f;
@ -325,17 +325,17 @@ static int make_matrix(struct channelmix *mix)
}
}
c = 0;
for (i = 0; i < NUM_CHAN; i++) {
for (ic = 0, i = 0; i < NUM_CHAN; i++) {
float sum = 0.0f;
if ((dst_mask & (1UL << (i + 2))) == 0)
continue;
for (j = 0; j < NUM_CHAN; j++) {
for (jc = 0, j = 0; j < NUM_CHAN; j++) {
if ((src_mask & (1UL << (j + 2))) == 0)
continue;
mix->matrix_orig[c++] = matrix[i][j];
mix->matrix_orig[ic][jc++] = matrix[i][j];
sum += fabs(matrix[i][j]);
}
ic++;
max = SPA_MAX(max, sum);
}
return 0;
@ -345,46 +345,56 @@ static void impl_channelmix_set_volume(struct channelmix *mix, float volume, boo
uint32_t n_channel_volumes, float *channel_volumes)
{
float volumes[SPA_AUDIO_MAX_CHANNELS];
float vol = mute ? 0.0f : volume, sum;
float vol = mute ? 0.0f : volume, sum, t;
uint32_t i, j;
uint32_t src_chan = mix->src_chan;
uint32_t dst_chan = mix->dst_chan;
/** apply global volume to channels */
sum = 0.0;
mix->norm = true;
for (i = 0; i < n_channel_volumes; i++) {
volumes[i] = channel_volumes[i] * vol;
if (volumes[i] != 1.0f)
mix->norm = false;
sum += volumes[i];
}
mix->volume = sum / n_channel_volumes;
if (n_channel_volumes == src_chan) {
for (i = 0; i < dst_chan; i++) {
for (j = 0; j < src_chan; j++) {
float v = mix->matrix_orig[i * src_chan + j];
mix->matrix[i * src_chan + j] = v * volumes[j];
mix->matrix[i][j] = mix->matrix_orig[i][j] * volumes[j];
}
}
} else if (n_channel_volumes == dst_chan) {
for (i = 0; i < dst_chan; i++) {
for (j = 0; j < src_chan; j++) {
float v = mix->matrix_orig[i * src_chan + j];
mix->matrix[i * src_chan + j] = v * volumes[i];
mix->matrix[i][j] = mix->matrix_orig[i][j] * volumes[i];
}
}
}
mix->is_identity = dst_chan == src_chan;
mix->zero = true;
mix->equal = true;
mix->identity = dst_chan == src_chan;
t = 0.0;
for (i = 0; i < dst_chan; i++) {
for (j = 0; j < src_chan; j++) {
float v = mix->matrix[i * src_chan + j];
float v = mix->matrix[i][j];
spa_log_debug(mix->log, "%d %d: %f", i, j, v);
if (i == 0 && j == 0)
t = v;
else if (t != v)
mix->equal = false;
if (v != 0.0)
mix->zero = false;
if ((i == j && v != 1.0f) ||
(i != j && v != 0.0f))
mix->is_identity = false;
mix->identity = false;
}
}
spa_log_debug(mix->log, "vol:%f, identity:%d", mix->volume, mix->is_identity);
spa_log_debug(mix->log, "zero:%d norm:%d identity:%d", mix->zero, mix->norm, mix->identity);
}
static void impl_channelmix_free(struct channelmix *mix)