summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2008-12-17 19:53:58 +0100
committerLennart Poettering <lennart@poettering.net>2009-01-12 20:23:28 +0100
commita66d2ed7d19a6ad8ba12e3a74df4b765937e9445 (patch)
tree34526bd1dad5fd8457caa0aeddd20881d0b1f5ea /src
parentd72b6eb7de07c98aecd1fe316fae4a35c6dd0df8 (diff)
Don't mix front-center into rear channels
If there's a center channel on input that is not available on output make sure we mix front-center only into front-left/right and rear-center into rear-left/right. Closes #400
Diffstat (limited to 'src')
-rw-r--r--src/pulsecore/resampler.c96
1 files changed, 93 insertions, 3 deletions
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index b2d512c8..f0515ebe 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -510,6 +510,52 @@ static pa_bool_t on_lfe(pa_channel_position_t p) {
p == PA_CHANNEL_POSITION_LFE;
}
+static pa_bool_t on_front(pa_channel_position_t p) {
+ return
+ p == PA_CHANNEL_POSITION_FRONT_LEFT ||
+ p == PA_CHANNEL_POSITION_FRONT_RIGHT ||
+ p == PA_CHANNEL_POSITION_FRONT_CENTER ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ||
+ p == PA_CHANNEL_POSITION_TOP_FRONT_CENTER ||
+ p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ||
+ p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
+}
+
+static pa_bool_t on_rear(pa_channel_position_t p) {
+ return
+ p == PA_CHANNEL_POSITION_REAR_LEFT ||
+ p == PA_CHANNEL_POSITION_REAR_RIGHT ||
+ p == PA_CHANNEL_POSITION_REAR_CENTER ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_LEFT ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT ||
+ p == PA_CHANNEL_POSITION_TOP_REAR_CENTER;
+}
+
+static pa_bool_t on_side(pa_channel_position_t p) {
+ return
+ p == PA_CHANNEL_POSITION_SIDE_LEFT ||
+ p == PA_CHANNEL_POSITION_SIDE_RIGHT ||
+ p == PA_CHANNEL_POSITION_TOP_CENTER;
+}
+
+enum {
+ ON_FRONT,
+ ON_REAR,
+ ON_SIDE,
+ ON_OTHER
+};
+
+static int front_rear_side(pa_channel_position_t p) {
+ if (on_front(p))
+ return ON_FRONT;
+ if (on_rear(p))
+ return ON_REAR;
+ if (on_side(p))
+ return ON_SIDE;
+ return ON_OTHER;
+}
+
static void calc_map_table(pa_resampler *r) {
unsigned oc, ic;
pa_bool_t ic_connected[PA_CHANNELS_MAX];
@@ -601,7 +647,9 @@ static void calc_map_table(pa_resampler *r) {
* D:left, all D:right, all D:center channels, gain is
* 0.375. The current (as result of 1..6) factors
* should be multiplied by 0.75. (Alt. suggestion: 0.25
- * vs. 0.5)
+ * vs. 0.5) If C-front is only mixed into
+ * L-front/R-front if available, otherwise into all L/R
+ * channels. Similarly for C-rear.
*
* S: and D: shall relate to the source resp. destination channels.
*
@@ -629,6 +677,8 @@ static void calc_map_table(pa_resampler *r) {
if (!oc_connected && remix) {
/* OK, we shall remix */
+ /* Try to find matching input ports for this output port */
+
if (on_left(b)) {
unsigned n = 0;
@@ -830,17 +880,54 @@ static void calc_map_table(pa_resampler *r) {
}
if (!mixed_in) {
+ unsigned ncenter[PA_CHANNELS_MAX];
+ pa_bool_t found_frs[PA_CHANNELS_MAX];
+
+ memset(ncenter, 0, sizeof(ncenter));
+ memset(found_frs, 0, sizeof(found_frs));
/* Hmm, as it appears there was no center channel we
could mix our center channel in. In this case, mix
it into left and right. Using .375 and 0.75 as
factors. */
+ for (ic = 0; ic < r->i_ss.channels; ic++) {
+
+ if (ic_connected[ic])
+ continue;
+
+ if (!on_center(r->i_cm.map[ic]))
+ continue;
+
+ for (oc = 0; oc < r->o_ss.channels; oc++) {
+
+ if (!on_left(r->o_cm.map[oc]) && !on_right(r->o_cm.map[oc]))
+ continue;
+
+ if (front_rear_side(r->i_cm.map[ic]) == front_rear_side(r->o_cm.map[oc])) {
+ found_frs[ic] = TRUE;
+ break;
+ }
+ }
+
+ for (oc = 0; oc < r->o_ss.channels; oc++) {
+
+ if (!on_left(r->o_cm.map[oc]) && !on_right(r->o_cm.map[oc]))
+ continue;
+
+ if (!found_frs[ic] || front_rear_side(r->i_cm.map[ic]) == front_rear_side(r->o_cm.map[oc]))
+ ncenter[oc]++;
+ }
+ }
+
for (oc = 0; oc < r->o_ss.channels; oc++) {
if (!on_left(r->o_cm.map[oc]) && !on_right(r->o_cm.map[oc]))
continue;
+ if (ncenter[oc] <= 0)
+ continue;
+
for (ic = 0; ic < r->i_ss.channels; ic++) {
if (ic_connected[ic]) {
@@ -848,8 +935,11 @@ static void calc_map_table(pa_resampler *r) {
continue;
}
- if (on_center(r->i_cm.map[ic]))
- r->map_table[oc][ic] = .375f / (float) ic_unconnected_center;
+ if (!on_center(r->i_cm.map[ic]))
+ continue;
+
+ if (!found_frs[ic] || front_rear_side(r->i_cm.map[ic]) == front_rear_side(r->o_cm.map[oc]))
+ r->map_table[oc][ic] = .375f / (float) ncenter[oc];
}
}
}