2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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/>.
31 #include <pulse/timeval.h>
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>
40 #include "sample-util.h"
42 #define PA_SILENCE_MAX (pa_page_size()*16)
44 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
50 data = pa_memblock_acquire(b);
51 pa_silence_memory(data, pa_memblock_get_length(b), spec);
52 pa_memblock_release(b);
57 pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
61 pa_assert(c->memblock);
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);
71 static uint8_t silence_byte(pa_sample_format_t format) {
79 case PA_SAMPLE_FLOAT32LE:
80 case PA_SAMPLE_FLOAT32BE:
83 case PA_SAMPLE_S24_32LE:
84 case PA_SAMPLE_S24_32BE:
91 pa_assert_not_reached();
95 void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
97 pa_assert(length > 0);
100 memset(p, silence_byte(spec->format), length);
104 size_t pa_frame_align(size_t l, const pa_sample_spec *ss) {
109 fs = pa_frame_size(ss);
114 bool pa_frame_aligned(size_t l, const pa_sample_spec *ss) {
119 fs = pa_frame_size(ss);
124 void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n) {
129 pa_assert(channels > 0);
136 for (c = 0; c < channels; c++) {
142 d = (uint8_t*) dst + c * ss;
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;
152 void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n) {
158 pa_assert(channels > 0);
164 for (c = 0; c < channels; c++) {
169 s = (uint8_t*) src + c * ss;
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;
180 static pa_memblock *silence_memblock_new(pa_mempool *pool, uint8_t c) {
187 length = PA_MIN(pa_mempool_block_size_max(pool), PA_SILENCE_MAX);
189 b = pa_memblock_new(pool, length);
191 data = pa_memblock_acquire(b);
192 memset(data, c, length);
193 pa_memblock_release(b);
195 pa_memblock_set_is_silence(b, true);
200 void pa_silence_cache_init(pa_silence_cache *cache) {
203 memset(cache, 0, sizeof(pa_silence_cache));
206 void pa_silence_cache_done(pa_silence_cache *cache) {
207 pa_sample_format_t f;
210 for (f = 0; f < PA_SAMPLE_MAX; f++)
211 if (cache->blocks[f])
212 pa_memblock_unref(cache->blocks[f]);
214 memset(cache, 0, sizeof(pa_silence_cache));
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) {
222 pa_assert(pa_sample_spec_valid(spec));
224 if (!(b = cache->blocks[spec->format]))
226 switch (spec->format) {
228 cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80);
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);
252 cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5);
255 cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff);
258 pa_assert_not_reached();
263 ret->memblock = pa_memblock_ref(b);
265 l = pa_memblock_get_length(b);
266 if (length > l || length == 0)
269 ret->length = pa_frame_align(length, spec);
275 void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n) {
281 if (format == PA_SAMPLE_FLOAT32NE) {
286 *d = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);
288 s = (const float*) ((const uint8_t*) s + sstr);
289 d = (float*) ((uint8_t*) d + dstr);
292 pa_assert(format == PA_SAMPLE_FLOAT32RE);
297 f = PA_READ_FLOAT32RE(s);
298 f = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);
299 PA_WRITE_FLOAT32RE(d, f);
301 s = (const float*) ((const uint8_t*) s + sstr);
302 d = (float*) ((uint8_t*) d + dstr);
307 /* Similar to pa_bytes_to_usec() but rounds up, not down */
309 pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec) {
315 fs = pa_frame_size(spec);
316 length = (length + fs - 1) / fs;
318 usec = (pa_usec_t) length * PA_USEC_PER_SEC;
320 return (usec + spec->rate - 1) / spec->rate;
323 /* Similar to pa_usec_to_bytes() but rounds up, not down */
325 size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) {
329 u = (uint64_t) t * (uint64_t) spec->rate;
331 u = (u + PA_USEC_PER_SEC - 1) / PA_USEC_PER_SEC;
333 u *= pa_frame_size(spec);
338 void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
345 /* Only for debugging purposes */
347 f = pa_fopen_cloexec(fn, "a");
350 pa_log_warn("Failed to open '%s': %s", fn, pa_cstrerror(errno));
354 p = pa_memblock_acquire(c->memblock);
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));
359 pa_memblock_release(c->memblock);
364 static void calc_sine(float *f, size_t l, double freq) {
369 for (i = 0; i < l; i++)
370 *(f++) = (float) 0.5f * sin((double) i*M_PI*2*freq / (double) l);
373 void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq) {
378 pa_memchunk_reset(c);
380 gcd = pa_gcd(rate, freq);
383 l = pa_mempool_block_size_max(pool) / sizeof(float);
389 c->length = l * sizeof(float);
390 c->memblock = pa_memblock_new(pool, c->length);
392 p = pa_memblock_acquire(c->memblock);
393 calc_sine(p, c->length, freq * l / rate);
394 pa_memblock_release(c->memblock);
397 size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to) {
403 usec = pa_bytes_to_usec_round_up(size, from);
404 return pa_usec_to_bytes_round_up(usec, to);