Add default-monitor-time-sec
[platform/upstream/pulseaudio.git] / src / pulsecore / sample-util.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <math.h>
30
31 #include <pulse/timeval.h>
32
33 #include <pulsecore/log.h>
34 #include <pulsecore/core-error.h>
35 #include <pulsecore/macro.h>
36 #include <pulsecore/g711.h>
37 #include <pulsecore/core-util.h>
38 #include <pulsecore/endianmacros.h>
39
40 #include "sample-util.h"
41
42 #define PA_SILENCE_MAX (pa_page_size()*16)
43
44 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
45     void *data;
46
47     pa_assert(b);
48     pa_assert(spec);
49
50     data = pa_memblock_acquire(b);
51     pa_silence_memory(data, pa_memblock_get_length(b), spec);
52     pa_memblock_release(b);
53
54     return b;
55 }
56
57 pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
58     void *data;
59
60     pa_assert(c);
61     pa_assert(c->memblock);
62     pa_assert(spec);
63
64     data = pa_memblock_acquire(c->memblock);
65     pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
66     pa_memblock_release(c->memblock);
67
68     return c;
69 }
70
71 static uint8_t silence_byte(pa_sample_format_t format) {
72     switch (format) {
73         case PA_SAMPLE_U8:
74             return 0x80;
75         case PA_SAMPLE_S16LE:
76         case PA_SAMPLE_S16BE:
77         case PA_SAMPLE_S32LE:
78         case PA_SAMPLE_S32BE:
79         case PA_SAMPLE_FLOAT32LE:
80         case PA_SAMPLE_FLOAT32BE:
81         case PA_SAMPLE_S24LE:
82         case PA_SAMPLE_S24BE:
83         case PA_SAMPLE_S24_32LE:
84         case PA_SAMPLE_S24_32BE:
85             return 0;
86         case PA_SAMPLE_ALAW:
87             return 0xd5;
88         case PA_SAMPLE_ULAW:
89             return 0xff;
90         default:
91             pa_assert_not_reached();
92     }
93 }
94
95 void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
96     pa_assert(p);
97     pa_assert(length > 0);
98     pa_assert(spec);
99
100     memset(p, silence_byte(spec->format), length);
101     return p;
102 }
103
104 size_t pa_frame_align(size_t l, const pa_sample_spec *ss) {
105     size_t fs;
106
107     pa_assert(ss);
108
109     fs = pa_frame_size(ss);
110
111     return (l/fs) * fs;
112 }
113
114 bool pa_frame_aligned(size_t l, const pa_sample_spec *ss) {
115     size_t fs;
116
117     pa_assert(ss);
118
119     fs = pa_frame_size(ss);
120
121     return l % fs == 0;
122 }
123
124 void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n) {
125     unsigned c;
126     size_t fs;
127
128     pa_assert(src);
129     pa_assert(channels > 0);
130     pa_assert(dst);
131     pa_assert(ss > 0);
132     pa_assert(n > 0);
133
134     fs = ss * channels;
135
136     for (c = 0; c < channels; c++) {
137         unsigned j;
138         void *d;
139         const void *s;
140
141         s = src[c];
142         d = (uint8_t*) dst + c * ss;
143
144         for (j = 0; j < n; j ++) {
145             memcpy(d, s, (int) ss);
146             s = (uint8_t*) s + ss;
147             d = (uint8_t*) d + fs;
148         }
149     }
150 }
151
152 void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n) {
153     size_t fs;
154     unsigned c;
155
156     pa_assert(src);
157     pa_assert(dst);
158     pa_assert(channels > 0);
159     pa_assert(ss > 0);
160     pa_assert(n > 0);
161
162     fs = ss * channels;
163
164     for (c = 0; c < channels; c++) {
165         unsigned j;
166         const void *s;
167         void *d;
168
169         s = (uint8_t*) src + c * ss;
170         d = dst[c];
171
172         for (j = 0; j < n; j ++) {
173             memcpy(d, s, (int) ss);
174             s = (uint8_t*) s + fs;
175             d = (uint8_t*) d + ss;
176         }
177     }
178 }
179
180 static pa_memblock *silence_memblock_new(pa_mempool *pool, uint8_t c) {
181     pa_memblock *b;
182     size_t length;
183     void *data;
184
185     pa_assert(pool);
186
187     length = PA_MIN(pa_mempool_block_size_max(pool), PA_SILENCE_MAX);
188
189     b = pa_memblock_new(pool, length);
190
191     data = pa_memblock_acquire(b);
192     memset(data, c, length);
193     pa_memblock_release(b);
194
195     pa_memblock_set_is_silence(b, true);
196
197     return b;
198 }
199
200 void pa_silence_cache_init(pa_silence_cache *cache) {
201     pa_assert(cache);
202
203     memset(cache, 0, sizeof(pa_silence_cache));
204 }
205
206 void pa_silence_cache_done(pa_silence_cache *cache) {
207     pa_sample_format_t f;
208     pa_assert(cache);
209
210     for (f = 0; f < PA_SAMPLE_MAX; f++)
211         if (cache->blocks[f])
212             pa_memblock_unref(cache->blocks[f]);
213
214     memset(cache, 0, sizeof(pa_silence_cache));
215 }
216
217 pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length) {
218     pa_memblock *b;
219     size_t l;
220
221     pa_assert(cache);
222     pa_assert(pa_sample_spec_valid(spec));
223
224     if (!(b = cache->blocks[spec->format]))
225
226         switch (spec->format) {
227             case PA_SAMPLE_U8:
228                 cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80);
229                 break;
230             case PA_SAMPLE_S16LE:
231             case PA_SAMPLE_S16BE:
232             case PA_SAMPLE_S32LE:
233             case PA_SAMPLE_S32BE:
234             case PA_SAMPLE_S24LE:
235             case PA_SAMPLE_S24BE:
236             case PA_SAMPLE_S24_32LE:
237             case PA_SAMPLE_S24_32BE:
238             case PA_SAMPLE_FLOAT32LE:
239             case PA_SAMPLE_FLOAT32BE:
240                 cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0);
241                 cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b);
242                 cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b);
243                 cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b);
244                 cache->blocks[PA_SAMPLE_S24LE] = pa_memblock_ref(b);
245                 cache->blocks[PA_SAMPLE_S24BE] = pa_memblock_ref(b);
246                 cache->blocks[PA_SAMPLE_S24_32LE] = pa_memblock_ref(b);
247                 cache->blocks[PA_SAMPLE_S24_32BE] = pa_memblock_ref(b);
248                 cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b);
249                 cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b);
250                 break;
251             case PA_SAMPLE_ALAW:
252                 cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5);
253                 break;
254             case PA_SAMPLE_ULAW:
255                 cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff);
256                 break;
257             default:
258                 pa_assert_not_reached();
259     }
260
261     pa_assert(b);
262
263     ret->memblock = pa_memblock_ref(b);
264
265     l = pa_memblock_get_length(b);
266     if (length > l || length == 0)
267         length = l;
268
269     ret->length = pa_frame_align(length, spec);
270     ret->index = 0;
271
272     return ret;
273 }
274
275 void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n) {
276     const float *s;
277     float *d;
278
279     s = src; d = dst;
280
281     if (format == PA_SAMPLE_FLOAT32NE) {
282         for (; n > 0; n--) {
283             float f;
284
285             f = *s;
286             *d = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);
287
288             s = (const float*) ((const uint8_t*) s + sstr);
289             d = (float*) ((uint8_t*) d + dstr);
290         }
291     } else {
292         pa_assert(format == PA_SAMPLE_FLOAT32RE);
293
294         for (; n > 0; n--) {
295             float f;
296
297             f = PA_READ_FLOAT32RE(s);
298             f = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);
299             PA_WRITE_FLOAT32RE(d, f);
300
301             s = (const float*) ((const uint8_t*) s + sstr);
302             d = (float*) ((uint8_t*) d + dstr);
303         }
304     }
305 }
306
307 /* Similar to pa_bytes_to_usec() but rounds up, not down */
308
309 pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec) {
310     size_t fs;
311     pa_usec_t usec;
312
313     pa_assert(spec);
314
315     fs = pa_frame_size(spec);
316     length = (length + fs - 1) / fs;
317
318     usec = (pa_usec_t) length * PA_USEC_PER_SEC;
319
320     return (usec + spec->rate - 1) / spec->rate;
321 }
322
323 /* Similar to pa_usec_to_bytes() but rounds up, not down */
324
325 size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) {
326     uint64_t u;
327     pa_assert(spec);
328
329     u = (uint64_t) t * (uint64_t) spec->rate;
330
331     u = (u + PA_USEC_PER_SEC - 1) / PA_USEC_PER_SEC;
332
333     u *= pa_frame_size(spec);
334
335     return (size_t) u;
336 }
337
338 void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
339     FILE *f;
340     void *p;
341
342     pa_assert(c);
343     pa_assert(fn);
344
345     /* Only for debugging purposes */
346
347     f = pa_fopen_cloexec(fn, "a");
348
349     if (!f) {
350         pa_log_warn("Failed to open '%s': %s", fn, pa_cstrerror(errno));
351         return;
352     }
353
354     p = pa_memblock_acquire(c->memblock);
355
356     if (fwrite((uint8_t*) p + c->index, 1, c->length, f) != c->length)
357         pa_log_warn("Failed to write to '%s': %s", fn, pa_cstrerror(errno));
358
359     pa_memblock_release(c->memblock);
360
361     fclose(f);
362 }
363
364 static void calc_sine(float *f, size_t l, double freq) {
365     size_t i;
366
367     l /= sizeof(float);
368
369     for (i = 0; i < l; i++)
370         *(f++) = (float) 0.5f * sin((double) i*M_PI*2*freq / (double) l);
371 }
372
373 void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq) {
374     size_t l;
375     unsigned gcd, n;
376     void *p;
377
378     pa_memchunk_reset(c);
379
380     gcd = pa_gcd(rate, freq);
381     n = rate / gcd;
382
383     l = pa_mempool_block_size_max(pool) / sizeof(float);
384
385     l /= n;
386     if (l <= 0) l = 1;
387     l *= n;
388
389     c->length = l * sizeof(float);
390     c->memblock = pa_memblock_new(pool, c->length);
391
392     p = pa_memblock_acquire(c->memblock);
393     calc_sine(p, c->length, freq * l / rate);
394     pa_memblock_release(c->memblock);
395 }
396
397 size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to) {
398     pa_usec_t usec;
399
400     pa_assert(from);
401     pa_assert(to);
402
403     usec = pa_bytes_to_usec_round_up(size, from);
404     return pa_usec_to_bytes_round_up(usec, to);
405 }