Merge "[RCAR] Update Rcar gen3 BSP to 3.6"
[AGL/meta-agl.git] / meta-agl-profile-core / recipes-multimedia / pulseaudio / pulseaudio / 0010-volume-ramp-additions-to-the-low-level-infra.patch
1 --- a/src/map-file      2016-04-12 15:03:17.009975690 +0200
2 +++ b/src/map-file      2016-04-12 15:03:52.389975631 +0200
3 @@ -136,6 +136,9 @@
4  pa_cvolume_merge;
5  pa_cvolume_min;
6  pa_cvolume_min_mask;
7 +pa_cvolume_ramp_init;
8 +pa_cvolume_ramp_set;
9 +pa_cvolume_ramp_channel_ramp_set;
10  pa_cvolume_remap;
11  pa_cvolume_scale;
12  pa_cvolume_scale_mask;
13 --- a/src/pulse/def.h   2016-04-12 15:05:58.245975421 +0200
14 +++ b/src/pulse/def.h   2016-04-12 15:13:19.424974685 +0200
15 @@ -347,11 +347,15 @@
16       * consider absolute when the sink is in flat volume mode,
17       * relative otherwise. \since 0.9.20 */
18  
19 -    PA_STREAM_PASSTHROUGH = 0x80000U
20 +    PA_STREAM_PASSTHROUGH = 0x80000U,
21      /**< Used to tag content that will be rendered by passthrough sinks.
22       * The data will be left as is and not reformatted, resampled.
23       * \since 1.0 */
24  
25 +    PA_STREAM_START_RAMP_MUTED = 0x100000U
26 +    /**< Used to tag content that the stream will be started ramp volume
27 +     * muted so that you can nicely fade it in */
28 +
29  } pa_stream_flags_t;
30  
31  /** \cond fulldocs */
32 @@ -380,6 +384,7 @@
33  #define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
34  #define PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME
35  #define PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH
36 +#define PA_STREAM_START_RAMP_MUTED PA_STREAM_START_RAMP_MUTED
37  
38  /** \endcond */
39  
40 @@ -1047,6 +1052,13 @@
41  /** \endcond */
42  #endif
43  
44 +/** \cond fulldocs */
45 +#define PA_VOLUMER_RAMP_TYPE_LINEAR PA_VOLUMER_RAMP_TYPE_LINEAR
46 +#define PA_VOLUMER_RAMP_TYPE_LOGARITHMIC PA_VOLUMER_RAMP_TYPE_LOGARITHMIC
47 +#define PA_VOLUMER_RAMP_TYPE_CUBIC PA_VOLUMER_RAMP_TYPE_CUBIC
48 +
49 +/** \endcond */
50 +
51  PA_C_DECL_END
52  
53  #endif
54 --- a/src/pulse/volume.c        2016-04-12 15:13:38.598974653 +0200
55 +++ b/src/pulse/volume.c        2016-04-12 15:27:57.729973219 +0200
56 @@ -445,7 +445,10 @@
57      unsigned c;
58      pa_assert(a);
59  
60 -    pa_return_val_if_fail(pa_cvolume_valid(a), 0);
61 +    if (pa_cvolume_valid(a) == 0)
62 +        abort();
63 +
64 +    /* pa_return_val_if_fail(pa_cvolume_valid(a), 0); */
65      pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0);
66  
67      for (c = 0; c < a->channels; c++)
68 @@ -986,3 +989,51 @@
69  
70      return pa_cvolume_scale(v, m);
71  }
72 +
73 +pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp) {
74 +    unsigned c;
75 +
76 +    pa_assert(ramp);
77 +
78 +    ramp->channels = 0;
79 +
80 +    for (c = 0; c < PA_CHANNELS_MAX; c++) {
81 +        ramp->ramps[c].type = PA_VOLUME_RAMP_TYPE_LINEAR;
82 +        ramp->ramps[c].length = 0;
83 +        ramp->ramps[c].target = PA_VOLUME_INVALID;
84 +    }
85 +
86 +    return ramp;
87 +}
88 +
89 +pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channels, pa_volume_ramp_type_t type, long time, pa_volume_t vol) {
90 +    int i;
91 +
92 +    pa_assert(ramp);
93 +    pa_assert(channels > 0);
94 +    pa_assert(time >= 0);
95 +    pa_assert(channels <= PA_CHANNELS_MAX);
96 +
97 +    ramp->channels = (uint8_t) channels;
98 +
99 +    for (i = 0; i < ramp->channels; i++) {
100 +        ramp->ramps[i].type = type;
101 +        ramp->ramps[i].length = time;
102 +        ramp->ramps[i].target = PA_CLAMP_VOLUME(vol);
103 +    }
104 +
105 +    return ramp;
106 +}
107 +
108 +pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol) {
109 +
110 +    pa_assert(ramp);
111 +    pa_assert(channel <= ramp->channels);
112 +    pa_assert(time >= 0);
113 +
114 +    ramp->ramps[channel].type = type;
115 +    ramp->ramps[channel].length = time;
116 +    ramp->ramps[channel].target = PA_CLAMP_VOLUME(vol);
117 +
118 +    return ramp;
119 +}
120 --- a/src/pulse/volume.h        2016-04-12 15:40:34.989971955 +0200
121 +++ b/src/pulse/volume.h        2016-04-12 15:38:50.708972129 +0200
122 @@ -413,6 +413,36 @@
123   * the channels are kept. \since 0.9.16 */
124  pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec);
125  
126 +/** Volume ramp type
127 +*/
128 +typedef enum pa_volume_ramp_type {
129 +    PA_VOLUME_RAMP_TYPE_LINEAR = 0,        /**< linear */
130 +    PA_VOLUME_RAMP_TYPE_LOGARITHMIC = 1,   /**< logarithmic */
131 +    PA_VOLUME_RAMP_TYPE_CUBIC = 2,
132 +} pa_volume_ramp_type_t;
133 +
134 +/** A structure encapsulating a volume ramp */
135 +typedef struct pa_volume_ramp_t {
136 +    pa_volume_ramp_type_t type;
137 +    long length;
138 +    pa_volume_t target;
139 +} pa_volume_ramp_t;
140 +
141 +/** A structure encapsulating a multichannel volume ramp */
142 +typedef struct pam_cvolume_ramp {
143 +    uint8_t channels;
144 +    pa_volume_ramp_t ramps[PA_CHANNELS_MAX];
145 +} pa_cvolume_ramp;
146 +
147 +/** Init volume ramp struct */
148 +pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp);
149 +
150 +/** Set first n channels of ramp struct to certain value */
151 +pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol);
152 +
153 +/** Set individual channel in the channel struct */
154 +pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol);
155 +
156  PA_C_DECL_END
157  
158  #endif
159 --- a/src/pulsecore/sample-util.c       2016-04-12 15:41:51.812971827 +0200
160 +++ b/src/pulsecore/sample-util.c       2016-04-12 16:31:56.795966812 +0200
161 @@ -41,6 +41,13 @@
162  
163  #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
164  
165 +#define VOLUME_PADDING 32
166 +
167 +typedef union {
168 +    float f;
169 +    uint32_t i;
170 +} volume_val;
171 +
172  pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
173      void *data;
174  
175 @@ -403,3 +410,292 @@
176      usec = pa_bytes_to_usec_round_up(size, from);
177      return pa_usec_to_bytes_round_up(usec, to);
178  }
179 +
180 +static void calc_linear_integer_volume_no_mapping(int32_t linear[], float volume[], unsigned nchannels) {
181 +    unsigned channel, padding;
182 +
183 +    pa_assert(linear);
184 +    pa_assert(volume);
185 +
186 +    for (channel = 0; channel < nchannels; channel++)
187 +        linear[channel] = (int32_t) lrint(volume[channel] * 0x10000U);
188 +
189 +    for (padding = 0; padding < VOLUME_PADDING; padding++, channel++)
190 +        linear[channel] = linear[padding];
191 +}
192 +
193 +static void calc_linear_float_volume_no_mapping(float linear[], float volume[], unsigned nchannels) {
194 +    unsigned channel, padding;
195 +
196 +    pa_assert(linear);
197 +    pa_assert(volume);
198 +
199 +    for (channel = 0; channel < nchannels; channel++)
200 +        linear[channel] = volume[channel];
201 +
202 +    for (padding = 0; padding < VOLUME_PADDING; padding++, channel++)
203 +        linear[channel] = linear[padding];
204 +}
205 +
206 +typedef void (*pa_calc_volume_no_mapping_func_t) (void *volumes, float *volume, int channels);
207 +
208 +static const pa_calc_volume_no_mapping_func_t calc_volume_table_no_mapping[] = {
209 +  [PA_SAMPLE_U8]        = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
210 +  [PA_SAMPLE_ALAW]      = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
211 +  [PA_SAMPLE_ULAW]      = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
212 +  [PA_SAMPLE_S16LE]     = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
213 +  [PA_SAMPLE_S16BE]     = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
214 +  [PA_SAMPLE_FLOAT32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping,
215 +  [PA_SAMPLE_FLOAT32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping,
216 +  [PA_SAMPLE_S32LE]     = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
217 +  [PA_SAMPLE_S32BE]     = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
218 +  [PA_SAMPLE_S24LE]     = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
219 +  [PA_SAMPLE_S24BE]     = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
220 +  [PA_SAMPLE_S24_32LE]  = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
221 +  [PA_SAMPLE_S24_32BE]  = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping
222 +};
223 +
224 +static const unsigned format_sample_size_table[] = {
225 +  [PA_SAMPLE_U8]        = 1,
226 +  [PA_SAMPLE_ALAW]      = 1,
227 +  [PA_SAMPLE_ULAW]      = 1,
228 +  [PA_SAMPLE_S16LE]     = 2,
229 +  [PA_SAMPLE_S16BE]     = 2,
230 +  [PA_SAMPLE_FLOAT32LE] = 4,
231 +  [PA_SAMPLE_FLOAT32BE] = 4,
232 +  [PA_SAMPLE_S32LE]     = 4,
233 +  [PA_SAMPLE_S32BE]     = 4,
234 +  [PA_SAMPLE_S24LE]     = 3,
235 +  [PA_SAMPLE_S24BE]     = 3,
236 +  [PA_SAMPLE_S24_32LE]  = 4,
237 +  [PA_SAMPLE_S24_32BE]  = 4
238 +};
239 +
240 +static float calc_volume_ramp_linear(pa_volume_ramp_int_t *ramp) {
241 +    pa_assert(ramp);
242 +    pa_assert(ramp->length > 0);
243 +
244 +    /* basic linear interpolation */
245 +    return ramp->start + (ramp->length - ramp->left) * (ramp->end - ramp->start) / (float) ramp->length;
246 +}
247 +
248 +static float calc_volume_ramp_logarithmic(pa_volume_ramp_int_t *ramp) {
249 +    float x_val, s, e;
250 +    long temp;
251 +
252 +    pa_assert(ramp);
253 +    pa_assert(ramp->length > 0);
254 +
255 +    if (ramp->end > ramp->start) {
256 +        temp = ramp->left;
257 +        s = ramp->end;
258 +        e = ramp->start;
259 +    } else {
260 +        temp = ramp->length - ramp->left;
261 +        s = ramp->start;
262 +        e = ramp->end;
263 +    }
264 +
265 +    x_val = temp == 0 ? 0.0 : powf(temp, 10);
266 +
267 +    /* base 10 logarithmic interpolation */
268 +    return s + x_val * (e - s) / powf(ramp->length, 10);
269 +}
270 +
271 +static float calc_volume_ramp_cubic(pa_volume_ramp_int_t *ramp) {
272 +    float x_val, s, e;
273 +    long temp;
274 +
275 +    pa_assert(ramp);
276 +    pa_assert(ramp->length > 0);
277 +
278 +    if (ramp->end > ramp->start) {
279 +        temp = ramp->left;
280 +        s = ramp->end;
281 +        e = ramp->start;
282 +    } else {
283 +        temp = ramp->length - ramp->left;
284 +        s = ramp->start;
285 +        e = ramp->end;
286 +    }
287 +
288 +    x_val = temp == 0 ? 0.0 : cbrtf(temp);
289 +
290 +    /* cubic interpolation */
291 +    return s + x_val * (e - s) / cbrtf(ramp->length);
292 +}
293 +
294 +typedef float (*pa_calc_volume_ramp_func_t) (pa_volume_ramp_int_t *);
295 +
296 +static const pa_calc_volume_ramp_func_t calc_volume_ramp_table[] = {
297 +    [PA_VOLUME_RAMP_TYPE_LINEAR] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_linear,
298 +    [PA_VOLUME_RAMP_TYPE_LOGARITHMIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_logarithmic,
299 +    [PA_VOLUME_RAMP_TYPE_CUBIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_cubic
300 +};
301 +
302 +static void calc_volume_ramps(pa_cvolume_ramp_int *ram, float *vol)
303 +{
304 +    int i;
305 +
306 +    for (i = 0; i < ram->channels; i++) {
307 +        if (ram->ramps[i].left <= 0) {
308 +            if (ram->ramps[i].target == PA_VOLUME_NORM) {
309 +                vol[i] = 1.0;
310 +            }
311 +        } else {
312 +            vol[i] = ram->ramps[i].curr = calc_volume_ramp_table[ram->ramps[i].type] (&ram->ramps[i]);
313 +            ram->ramps[i].left--;
314 +        }
315 +    }
316 +}
317 +
318 +void pa_volume_ramp_memchunk(
319 +        pa_memchunk *c,
320 +        const pa_sample_spec *spec,
321 +        pa_cvolume_ramp_int *ramp) {
322 +
323 +    void *ptr;
324 +    volume_val linear[PA_CHANNELS_MAX + VOLUME_PADDING];
325 +    float vol[PA_CHANNELS_MAX + VOLUME_PADDING];
326 +    pa_do_volume_func_t do_volume;
327 +    long length_in_frames;
328 +    int i;
329 +
330 +    pa_assert(c);
331 +    pa_assert(spec);
332 +    pa_assert(pa_frame_aligned(c->length, spec));
333 +    pa_assert(ramp);
334 +
335 +    length_in_frames = c->length / format_sample_size_table[spec->format] / spec->channels;
336 +
337 +    if (pa_memblock_is_silence(c->memblock)) {
338 +        for (i = 0; i < ramp->channels; i++) {
339 +            if (ramp->ramps[i].length > 0)
340 +                ramp->ramps[i].length -= length_in_frames;
341 +        }
342 +        return;
343 +    }
344 +
345 +    if (spec->format < 0 || spec->format >= PA_SAMPLE_MAX) {
346 +      pa_log_warn("Unable to change volume of format");
347 +      return;
348 +    }
349 +
350 +    do_volume = pa_get_volume_func(spec->format);
351 +    pa_assert(do_volume);
352 +
353 +    ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index;
354 +
355 +    for (i = 0; i < length_in_frames; i++) {
356 +        calc_volume_ramps(ramp, vol);
357 +        calc_volume_table_no_mapping[spec->format] ((void *)linear, vol, spec->channels);
358 +
359 +        /* we only process one frame per iteration */
360 +        do_volume (ptr, (void *)linear, spec->channels, format_sample_size_table[spec->format] * spec->channels);
361 +
362 +        /* pa_log_debug("1: %d  2: %d", linear[0], linear[1]); */
363 +
364 +        ptr = (uint8_t*)ptr + format_sample_size_table[spec->format] * spec->channels;
365 +    }
366 +
367 +    pa_memblock_release(c->memblock);
368 +}
369 +
370 +pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate) {
371 +    int i;
372 +    float temp;
373 +
374 +    for (i = 0; i < dst->channels; i++) {
375 +        dst->ramps[i].type = src->ramps[i].type;
376 +        /* ms to samples */
377 +        dst->ramps[i].length = src->ramps[i].length * sample_rate / 1000;
378 +        dst->ramps[i].left = dst->ramps[i].length;
379 +        dst->ramps[i].start = dst->ramps[i].end;
380 +        dst->ramps[i].target = src->ramps[i].target;
381 +        /* scale to pulse internal mapping so that when ramp is over there's no glitch in volume */
382 +        temp = src->ramps[i].target / (float)0x10000U;
383 +        dst->ramps[i].end = temp * temp * temp;
384 +    }
385 +
386 +    return dst;
387 +}
388 +
389 +bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp) {
390 +    int i;
391 +
392 +    for (i = 0; i < ramp->channels; i++) {
393 +        if (ramp->ramps[i].left > 0)
394 +            return true;
395 +    }
396 +
397 +    return false;
398 +}
399 +
400 +bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp) {
401 +    int i;
402 +
403 +    for (i = 0; i < ramp->channels; i++) {
404 +        if (ramp->ramps[i].target != PA_VOLUME_NORM)
405 +            return true;
406 +    }
407 +
408 +    return false;
409 +}
410 +
411 +pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume) {
412 +    int i = 0;
413 +
414 +    volume->channels = ramp->channels;
415 +
416 +    for (i = 0; i < ramp->channels; i++)
417 +        volume->values[i] = ramp->ramps[i].target;
418 +
419 +    return volume;
420 +}
421 +
422 +pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst) {
423 +    int i;
424 +
425 +    for (i = 0; i < src->channels; i++) {
426 +        /* if new vols are invalid, copy old ramp i.e. no effect */
427 +        if (dst->ramps[i].target == PA_VOLUME_INVALID)
428 +            dst->ramps[i] = src->ramps[i];
429 +        /* if there's some old ramp still left */
430 +        else if (src->ramps[i].left > 0)
431 +            dst->ramps[i].start = src->ramps[i].curr;
432 +    }
433 +
434 +    return dst;
435 +}
436 +
437 +pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels) {
438 +    int i;
439 +    float temp;
440 +
441 +    src->channels = channels;
442 +
443 +    for (i = 0; i < channels; i++) {
444 +        src->ramps[i].type = PA_VOLUME_RAMP_TYPE_LINEAR;
445 +        src->ramps[i].length = 0;
446 +        src->ramps[i].left = 0;
447 +        if (vol == PA_VOLUME_NORM) {
448 +            src->ramps[i].start = 1.0;
449 +            src->ramps[i].end = 1.0;
450 +            src->ramps[i].curr = 1.0;
451 +        }
452 +        else if (vol == PA_VOLUME_MUTED) {
453 +            src->ramps[i].start = 0.0;
454 +            src->ramps[i].end = 0.0;
455 +            src->ramps[i].curr = 0.0;
456 +        }
457 +        else {
458 +            temp = vol / (float)0x10000U;
459 +            src->ramps[i].start = temp * temp * temp;
460 +            src->ramps[i].end = src->ramps[i].start;
461 +            src->ramps[i].curr = src->ramps[i].start;
462 +        }
463 +        src->ramps[i].target = vol;
464 +    }
465 +
466 +    return src;
467 +}
468 --- a/src/pulsecore/sample-util.h       2016-04-12 15:53:06.327970701 +0200
469 +++ b/src/pulsecore/sample-util.h       2016-04-12 16:24:16.356967580 +0200
470 @@ -45,6 +45,33 @@
471  
472  pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length);
473  
474 +typedef struct pa_volume_ramp_int_t {
475 +    pa_volume_ramp_type_t type;
476 +    long length;
477 +    long left;
478 +    float start;
479 +    float end;
480 +    float curr;
481 +    pa_volume_t target;
482 +} pa_volume_ramp_int_t;
483 +
484 +typedef struct pa_cvolume_ramp_int {
485 +    uint8_t channels;
486 +    pa_volume_ramp_int_t ramps[PA_CHANNELS_MAX];
487 +} pa_cvolume_ramp_int;
488 +
489 +pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate);
490 +bool pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp);
491 +bool pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp);
492 +pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst);
493 +pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels);
494 +pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume);
495 +
496 +void pa_volume_ramp_memchunk(
497 +        pa_memchunk *c,
498 +        const pa_sample_spec *spec,
499 +        pa_cvolume_ramp_int *ramp);
500 +
501  size_t pa_frame_align(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;
502  
503  bool pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;