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 44pa_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 57pa_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 71static 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 95void* 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 104size_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 114bool 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 124void 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 152void 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 180static 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 200void pa_silence_cache_init(pa_silence_cache *cache) { 201 pa_assert(cache); 202 203 memset(cache, 0, sizeof(pa_silence_cache)); 204} 205 206void 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 217pa_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 275void 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 309pa_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 325size_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 338void 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 364static 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 373void 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 397size_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