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, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 #include <pulse/timeval.h>
35 #include <pulsecore/log.h>
36 #include <pulsecore/core-error.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/g711.h>
39 #include <pulsecore/core-util.h>
40 #include <pulsecore/endianmacros.h>
42 #include "sample-util.h"
44 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
46 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
52 data
= pa_memblock_acquire(b
);
53 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
54 pa_memblock_release(b
);
59 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
63 pa_assert(c
->memblock
);
66 data
= pa_memblock_acquire(c
->memblock
);
67 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
68 pa_memblock_release(c
->memblock
);
73 static uint8_t silence_byte(pa_sample_format_t format
) {
81 case PA_SAMPLE_FLOAT32LE
:
82 case PA_SAMPLE_FLOAT32BE
:
85 case PA_SAMPLE_S24_32LE
:
86 case PA_SAMPLE_S24_32BE
:
93 pa_assert_not_reached();
97 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
99 pa_assert(length
> 0);
102 memset(p
, silence_byte(spec
->format
), length
);
106 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
111 fs
= pa_frame_size(ss
);
116 bool pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
121 fs
= pa_frame_size(ss
);
126 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
131 pa_assert(channels
> 0);
138 for (c
= 0; c
< channels
; c
++) {
144 d
= (uint8_t*) dst
+ c
* ss
;
146 for (j
= 0; j
< n
; j
++) {
147 memcpy(d
, s
, (int) ss
);
148 s
= (uint8_t*) s
+ ss
;
149 d
= (uint8_t*) d
+ fs
;
154 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
160 pa_assert(channels
> 0);
166 for (c
= 0; c
< channels
; c
++) {
171 s
= (uint8_t*) src
+ c
* ss
;
174 for (j
= 0; j
< n
; j
++) {
175 memcpy(d
, s
, (int) ss
);
176 s
= (uint8_t*) s
+ fs
;
177 d
= (uint8_t*) d
+ ss
;
182 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
189 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
191 b
= pa_memblock_new(pool
, length
);
193 data
= pa_memblock_acquire(b
);
194 memset(data
, c
, length
);
195 pa_memblock_release(b
);
197 pa_memblock_set_is_silence(b
, true);
202 void pa_silence_cache_init(pa_silence_cache
*cache
) {
205 memset(cache
, 0, sizeof(pa_silence_cache
));
208 void pa_silence_cache_done(pa_silence_cache
*cache
) {
209 pa_sample_format_t f
;
212 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
213 if (cache
->blocks
[f
])
214 pa_memblock_unref(cache
->blocks
[f
]);
216 memset(cache
, 0, sizeof(pa_silence_cache
));
219 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
224 pa_assert(pa_sample_spec_valid(spec
));
226 if (!(b
= cache
->blocks
[spec
->format
]))
228 switch (spec
->format
) {
230 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
232 case PA_SAMPLE_S16LE
:
233 case PA_SAMPLE_S16BE
:
234 case PA_SAMPLE_S32LE
:
235 case PA_SAMPLE_S32BE
:
236 case PA_SAMPLE_S24LE
:
237 case PA_SAMPLE_S24BE
:
238 case PA_SAMPLE_S24_32LE
:
239 case PA_SAMPLE_S24_32BE
:
240 case PA_SAMPLE_FLOAT32LE
:
241 case PA_SAMPLE_FLOAT32BE
:
242 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
243 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
244 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
245 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
246 cache
->blocks
[PA_SAMPLE_S24LE
] = pa_memblock_ref(b
);
247 cache
->blocks
[PA_SAMPLE_S24BE
] = pa_memblock_ref(b
);
248 cache
->blocks
[PA_SAMPLE_S24_32LE
] = pa_memblock_ref(b
);
249 cache
->blocks
[PA_SAMPLE_S24_32BE
] = pa_memblock_ref(b
);
250 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
251 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
254 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
257 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
260 pa_assert_not_reached();
265 ret
->memblock
= pa_memblock_ref(b
);
267 l
= pa_memblock_get_length(b
);
268 if (length
> l
|| length
== 0)
271 ret
->length
= pa_frame_align(length
, spec
);
277 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
283 if (format
== PA_SAMPLE_FLOAT32NE
) {
288 *d
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
290 s
= (const float*) ((const uint8_t*) s
+ sstr
);
291 d
= (float*) ((uint8_t*) d
+ dstr
);
294 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
299 f
= PA_FLOAT32_SWAP(*s
);
300 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
301 *d
= PA_FLOAT32_SWAP(f
);
303 s
= (const float*) ((const uint8_t*) s
+ sstr
);
304 d
= (float*) ((uint8_t*) d
+ dstr
);
309 /* Similar to pa_bytes_to_usec() but rounds up, not down */
311 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
317 fs
= pa_frame_size(spec
);
318 length
= (length
+ fs
- 1) / fs
;
320 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
322 return (usec
+ spec
->rate
- 1) / spec
->rate
;
325 /* Similar to pa_usec_to_bytes() but rounds up, not down */
327 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
331 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
333 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
335 u
*= pa_frame_size(spec
);
340 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
347 /* Only for debugging purposes */
349 f
= pa_fopen_cloexec(fn
, "a");
352 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
356 p
= pa_memblock_acquire(c
->memblock
);
358 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
359 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
361 pa_memblock_release(c
->memblock
);
366 static void calc_sine(float *f
, size_t l
, double freq
) {
371 for (i
= 0; i
< l
; i
++)
372 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
375 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
380 pa_memchunk_reset(c
);
382 gcd
= pa_gcd(rate
, freq
);
385 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
391 c
->length
= l
* sizeof(float);
392 c
->memblock
= pa_memblock_new(pool
, c
->length
);
394 p
= pa_memblock_acquire(c
->memblock
);
395 calc_sine(p
, c
->length
, freq
* l
/ rate
);
396 pa_memblock_release(c
->memblock
);
399 size_t pa_convert_size(size_t size
, const pa_sample_spec
*from
, const pa_sample_spec
*to
) {
405 usec
= pa_bytes_to_usec_round_up(size
, from
);
406 return pa_usec_to_bytes_round_up(usec
, to
);