• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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