diff options
| author | Lennart Poettering <lennart@poettering.net> | 2009-05-25 23:55:44 +0200 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2009-05-25 23:55:44 +0200 | 
| commit | 8b180b6368b64c53d0da03682b5bfa8c7e6e6536 (patch) | |
| tree | e4ed2e5a10cc5644f3196b21de0ce5672605ff9b | |
| parent | 5f2d848d8e6958f8e83d4ef5100ef9597ff75011 (diff) | |
volume: implement pa_cvolume_{scale|max|avg}_mask()
| -rw-r--r-- | src/map-file | 3 | ||||
| -rw-r--r-- | src/pulse/volume.c | 87 | ||||
| -rw-r--r-- | src/pulse/volume.h | 22 | 
3 files changed, 101 insertions, 11 deletions
diff --git a/src/map-file b/src/map-file index 5cae6d33..c46c6792 100644 --- a/src/map-file +++ b/src/map-file @@ -112,6 +112,7 @@ pa_context_suspend_source_by_name;  pa_context_unload_module;  pa_context_unref;  pa_cvolume_avg; +pa_cvolume_avg_mask;  pa_cvolume_channels_equal_to;  pa_cvolume_compatible;  pa_cvolume_compatible_with_channel_map; @@ -121,8 +122,10 @@ pa_cvolume_get_fade;  pa_cvolume_get_position;  pa_cvolume_init;  pa_cvolume_max; +pa_cvolume_max_mask;  pa_cvolume_remap;  pa_cvolume_scale; +pa_cvolume_scale_mask;  pa_cvolume_set;  pa_cvolume_set_balance;  pa_cvolume_set_fade; diff --git a/src/pulse/volume.c b/src/pulse/volume.c index e48c7773..64688e0b 100644 --- a/src/pulse/volume.c +++ b/src/pulse/volume.c @@ -80,29 +80,78 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {  pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {      uint64_t sum = 0; -    int i; +    unsigned c;      pa_assert(a);      pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED); -    for (i = 0; i < a->channels; i++) -        sum += a->values[i]; +    for (c = 0; c < a->channels; c++) +        sum += a->values[c];      sum /= a->channels;      return (pa_volume_t) sum;  } +pa_volume_t pa_cvolume_avg_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) { +    uint64_t sum = 0; +    unsigned c, n; + +    pa_assert(a); + +    if (!cm) +        return pa_cvolume_avg(a); + +    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED); + +    for (c = n = 0; c < a->channels; c++) { + +        if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask)) +            continue; + +        sum += a->values[c]; +        n ++; +    } + +    if (n > 0) +        sum /= n; + +    return (pa_volume_t) sum; +} +  pa_volume_t pa_cvolume_max(const pa_cvolume *a) {      pa_volume_t m = 0; -    int i; +    unsigned c;      pa_assert(a);      pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED); -    for (i = 0; i < a->channels; i++) -        if (a->values[i] > m) -            m = a->values[i]; +    for (c = 0; c < a->channels; c++) +        if (a->values[c] > m) +            m = a->values[c]; + +    return m; +} + +pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) { +    pa_volume_t m = 0; +    unsigned c, n; + +    pa_assert(a); + +    if (!cm) +        return pa_cvolume_max(a); + +    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED); + +    for (c = n = 0; c < a->channels; c++) { + +        if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask)) +            continue; + +        if (a->values[c] > m) +            m = a->values[c]; +    }      return m;  } @@ -590,11 +639,29 @@ pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {      pa_return_val_if_fail(pa_cvolume_valid(v), NULL);      pa_return_val_if_fail(max != (pa_volume_t) -1, NULL); +    t = pa_cvolume_max(v); + +    if (t <= PA_VOLUME_MUTED) +        return pa_cvolume_set(v, v->channels, max); +      for (c = 0; c < v->channels; c++) -        if (v->values[c] > t) -            t = v->values[c]; +        v->values[c] = (pa_volume_t) (((uint64_t)  v->values[c] * (uint64_t) max) / (uint64_t) t); + +    return v; +} + +pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map *cm, pa_channel_position_mask_t mask) { +    unsigned c; +    pa_volume_t t = 0; + +    pa_assert(v); + +    pa_return_val_if_fail(pa_cvolume_valid(v), NULL); +    pa_return_val_if_fail(max != (pa_volume_t) -1, NULL); + +    t = pa_cvolume_max_mask(v, cm, mask); -    if (t <= 0) +    if (t <= PA_VOLUME_MUTED)          return pa_cvolume_set(v, v->channels, max);      for (c = 0; c < v->channels; c++) diff --git a/src/pulse/volume.h b/src/pulse/volume.h index b5677785..c07fd99a 100644 --- a/src/pulse/volume.h +++ b/src/pulse/volume.h @@ -178,9 +178,23 @@ char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v);  /** Return the average volume of all channels */  pa_volume_t pa_cvolume_avg(const pa_cvolume *a) PA_GCC_PURE; +/** Return the average volume of all channels that are included in the + * specified channel map with the specified channel position mask. If + * cm is NULL this call is identical to pa_cvolume_avg(). If no + * channel is selected the returned value will be + * PA_VOLUME_MUTED. \since 0.9.16 */ +pa_volume_t pa_cvolume_avg_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) PA_GCC_PURE; +  /** Return the maximum volume of all channels. \since 0.9.12 */  pa_volume_t pa_cvolume_max(const pa_cvolume *a) PA_GCC_PURE; +/** Return the maximum volume of all channels that are included in the + * specified channel map with the specified channel position mask. If + * cm is NULL this call is identical to pa_cvolume_max(). If no + * channel is selected the returned value will be PA_VOLUME_MUTED. + * \since 0.9.16 */ +pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) PA_GCC_PURE; +  /** Return TRUE when the passed cvolume structure is valid, FALSE otherwise */  int pa_cvolume_valid(const pa_cvolume *v) PA_GCC_PURE; @@ -283,6 +297,12 @@ pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float   * volumes are kept. \since 0.9.15 */  pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max); +/** Scale the passed pa_cvolume structure so that the maximum volume + * of all channels selected via cm/mask equals max. This also modifies + * the volume of those channels that are unmasked. The proportions + * between the channel volumes are kept. \since 0.9.16 */ +pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map *cm, pa_channel_position_mask_t mask); +  /** Set the passed volume to all channels at the specified channel   * position. Will return the updated volume struct, or NULL if there   * is no channel at the position specified. You can check if a channel @@ -294,7 +314,7 @@ pa_cvolume* pa_cvolume_set_position(pa_cvolume *cv, const pa_channel_map *map, p   * position. Will return 0 if there is no channel at the position   * specified. You can check if a channel map includes a specific   * position by calling pa_channel_map_has_position(). \since 0.9.16 */ -pa_volume_t pa_cvolume_get_position(pa_cvolume *cv, const pa_channel_map *map, pa_channel_position_t t); +pa_volume_t pa_cvolume_get_position(pa_cvolume *cv, const pa_channel_map *map, pa_channel_position_t t) PA_GCC_PURE;  PA_C_DECL_END  | 
