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
pa_silence_memblock(pa_memblock * b,const pa_sample_spec * spec)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
pa_silence_memchunk(pa_memchunk * c,const pa_sample_spec * spec)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
silence_byte(pa_sample_format_t format)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
pa_silence_memory(void * p,size_t length,const pa_sample_spec * spec)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
pa_frame_align(size_t l,const pa_sample_spec * ss)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
pa_frame_aligned(size_t l,const pa_sample_spec * ss)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
pa_interleave(const void * src[],unsigned channels,void * dst,size_t ss,unsigned n)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
pa_deinterleave(const void * src,void * dst[],unsigned channels,size_t ss,unsigned n)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
silence_memblock_new(pa_mempool * pool,uint8_t c)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
pa_silence_cache_init(pa_silence_cache * cache)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
pa_silence_cache_done(pa_silence_cache * cache)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
pa_silence_memchunk_get(pa_silence_cache * cache,pa_mempool * pool,pa_memchunk * ret,const pa_sample_spec * spec,size_t length)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
pa_sample_clamp(pa_sample_format_t format,void * dst,size_t dstr,const void * src,size_t sstr,unsigned n)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
pa_bytes_to_usec_round_up(uint64_t length,const pa_sample_spec * spec)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
pa_usec_to_bytes_round_up(pa_usec_t t,const pa_sample_spec * spec)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
pa_memchunk_dump_to_file(pa_memchunk * c,const char * fn)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
calc_sine(float * f,size_t l,double freq)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
pa_memchunk_sine(pa_memchunk * c,pa_mempool * pool,unsigned rate,unsigned freq)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
pa_convert_size(size_t size,const pa_sample_spec * from,const pa_sample_spec * to)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 }
406