~diwic/ubuntu/lucid/pulseaudio/bugfixes

« back to all changes in this revision

Viewing changes to src/pulsecore/envelope.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2008-11-04 15:46:00 UTC
  • mfrom: (1.2.1 upstream) (1.1.6 lenny)
  • Revision ID: james.westby@ubuntu.com-20081104154600-hlzknpcazaam0nxm
Tags: 0.9.13-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Don't build against, and create jack package. Jack is not in main.
  - Remove --disable-per-user-esound-socket from configure flags, as we still
    want per user esound sockets.
  - Remove stop links from rc0 and rc6.
  - Change default resample algorithm and bubffer size.
  - Add alsa configuration files to route alsa applications via pulseaudio.
  - Move libasound2-plugins from Recommends to Depends.
* debian/pulseaudio.preinst: When upgrading from intrepid, remove
  /etc/X11/Xsession.d/70pulseaudio, as this was used to minimize a race
  condition when starting GNOME in intrepid. This race should not exist in
  jaunty once libcanberra is built to use pulseaudio as a backend.
* Do not spawn a pulseaudio server if clients fail to find a running server.
* Remove explicit version dependency for libspeex-dev to allow the package
  to be built for now.
* Regenerate autotools files to work with Ubuntu's newer libtool/libltdl.
* debian/control: libpulsecore5 -> libpulsecore8 to match the library
  soname.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***
 
2
  This file is part of PulseAudio.
 
3
 
 
4
  Copyright 2007 Lennart Poettering
 
5
 
 
6
  PulseAudio is free software; you can redistribute it and/or modify
 
7
  it under the terms of the GNU Lesser General Public License as
 
8
  published by the Free Software Foundation; either version 2.1 of the
 
9
  License, or (at your option) any later version.
 
10
 
 
11
  PulseAudio is distributed in the hope that it will be useful, but
 
12
  WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
14
  Lesser General Public License for more details.
 
15
 
 
16
  You should have received a copy of the GNU Lesser General Public
 
17
  License along with PulseAudio; if not, write to the Free Software
 
18
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
19
  USA.
 
20
***/
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#include <config.h>
 
24
#endif
 
25
 
 
26
#include <stdio.h>
 
27
 
 
28
#include <pulse/sample.h>
 
29
#include <pulse/xmalloc.h>
 
30
 
 
31
#include <pulsecore/endianmacros.h>
 
32
#include <pulsecore/memchunk.h>
 
33
#include <pulsecore/macro.h>
 
34
#include <pulsecore/flist.h>
 
35
#include <pulsecore/semaphore.h>
 
36
#include <pulsecore/g711.h>
 
37
 
 
38
#include "envelope.h"
 
39
 
 
40
/*
 
41
    Envelope subsystem for applying linear interpolated volume
 
42
    envelopes on audio data. If multiple enevelopes shall be applied
 
43
    at the same time, the "minimum" envelope is determined and
 
44
    applied.
 
45
 
 
46
    Envelopes are defined in a statically allocated constant structure
 
47
    pa_envelope_def. It may be activated using pa_envelope_add(). And
 
48
    already active envelope may be replaced with pa_envelope_replace()
 
49
    and removed with pa_envelope_remove().The combined "minimum"
 
50
    envelope can be applied to audio data with pa_envelope_apply().
 
51
 
 
52
    _apply() on one hand and _add()/_replace()/_remove() on the other
 
53
    can be executed in seperate threads, in which case no locking is
 
54
    used.
 
55
*/
 
56
 
 
57
PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
 
58
 
 
59
struct pa_envelope_item {
 
60
    PA_LLIST_FIELDS(pa_envelope_item);
 
61
    const pa_envelope_def *def;
 
62
    pa_usec_t start_x;
 
63
    union {
 
64
        int32_t i;
 
65
        float f;
 
66
    } start_y;
 
67
    unsigned j;
 
68
};
 
69
 
 
70
enum envelope_state {
 
71
    STATE_VALID0,
 
72
    STATE_VALID1,
 
73
    STATE_READ0,
 
74
    STATE_READ1,
 
75
    STATE_WAIT0,
 
76
    STATE_WAIT1,
 
77
    STATE_WRITE0,
 
78
    STATE_WRITE1
 
79
};
 
80
 
 
81
struct pa_envelope {
 
82
    pa_sample_spec sample_spec;
 
83
 
 
84
    PA_LLIST_HEAD(pa_envelope_item, items);
 
85
 
 
86
    pa_atomic_t state;
 
87
 
 
88
    size_t x;
 
89
 
 
90
    struct {
 
91
        unsigned n_points, n_allocated, n_current;
 
92
 
 
93
        size_t *x;
 
94
        union {
 
95
            int32_t *i;
 
96
            float *f;
 
97
        } y;
 
98
 
 
99
        size_t cached_dx;
 
100
        int32_t cached_dy_i;
 
101
        float cached_dy_dx;
 
102
        pa_bool_t cached_valid;
 
103
    } points[2];
 
104
 
 
105
    pa_bool_t is_float;
 
106
 
 
107
    pa_semaphore *semaphore;
 
108
};
 
109
 
 
110
pa_envelope *pa_envelope_new(const pa_sample_spec *ss) {
 
111
    pa_envelope *e;
 
112
    pa_assert(ss);
 
113
 
 
114
    e = pa_xnew(pa_envelope, 1);
 
115
 
 
116
    e->sample_spec = *ss;
 
117
    PA_LLIST_HEAD_INIT(pa_envelope_item, e->items);
 
118
 
 
119
    e->x = 0;
 
120
 
 
121
    e->points[0].n_points = e->points[1].n_points = 0;
 
122
    e->points[0].n_allocated = e->points[1].n_allocated = 0;
 
123
    e->points[0].n_current = e->points[1].n_current = 0;
 
124
    e->points[0].x = e->points[1].x = NULL;
 
125
    e->points[0].y.i = e->points[1].y.i = NULL;
 
126
    e->points[0].cached_valid = e->points[1].cached_valid = FALSE;
 
127
 
 
128
    pa_atomic_store(&e->state, STATE_VALID0);
 
129
 
 
130
    e->is_float =
 
131
        ss->format == PA_SAMPLE_FLOAT32LE ||
 
132
        ss->format == PA_SAMPLE_FLOAT32BE;
 
133
 
 
134
    e->semaphore = pa_semaphore_new(0);
 
135
 
 
136
    return e;
 
137
}
 
138
 
 
139
void pa_envelope_free(pa_envelope *e) {
 
140
    pa_assert(e);
 
141
 
 
142
    while (e->items)
 
143
        pa_envelope_remove(e, e->items);
 
144
 
 
145
    pa_xfree(e->points[0].x);
 
146
    pa_xfree(e->points[1].x);
 
147
    pa_xfree(e->points[0].y.i);
 
148
    pa_xfree(e->points[1].y.i);
 
149
 
 
150
    pa_semaphore_free(e->semaphore);
 
151
 
 
152
    pa_xfree(e);
 
153
}
 
154
 
 
155
static int32_t linear_interpolate_int(pa_usec_t x1, int32_t _y1, pa_usec_t x2, int32_t y2, pa_usec_t x3) {
 
156
    return (int32_t) ((double) _y1 + (double) (x3 - x1) * (double) (y2 - _y1) / (double) (x2 - x1));
 
157
}
 
158
 
 
159
static float linear_interpolate_float(pa_usec_t x1, float _y1, pa_usec_t x2, float y2, pa_usec_t x3) {
 
160
    return _y1 + ((float) x3 - (float) x1) * (y2 - _y1) / ((float) x2 - (float) x1);
 
161
}
 
162
 
 
163
static int32_t item_get_int(pa_envelope_item *i, pa_usec_t x) {
 
164
    pa_assert(i);
 
165
 
 
166
    if (x <= i->start_x)
 
167
        return i->start_y.i;
 
168
 
 
169
    x -= i->start_x;
 
170
 
 
171
    if (x <= i->def->points_x[0])
 
172
        return linear_interpolate_int(0, i->start_y.i,
 
173
                                      i->def->points_x[0], i->def->points_y.i[0], x);
 
174
 
 
175
    if (x >= i->def->points_x[i->def->n_points-1])
 
176
        return i->def->points_y.i[i->def->n_points-1];
 
177
 
 
178
    pa_assert(i->j > 0);
 
179
    pa_assert(i->def->points_x[i->j-1] <= x);
 
180
    pa_assert(x < i->def->points_x[i->j]);
 
181
 
 
182
    return linear_interpolate_int(i->def->points_x[i->j-1], i->def->points_y.i[i->j-1],
 
183
                                  i->def->points_x[i->j], i->def->points_y.i[i->j], x);
 
184
}
 
185
 
 
186
static float item_get_float(pa_envelope_item *i, pa_usec_t x) {
 
187
    pa_assert(i);
 
188
 
 
189
    if (x <= i->start_x)
 
190
        return i->start_y.f;
 
191
 
 
192
    x -= i->start_x;
 
193
 
 
194
    if (x <= i->def->points_x[0])
 
195
        return linear_interpolate_float(0, i->start_y.f,
 
196
                                        i->def->points_x[0], i->def->points_y.f[0], x);
 
197
 
 
198
    if (x >= i->def->points_x[i->def->n_points-1])
 
199
        return i->def->points_y.f[i->def->n_points-1];
 
200
 
 
201
    pa_assert(i->j > 0);
 
202
    pa_assert(i->def->points_x[i->j-1] <= x);
 
203
    pa_assert(x < i->def->points_x[i->j]);
 
204
 
 
205
    return linear_interpolate_float(i->def->points_x[i->j-1], i->def->points_y.f[i->j-1],
 
206
                                    i->def->points_x[i->j], i->def->points_y.f[i->j], x);
 
207
}
 
208
 
 
209
static void envelope_begin_write(pa_envelope *e, int *v) {
 
210
    enum envelope_state new_state, old_state;
 
211
    pa_bool_t wait_sem;
 
212
 
 
213
    pa_assert(e);
 
214
    pa_assert(v);
 
215
 
 
216
    for (;;) {
 
217
        do {
 
218
            wait_sem = FALSE;
 
219
            old_state = pa_atomic_load(&e->state);
 
220
 
 
221
            switch (old_state) {
 
222
                case STATE_VALID0:
 
223
                    *v = 1;
 
224
                    new_state = STATE_WRITE0;
 
225
                    break;
 
226
                case STATE_VALID1:
 
227
                    *v = 0;
 
228
                    new_state = STATE_WRITE1;
 
229
                    break;
 
230
                case STATE_READ0:
 
231
                    new_state = STATE_WAIT0;
 
232
                    wait_sem = TRUE;
 
233
                    break;
 
234
                case STATE_READ1:
 
235
                    new_state = STATE_WAIT1;
 
236
                    wait_sem = TRUE;
 
237
                    break;
 
238
                default:
 
239
                    pa_assert_not_reached();
 
240
            }
 
241
        } while (!pa_atomic_cmpxchg(&e->state, old_state, new_state));
 
242
 
 
243
        if (!wait_sem)
 
244
            break;
 
245
 
 
246
        pa_semaphore_wait(e->semaphore);
 
247
    }
 
248
}
 
249
 
 
250
static pa_bool_t envelope_commit_write(pa_envelope *e, int v) {
 
251
    enum envelope_state new_state, old_state;
 
252
 
 
253
    pa_assert(e);
 
254
 
 
255
    do {
 
256
        old_state = pa_atomic_load(&e->state);
 
257
 
 
258
        switch (old_state) {
 
259
            case STATE_WRITE0:
 
260
                pa_assert(v == 1);
 
261
                new_state = STATE_VALID1;
 
262
                break;
 
263
            case STATE_WRITE1:
 
264
                pa_assert(v == 0);
 
265
                new_state = STATE_VALID0;
 
266
                break;
 
267
            case STATE_VALID0:
 
268
            case STATE_VALID1:
 
269
            case STATE_READ0:
 
270
            case STATE_READ1:
 
271
                return FALSE;
 
272
            default:
 
273
                pa_assert_not_reached();
 
274
        }
 
275
    } while (!pa_atomic_cmpxchg(&e->state, old_state, new_state));
 
276
 
 
277
    return TRUE;
 
278
}
 
279
 
 
280
static void envelope_begin_read(pa_envelope *e, int *v) {
 
281
    enum envelope_state new_state, old_state;
 
282
    pa_assert(e);
 
283
    pa_assert(v);
 
284
 
 
285
    do {
 
286
        old_state = pa_atomic_load(&e->state);
 
287
 
 
288
        switch (old_state) {
 
289
            case STATE_VALID0:
 
290
            case STATE_WRITE0:
 
291
                *v = 0;
 
292
                new_state = STATE_READ0;
 
293
                break;
 
294
            case STATE_VALID1:
 
295
            case STATE_WRITE1:
 
296
                *v = 1;
 
297
                new_state = STATE_READ1;
 
298
                break;
 
299
            default:
 
300
                pa_assert_not_reached();
 
301
        }
 
302
    } while (!pa_atomic_cmpxchg(&e->state, old_state, new_state));
 
303
}
 
304
 
 
305
static void envelope_commit_read(pa_envelope *e, int v) {
 
306
    enum envelope_state new_state, old_state;
 
307
    pa_bool_t post_sem;
 
308
 
 
309
    pa_assert(e);
 
310
 
 
311
    do {
 
312
        post_sem = FALSE;
 
313
        old_state = pa_atomic_load(&e->state);
 
314
 
 
315
        switch (old_state) {
 
316
            case STATE_READ0:
 
317
                pa_assert(v == 0);
 
318
                new_state = STATE_VALID0;
 
319
                break;
 
320
            case STATE_READ1:
 
321
                pa_assert(v == 1);
 
322
                new_state = STATE_VALID1;
 
323
                break;
 
324
            case STATE_WAIT0:
 
325
                pa_assert(v == 0);
 
326
                new_state = STATE_VALID0;
 
327
                post_sem = TRUE;
 
328
                break;
 
329
            case STATE_WAIT1:
 
330
                pa_assert(v == 1);
 
331
                new_state = STATE_VALID1;
 
332
                post_sem = TRUE;
 
333
                break;
 
334
            default:
 
335
                pa_assert_not_reached();
 
336
        }
 
337
    } while (!pa_atomic_cmpxchg(&e->state, old_state, new_state));
 
338
 
 
339
    if (post_sem)
 
340
        pa_semaphore_post(e->semaphore);
 
341
}
 
342
 
 
343
static void envelope_merge(pa_envelope *e, int v) {
 
344
 
 
345
    e->points[v].n_points = 0;
 
346
 
 
347
    if (e->items) {
 
348
        pa_envelope_item *i;
 
349
        pa_usec_t x = (pa_usec_t) -1;
 
350
 
 
351
        for (i = e->items; i; i = i->next)
 
352
            i->j = 0;
 
353
 
 
354
        for (;;) {
 
355
            pa_bool_t min_is_set;
 
356
            pa_envelope_item *s = NULL;
 
357
 
 
358
            /* Let's find the next spot on the X axis to analyze */
 
359
            for (i = e->items; i; i = i->next) {
 
360
 
 
361
                for (;;) {
 
362
 
 
363
                    if (i->j >= i->def->n_points)
 
364
                        break;
 
365
 
 
366
                    if ((x != (pa_usec_t) -1) && i->start_x + i->def->points_x[i->j] <= x) {
 
367
                        i->j++;
 
368
                        continue;
 
369
                    }
 
370
 
 
371
                    if (!s || (i->start_x + i->def->points_x[i->j] < s->start_x + s->def->points_x[s->j]))
 
372
                        s = i;
 
373
 
 
374
                    break;
 
375
                }
 
376
            }
 
377
 
 
378
            if (!s)
 
379
                break;
 
380
 
 
381
            if (e->points[v].n_points >= e->points[v].n_allocated) {
 
382
                e->points[v].n_allocated = PA_MAX(e->points[v].n_points*2, PA_ENVELOPE_POINTS_MAX);
 
383
 
 
384
                e->points[v].x = pa_xrealloc(e->points[v].x, sizeof(size_t) * e->points[v].n_allocated);
 
385
                e->points[v].y.i = pa_xrealloc(e->points[v].y.i, sizeof(int32_t) * e->points[v].n_allocated);
 
386
            }
 
387
 
 
388
            x = s->start_x + s->def->points_x[s->j];
 
389
            e->points[v].x[e->points[v].n_points] = pa_usec_to_bytes(x, &e->sample_spec);
 
390
 
 
391
            min_is_set = FALSE;
 
392
 
 
393
            /* Now let's find the lowest value */
 
394
            if (e->is_float) {
 
395
                float min_f;
 
396
 
 
397
                for (i = e->items; i; i = i->next) {
 
398
                    float f = item_get_float(i, x);
 
399
                    if (!min_is_set || f < min_f) {
 
400
                        min_f = f;
 
401
                        min_is_set = TRUE;
 
402
                    }
 
403
                }
 
404
 
 
405
                e->points[v].y.f[e->points[v].n_points] = min_f;
 
406
            } else {
 
407
                int32_t min_k;
 
408
 
 
409
                for (i = e->items; i; i = i->next) {
 
410
                    int32_t k = item_get_int(i, x);
 
411
                    if (!min_is_set || k < min_k) {
 
412
                        min_k = k;
 
413
                        min_is_set = TRUE;
 
414
                    }
 
415
                }
 
416
 
 
417
                e->points[v].y.i[e->points[v].n_points] = min_k;
 
418
            }
 
419
 
 
420
            pa_assert_se(min_is_set);
 
421
            e->points[v].n_points++;
 
422
        }
 
423
    }
 
424
 
 
425
    e->points[v].n_current = 0;
 
426
    e->points[v].cached_valid = FALSE;
 
427
}
 
428
 
 
429
pa_envelope_item *pa_envelope_add(pa_envelope *e, const pa_envelope_def *def) {
 
430
    pa_envelope_item *i;
 
431
    int v;
 
432
 
 
433
    pa_assert(e);
 
434
    pa_assert(def);
 
435
    pa_assert(def->n_points > 0);
 
436
 
 
437
    if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
 
438
        i = pa_xnew(pa_envelope_item, 1);
 
439
 
 
440
    i->def = def;
 
441
 
 
442
    if (e->is_float)
 
443
        i->start_y.f = def->points_y.f[0];
 
444
    else
 
445
        i->start_y.i = def->points_y.i[0];
 
446
 
 
447
    PA_LLIST_PREPEND(pa_envelope_item, e->items, i);
 
448
 
 
449
    envelope_begin_write(e, &v);
 
450
 
 
451
    do {
 
452
 
 
453
        i->start_x = pa_bytes_to_usec(e->x, &e->sample_spec);
 
454
        envelope_merge(e, v);
 
455
 
 
456
    } while (!envelope_commit_write(e, v));
 
457
 
 
458
    return i;
 
459
}
 
460
 
 
461
pa_envelope_item *pa_envelope_replace(pa_envelope *e, pa_envelope_item *i, const pa_envelope_def *def) {
 
462
    pa_usec_t x;
 
463
    int v;
 
464
 
 
465
    pa_assert(e);
 
466
    pa_assert(i);
 
467
    pa_assert(def->n_points > 0);
 
468
 
 
469
    envelope_begin_write(e, &v);
 
470
 
 
471
    for (;;) {
 
472
        float saved_f;
 
473
        int32_t saved_i;
 
474
        uint64_t saved_start_x;
 
475
        const pa_envelope_def *saved_def;
 
476
 
 
477
        x = pa_bytes_to_usec(e->x, &e->sample_spec);
 
478
 
 
479
        if (e->is_float) {
 
480
            saved_f = i->start_y.f;
 
481
            i->start_y.f = item_get_float(i, x);
 
482
        } else {
 
483
            saved_i = i->start_y.i;
 
484
            i->start_y.i = item_get_int(i, x);
 
485
        }
 
486
 
 
487
        saved_start_x = i->start_x;
 
488
        saved_def = i->def;
 
489
 
 
490
        i->start_x = x;
 
491
        i->def = def;
 
492
 
 
493
        envelope_merge(e, v);
 
494
 
 
495
        if (envelope_commit_write(e, v))
 
496
            break;
 
497
 
 
498
        i->start_x = saved_start_x;
 
499
        i->def = saved_def;
 
500
 
 
501
        if (e->is_float)
 
502
            i->start_y.f = saved_f;
 
503
        else
 
504
            i->start_y.i = saved_i;
 
505
    }
 
506
 
 
507
    return i;
 
508
}
 
509
 
 
510
void pa_envelope_remove(pa_envelope *e, pa_envelope_item *i) {
 
511
    int v;
 
512
 
 
513
    pa_assert(e);
 
514
    pa_assert(i);
 
515
 
 
516
    PA_LLIST_REMOVE(pa_envelope_item, e->items, i);
 
517
 
 
518
    if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
 
519
        pa_xfree(i);
 
520
 
 
521
    envelope_begin_write(e, &v);
 
522
    do {
 
523
        envelope_merge(e, v);
 
524
    } while (!envelope_commit_write(e, v));
 
525
}
 
526
 
 
527
static int32_t linear_get_int(pa_envelope *e, int v) {
 
528
    pa_assert(e);
 
529
 
 
530
    /* The repeated division could be replaced by Bresenham, as an
 
531
     * optimization */
 
532
 
 
533
    if (e->x < e->points[v].x[0])
 
534
        return e->points[v].y.i[0];
 
535
 
 
536
    for (;;) {
 
537
        if (e->points[v].n_current+1 >= e->points[v].n_points)
 
538
            return e->points[v].y.i[e->points[v].n_points-1];
 
539
 
 
540
        if (e->x < e->points[v].x[e->points[v].n_current+1])
 
541
            break;
 
542
 
 
543
        e->points[v].n_current++;
 
544
        e->points[v].cached_valid = FALSE;
 
545
    }
 
546
 
 
547
    if (!e->points[v].cached_valid) {
 
548
        e->points[v].cached_dx = e->points[v].x[e->points[v].n_current+1] - e->points[v].x[e->points[v].n_current];
 
549
        e->points[v].cached_dy_i = e->points[v].y.i[e->points[v].n_current+1] - e->points[v].y.i[e->points[v].n_current];
 
550
        e->points[v].cached_valid = TRUE;
 
551
    }
 
552
 
 
553
    return e->points[v].y.i[e->points[v].n_current] + (e->points[v].cached_dy_i * (int32_t) (e->x - e->points[v].x[e->points[v].n_current])) / (int32_t) e->points[v].cached_dx;
 
554
}
 
555
 
 
556
static float linear_get_float(pa_envelope *e, int v) {
 
557
    pa_assert(e);
 
558
 
 
559
    if (e->x < e->points[v].x[0])
 
560
        return e->points[v].y.f[0];
 
561
 
 
562
    for (;;) {
 
563
        if (e->points[v].n_current+1 >= e->points[v].n_points)
 
564
            return e->points[v].y.f[e->points[v].n_points-1];
 
565
 
 
566
        if (e->x < e->points[v].x[e->points[v].n_current+1])
 
567
            break;
 
568
 
 
569
        e->points[v].n_current++;
 
570
        e->points[v].cached_valid = FALSE;
 
571
    }
 
572
 
 
573
    if (!e->points[v].cached_valid) {
 
574
        e->points[v].cached_dy_dx =
 
575
            (e->points[v].y.f[e->points[v].n_current+1] - e->points[v].y.f[e->points[v].n_current]) /
 
576
            ((float) e->points[v].x[e->points[v].n_current+1] - (float) e->points[v].x[e->points[v].n_current]);
 
577
        e->points[v].cached_valid = TRUE;
 
578
    }
 
579
 
 
580
    return e->points[v].y.f[e->points[v].n_current] + (float) (e->x - e->points[v].x[e->points[v].n_current]) * e->points[v].cached_dy_dx;
 
581
}
 
582
 
 
583
void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
 
584
    int v;
 
585
 
 
586
    pa_assert(e);
 
587
    pa_assert(chunk);
 
588
 
 
589
    envelope_begin_read(e, &v);
 
590
 
 
591
    if (e->points[v].n_points > 0) {
 
592
        void *p;
 
593
        size_t fs, n;
 
594
 
 
595
        pa_memchunk_make_writable(chunk, 0);
 
596
        p = (uint8_t*) pa_memblock_acquire(chunk->memblock) + chunk->index;
 
597
        fs = pa_frame_size(&e->sample_spec);
 
598
        n = chunk->length;
 
599
 
 
600
        switch (e->sample_spec.format) {
 
601
 
 
602
 
 
603
 
 
604
            case PA_SAMPLE_U8: {
 
605
                uint8_t *t;
 
606
 
 
607
                for (t = p; n > 0; n -= fs) {
 
608
                    int32_t factor = linear_get_int(e, v);
 
609
                    unsigned c;
 
610
                    e->x += fs;
 
611
 
 
612
                    for (c = 0; c < e->sample_spec.channels; c++, t++)
 
613
                        *t = (uint8_t) (((factor * ((int16_t) *t - 0x80)) / 0x10000) + 0x80);
 
614
                }
 
615
 
 
616
                break;
 
617
            }
 
618
 
 
619
            case PA_SAMPLE_ULAW: {
 
620
                uint8_t *t;
 
621
 
 
622
                for (t = p; n > 0; n -= fs) {
 
623
                    int32_t factor = linear_get_int(e, v);
 
624
                    unsigned c;
 
625
                    e->x += fs;
 
626
 
 
627
                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
 
628
                        int16_t k = st_ulaw2linear16(*t);
 
629
                        *t = (uint8_t) st_14linear2ulaw((int16_t) (((factor * k) / 0x10000) >> 2));
 
630
                    }
 
631
                }
 
632
 
 
633
                break;
 
634
            }
 
635
 
 
636
            case PA_SAMPLE_ALAW: {
 
637
                uint8_t *t;
 
638
 
 
639
                for (t = p; n > 0; n -= fs) {
 
640
                    int32_t factor = linear_get_int(e, v);
 
641
                    unsigned c;
 
642
                    e->x += fs;
 
643
 
 
644
                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
 
645
                        int16_t k = st_alaw2linear16(*t);
 
646
                        *t = (uint8_t) st_13linear2alaw((int16_t) (((factor * k) / 0x10000) >> 3));
 
647
                    }
 
648
                }
 
649
 
 
650
                break;
 
651
            }
 
652
 
 
653
            case PA_SAMPLE_S16NE: {
 
654
                int16_t *t;
 
655
 
 
656
                for (t = p; n > 0; n -= fs) {
 
657
                    int32_t factor = linear_get_int(e, v);
 
658
                    unsigned c;
 
659
                    e->x += fs;
 
660
 
 
661
                    for (c = 0; c < e->sample_spec.channels; c++, t++)
 
662
                        *t = (int16_t) ((factor * *t) / 0x10000);
 
663
                }
 
664
 
 
665
                break;
 
666
            }
 
667
 
 
668
            case PA_SAMPLE_S16RE: {
 
669
                int16_t *t;
 
670
 
 
671
                for (t = p; n > 0; n -= fs) {
 
672
                    int32_t factor = linear_get_int(e, v);
 
673
                    unsigned c;
 
674
                    e->x += fs;
 
675
 
 
676
                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
 
677
                        int16_t r = (int16_t) ((factor * PA_INT16_SWAP(*t)) / 0x10000);
 
678
                        *t = PA_INT16_SWAP(r);
 
679
                    }
 
680
                }
 
681
 
 
682
                break;
 
683
            }
 
684
 
 
685
            case PA_SAMPLE_S32NE: {
 
686
                int32_t *t;
 
687
 
 
688
                for (t = p; n > 0; n -= fs) {
 
689
                    int32_t factor = linear_get_int(e, v);
 
690
                    unsigned c;
 
691
                    e->x += fs;
 
692
 
 
693
                    for (c = 0; c < e->sample_spec.channels; c++, t++)
 
694
                        *t = (int32_t) (((int64_t) factor * (int64_t) *t) / 0x10000);
 
695
                }
 
696
 
 
697
                break;
 
698
            }
 
699
 
 
700
            case PA_SAMPLE_S32RE: {
 
701
                int32_t *t;
 
702
 
 
703
                for (t = p; n > 0; n -= fs) {
 
704
                    int32_t factor = linear_get_int(e, v);
 
705
                    unsigned c;
 
706
                    e->x += fs;
 
707
 
 
708
                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
 
709
                        int32_t r = (int32_t) (((int64_t) factor * (int64_t) PA_INT32_SWAP(*t)) / 0x10000);
 
710
                        *t = PA_INT32_SWAP(r);
 
711
                    }
 
712
                }
 
713
 
 
714
                break;
 
715
            }
 
716
 
 
717
            case PA_SAMPLE_FLOAT32NE: {
 
718
                float *t;
 
719
 
 
720
                for (t = p; n > 0; n -= fs) {
 
721
                    float factor = linear_get_float(e, v);
 
722
                    unsigned c;
 
723
                    e->x += fs;
 
724
 
 
725
                    for (c = 0; c < e->sample_spec.channels; c++, t++)
 
726
                        *t = *t * factor;
 
727
                }
 
728
 
 
729
                break;
 
730
            }
 
731
 
 
732
            case PA_SAMPLE_FLOAT32RE: {
 
733
                float *t;
 
734
 
 
735
                for (t = p; n > 0; n -= fs) {
 
736
                    float factor = linear_get_float(e, v);
 
737
                    unsigned c;
 
738
                    e->x += fs;
 
739
 
 
740
                    for (c = 0; c < e->sample_spec.channels; c++, t++) {
 
741
                        float r = PA_FLOAT32_SWAP(*t) * factor;
 
742
                        *t = PA_FLOAT32_SWAP(r);
 
743
                    }
 
744
                }
 
745
 
 
746
                break;
 
747
            }
 
748
 
 
749
            case PA_SAMPLE_MAX:
 
750
            case PA_SAMPLE_INVALID:
 
751
                pa_assert_not_reached();
 
752
        }
 
753
 
 
754
        pa_memblock_release(chunk->memblock);
 
755
 
 
756
        e->x += chunk->length;
 
757
    } else {
 
758
        /* When we have no envelope to apply we reset our origin */
 
759
        e->x = 0;
 
760
    }
 
761
 
 
762
    envelope_commit_read(e, v);
 
763
}
 
764
 
 
765
void pa_envelope_rewind(pa_envelope *e, size_t n_bytes) {
 
766
    int v;
 
767
 
 
768
    pa_assert(e);
 
769
 
 
770
    envelope_begin_read(e, &v);
 
771
 
 
772
    if (n_bytes < e->x)
 
773
        e->x -= n_bytes;
 
774
    else
 
775
        e->x = 0;
 
776
 
 
777
    e->points[v].n_current = 0;
 
778
    e->points[v].cached_valid = FALSE;
 
779
 
 
780
    envelope_commit_read(e, v);
 
781
}