diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/pulsecore/resampler.c | 96 | 
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];                      }                  }              }  | 
