153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2004-2006 Lennart Poettering 553a5a1b3Sopenharmony_ci Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 953a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 1053a5a1b3Sopenharmony_ci or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1853a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <stdio.h> 2653a5a1b3Sopenharmony_ci#include <string.h> 2753a5a1b3Sopenharmony_ci 2853a5a1b3Sopenharmony_ci#include <pulse/timeval.h> 2953a5a1b3Sopenharmony_ci 3053a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 3153a5a1b3Sopenharmony_ci#include <pulsecore/i18n.h> 3253a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 3353a5a1b3Sopenharmony_ci 3453a5a1b3Sopenharmony_ci#include "sample.h" 3553a5a1b3Sopenharmony_ci 3653a5a1b3Sopenharmony_cistatic const size_t size_table[] = { 3753a5a1b3Sopenharmony_ci [PA_SAMPLE_U8] = 1, 3853a5a1b3Sopenharmony_ci [PA_SAMPLE_ULAW] = 1, 3953a5a1b3Sopenharmony_ci [PA_SAMPLE_ALAW] = 1, 4053a5a1b3Sopenharmony_ci [PA_SAMPLE_S16LE] = 2, 4153a5a1b3Sopenharmony_ci [PA_SAMPLE_S16BE] = 2, 4253a5a1b3Sopenharmony_ci [PA_SAMPLE_FLOAT32LE] = 4, 4353a5a1b3Sopenharmony_ci [PA_SAMPLE_FLOAT32BE] = 4, 4453a5a1b3Sopenharmony_ci [PA_SAMPLE_S32LE] = 4, 4553a5a1b3Sopenharmony_ci [PA_SAMPLE_S32BE] = 4, 4653a5a1b3Sopenharmony_ci [PA_SAMPLE_S24LE] = 3, 4753a5a1b3Sopenharmony_ci [PA_SAMPLE_S24BE] = 3, 4853a5a1b3Sopenharmony_ci [PA_SAMPLE_S24_32LE] = 4, 4953a5a1b3Sopenharmony_ci [PA_SAMPLE_S24_32BE] = 4 5053a5a1b3Sopenharmony_ci}; 5153a5a1b3Sopenharmony_ci 5253a5a1b3Sopenharmony_cisize_t pa_sample_size_of_format(pa_sample_format_t f) { 5353a5a1b3Sopenharmony_ci pa_assert(pa_sample_format_valid(f)); 5453a5a1b3Sopenharmony_ci 5553a5a1b3Sopenharmony_ci return size_table[f]; 5653a5a1b3Sopenharmony_ci} 5753a5a1b3Sopenharmony_ci 5853a5a1b3Sopenharmony_cisize_t pa_sample_size(const pa_sample_spec *spec) { 5953a5a1b3Sopenharmony_ci pa_assert(spec); 6053a5a1b3Sopenharmony_ci pa_assert(pa_sample_spec_valid(spec)); 6153a5a1b3Sopenharmony_ci 6253a5a1b3Sopenharmony_ci return size_table[spec->format]; 6353a5a1b3Sopenharmony_ci} 6453a5a1b3Sopenharmony_ci 6553a5a1b3Sopenharmony_cisize_t pa_frame_size(const pa_sample_spec *spec) { 6653a5a1b3Sopenharmony_ci pa_assert(spec); 6753a5a1b3Sopenharmony_ci pa_assert(pa_sample_spec_valid(spec)); 6853a5a1b3Sopenharmony_ci 6953a5a1b3Sopenharmony_ci return size_table[spec->format] * spec->channels; 7053a5a1b3Sopenharmony_ci} 7153a5a1b3Sopenharmony_ci 7253a5a1b3Sopenharmony_cisize_t pa_bytes_per_second(const pa_sample_spec *spec) { 7353a5a1b3Sopenharmony_ci pa_assert(spec); 7453a5a1b3Sopenharmony_ci pa_assert(pa_sample_spec_valid(spec)); 7553a5a1b3Sopenharmony_ci 7653a5a1b3Sopenharmony_ci return spec->rate * size_table[spec->format] * spec->channels; 7753a5a1b3Sopenharmony_ci} 7853a5a1b3Sopenharmony_ci 7953a5a1b3Sopenharmony_cipa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) { 8053a5a1b3Sopenharmony_ci pa_assert(spec); 8153a5a1b3Sopenharmony_ci pa_assert(pa_sample_spec_valid(spec)); 8253a5a1b3Sopenharmony_ci 8353a5a1b3Sopenharmony_ci return (((pa_usec_t) (length / (size_table[spec->format] * spec->channels)) * PA_USEC_PER_SEC) / spec->rate); 8453a5a1b3Sopenharmony_ci} 8553a5a1b3Sopenharmony_ci 8653a5a1b3Sopenharmony_cisize_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) { 8753a5a1b3Sopenharmony_ci pa_assert(spec); 8853a5a1b3Sopenharmony_ci pa_assert(pa_sample_spec_valid(spec)); 8953a5a1b3Sopenharmony_ci 9053a5a1b3Sopenharmony_ci return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * (size_table[spec->format] * spec->channels); 9153a5a1b3Sopenharmony_ci} 9253a5a1b3Sopenharmony_ci 9353a5a1b3Sopenharmony_cipa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec) { 9453a5a1b3Sopenharmony_ci pa_assert(spec); 9553a5a1b3Sopenharmony_ci 9653a5a1b3Sopenharmony_ci spec->format = PA_SAMPLE_INVALID; 9753a5a1b3Sopenharmony_ci spec->rate = 0; 9853a5a1b3Sopenharmony_ci spec->channels = 0; 9953a5a1b3Sopenharmony_ci 10053a5a1b3Sopenharmony_ci return spec; 10153a5a1b3Sopenharmony_ci} 10253a5a1b3Sopenharmony_ci 10353a5a1b3Sopenharmony_ciint pa_sample_format_valid(unsigned format) { 10453a5a1b3Sopenharmony_ci return format < PA_SAMPLE_MAX; 10553a5a1b3Sopenharmony_ci} 10653a5a1b3Sopenharmony_ci 10753a5a1b3Sopenharmony_ciint pa_sample_rate_valid(uint32_t rate) { 10853a5a1b3Sopenharmony_ci /* The extra 1% is due to module-loopback: it temporarily sets 10953a5a1b3Sopenharmony_ci * a higher-than-nominal rate to get rid of excessive buffer 11053a5a1b3Sopenharmony_ci * latency */ 11153a5a1b3Sopenharmony_ci return rate > 0 && rate <= PA_RATE_MAX * 101 / 100; 11253a5a1b3Sopenharmony_ci} 11353a5a1b3Sopenharmony_ci 11453a5a1b3Sopenharmony_ciint pa_channels_valid(uint8_t channels) { 11553a5a1b3Sopenharmony_ci return channels > 0 && channels <= PA_CHANNELS_MAX; 11653a5a1b3Sopenharmony_ci} 11753a5a1b3Sopenharmony_ci 11853a5a1b3Sopenharmony_ciint pa_sample_spec_valid(const pa_sample_spec *spec) { 11953a5a1b3Sopenharmony_ci pa_assert(spec); 12053a5a1b3Sopenharmony_ci 12153a5a1b3Sopenharmony_ci if (PA_UNLIKELY(!pa_sample_rate_valid(spec->rate) || 12253a5a1b3Sopenharmony_ci !pa_channels_valid(spec->channels) || 12353a5a1b3Sopenharmony_ci !pa_sample_format_valid(spec->format))) 12453a5a1b3Sopenharmony_ci return 0; 12553a5a1b3Sopenharmony_ci 12653a5a1b3Sopenharmony_ci return 1; 12753a5a1b3Sopenharmony_ci} 12853a5a1b3Sopenharmony_ci 12953a5a1b3Sopenharmony_ciint pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) { 13053a5a1b3Sopenharmony_ci pa_assert(a); 13153a5a1b3Sopenharmony_ci pa_assert(b); 13253a5a1b3Sopenharmony_ci 13353a5a1b3Sopenharmony_ci pa_return_val_if_fail(pa_sample_spec_valid(a), 0); 13453a5a1b3Sopenharmony_ci 13553a5a1b3Sopenharmony_ci if (PA_UNLIKELY(a == b)) 13653a5a1b3Sopenharmony_ci return 1; 13753a5a1b3Sopenharmony_ci 13853a5a1b3Sopenharmony_ci pa_return_val_if_fail(pa_sample_spec_valid(b), 0); 13953a5a1b3Sopenharmony_ci 14053a5a1b3Sopenharmony_ci return 14153a5a1b3Sopenharmony_ci (a->format == b->format) && 14253a5a1b3Sopenharmony_ci (a->rate == b->rate) && 14353a5a1b3Sopenharmony_ci (a->channels == b->channels); 14453a5a1b3Sopenharmony_ci} 14553a5a1b3Sopenharmony_ci 14653a5a1b3Sopenharmony_ciconst char *pa_sample_format_to_string(pa_sample_format_t f) { 14753a5a1b3Sopenharmony_ci static const char* const table[]= { 14853a5a1b3Sopenharmony_ci [PA_SAMPLE_U8] = "u8", 14953a5a1b3Sopenharmony_ci [PA_SAMPLE_ALAW] = "aLaw", 15053a5a1b3Sopenharmony_ci [PA_SAMPLE_ULAW] = "uLaw", 15153a5a1b3Sopenharmony_ci [PA_SAMPLE_S16LE] = "s16le", 15253a5a1b3Sopenharmony_ci [PA_SAMPLE_S16BE] = "s16be", 15353a5a1b3Sopenharmony_ci [PA_SAMPLE_FLOAT32LE] = "float32le", 15453a5a1b3Sopenharmony_ci [PA_SAMPLE_FLOAT32BE] = "float32be", 15553a5a1b3Sopenharmony_ci [PA_SAMPLE_S32LE] = "s32le", 15653a5a1b3Sopenharmony_ci [PA_SAMPLE_S32BE] = "s32be", 15753a5a1b3Sopenharmony_ci [PA_SAMPLE_S24LE] = "s24le", 15853a5a1b3Sopenharmony_ci [PA_SAMPLE_S24BE] = "s24be", 15953a5a1b3Sopenharmony_ci [PA_SAMPLE_S24_32LE] = "s24-32le", 16053a5a1b3Sopenharmony_ci [PA_SAMPLE_S24_32BE] = "s24-32be", 16153a5a1b3Sopenharmony_ci }; 16253a5a1b3Sopenharmony_ci 16353a5a1b3Sopenharmony_ci if (!pa_sample_format_valid(f)) 16453a5a1b3Sopenharmony_ci return NULL; 16553a5a1b3Sopenharmony_ci 16653a5a1b3Sopenharmony_ci return table[f]; 16753a5a1b3Sopenharmony_ci} 16853a5a1b3Sopenharmony_ci 16953a5a1b3Sopenharmony_cichar *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) { 17053a5a1b3Sopenharmony_ci pa_assert(s); 17153a5a1b3Sopenharmony_ci pa_assert(l > 0); 17253a5a1b3Sopenharmony_ci pa_assert(spec); 17353a5a1b3Sopenharmony_ci 17453a5a1b3Sopenharmony_ci pa_init_i18n(); 17553a5a1b3Sopenharmony_ci 17653a5a1b3Sopenharmony_ci if (!pa_sample_spec_valid(spec)) 17753a5a1b3Sopenharmony_ci pa_snprintf(s, l, _("(invalid)")); 17853a5a1b3Sopenharmony_ci else 17953a5a1b3Sopenharmony_ci pa_snprintf(s, l, _("%s %uch %uHz"), pa_sample_format_to_string(spec->format), spec->channels, spec->rate); 18053a5a1b3Sopenharmony_ci 18153a5a1b3Sopenharmony_ci return s; 18253a5a1b3Sopenharmony_ci} 18353a5a1b3Sopenharmony_ci 18453a5a1b3Sopenharmony_cichar* pa_bytes_snprint(char *s, size_t l, unsigned v) { 18553a5a1b3Sopenharmony_ci pa_assert(s); 18653a5a1b3Sopenharmony_ci pa_assert(l > 0); 18753a5a1b3Sopenharmony_ci 18853a5a1b3Sopenharmony_ci pa_init_i18n(); 18953a5a1b3Sopenharmony_ci 19053a5a1b3Sopenharmony_ci if (v >= ((unsigned) 1024)*1024*1024) 19153a5a1b3Sopenharmony_ci pa_snprintf(s, l, _("%0.1f GiB"), ((double) v)/1024/1024/1024); 19253a5a1b3Sopenharmony_ci else if (v >= ((unsigned) 1024)*1024) 19353a5a1b3Sopenharmony_ci pa_snprintf(s, l, _("%0.1f MiB"), ((double) v)/1024/1024); 19453a5a1b3Sopenharmony_ci else if (v >= (unsigned) 1024) 19553a5a1b3Sopenharmony_ci pa_snprintf(s, l, _("%0.1f KiB"), ((double) v)/1024); 19653a5a1b3Sopenharmony_ci else 19753a5a1b3Sopenharmony_ci pa_snprintf(s, l, _("%u B"), (unsigned) v); 19853a5a1b3Sopenharmony_ci 19953a5a1b3Sopenharmony_ci return s; 20053a5a1b3Sopenharmony_ci} 20153a5a1b3Sopenharmony_ci 20253a5a1b3Sopenharmony_cipa_sample_format_t pa_parse_sample_format(const char *format) { 20353a5a1b3Sopenharmony_ci pa_assert(format); 20453a5a1b3Sopenharmony_ci 20553a5a1b3Sopenharmony_ci if (strcasecmp(format, "s16le") == 0) 20653a5a1b3Sopenharmony_ci return PA_SAMPLE_S16LE; 20753a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s16be") == 0) 20853a5a1b3Sopenharmony_ci return PA_SAMPLE_S16BE; 20953a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s16ne") == 0 || strcasecmp(format, "s16") == 0 || strcasecmp(format, "16") == 0) 21053a5a1b3Sopenharmony_ci return PA_SAMPLE_S16NE; 21153a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s16re") == 0) 21253a5a1b3Sopenharmony_ci return PA_SAMPLE_S16RE; 21353a5a1b3Sopenharmony_ci else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0) 21453a5a1b3Sopenharmony_ci return PA_SAMPLE_U8; 21553a5a1b3Sopenharmony_ci else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0 || strcasecmp(format, "float") == 0) 21653a5a1b3Sopenharmony_ci return PA_SAMPLE_FLOAT32NE; 21753a5a1b3Sopenharmony_ci else if (strcasecmp(format, "float32re") == 0) 21853a5a1b3Sopenharmony_ci return PA_SAMPLE_FLOAT32RE; 21953a5a1b3Sopenharmony_ci else if (strcasecmp(format, "float32le") == 0) 22053a5a1b3Sopenharmony_ci return PA_SAMPLE_FLOAT32LE; 22153a5a1b3Sopenharmony_ci else if (strcasecmp(format, "float32be") == 0) 22253a5a1b3Sopenharmony_ci return PA_SAMPLE_FLOAT32BE; 22353a5a1b3Sopenharmony_ci else if (strcasecmp(format, "ulaw") == 0 || strcasecmp(format, "mulaw") == 0) 22453a5a1b3Sopenharmony_ci return PA_SAMPLE_ULAW; 22553a5a1b3Sopenharmony_ci else if (strcasecmp(format, "alaw") == 0) 22653a5a1b3Sopenharmony_ci return PA_SAMPLE_ALAW; 22753a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s32le") == 0) 22853a5a1b3Sopenharmony_ci return PA_SAMPLE_S32LE; 22953a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s32be") == 0) 23053a5a1b3Sopenharmony_ci return PA_SAMPLE_S32BE; 23153a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s32ne") == 0 || strcasecmp(format, "s32") == 0 || strcasecmp(format, "32") == 0) 23253a5a1b3Sopenharmony_ci return PA_SAMPLE_S32NE; 23353a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s32re") == 0) 23453a5a1b3Sopenharmony_ci return PA_SAMPLE_S24RE; 23553a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s24le") == 0) 23653a5a1b3Sopenharmony_ci return PA_SAMPLE_S24LE; 23753a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s24be") == 0) 23853a5a1b3Sopenharmony_ci return PA_SAMPLE_S24BE; 23953a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s24ne") == 0 || strcasecmp(format, "s24") == 0 || strcasecmp(format, "24") == 0) 24053a5a1b3Sopenharmony_ci return PA_SAMPLE_S24NE; 24153a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s24re") == 0) 24253a5a1b3Sopenharmony_ci return PA_SAMPLE_S24RE; 24353a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s24-32le") == 0) 24453a5a1b3Sopenharmony_ci return PA_SAMPLE_S24_32LE; 24553a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s24-32be") == 0) 24653a5a1b3Sopenharmony_ci return PA_SAMPLE_S24_32BE; 24753a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s24-32ne") == 0 || strcasecmp(format, "s24-32") == 0) 24853a5a1b3Sopenharmony_ci return PA_SAMPLE_S24_32NE; 24953a5a1b3Sopenharmony_ci else if (strcasecmp(format, "s24-32re") == 0) 25053a5a1b3Sopenharmony_ci return PA_SAMPLE_S24_32RE; 25153a5a1b3Sopenharmony_ci 25253a5a1b3Sopenharmony_ci return PA_SAMPLE_INVALID; 25353a5a1b3Sopenharmony_ci} 25453a5a1b3Sopenharmony_ci 25553a5a1b3Sopenharmony_ciint pa_sample_format_is_le(pa_sample_format_t f) { 25653a5a1b3Sopenharmony_ci pa_assert(pa_sample_format_valid(f)); 25753a5a1b3Sopenharmony_ci 25853a5a1b3Sopenharmony_ci switch (f) { 25953a5a1b3Sopenharmony_ci case PA_SAMPLE_S16LE: 26053a5a1b3Sopenharmony_ci case PA_SAMPLE_S24LE: 26153a5a1b3Sopenharmony_ci case PA_SAMPLE_S32LE: 26253a5a1b3Sopenharmony_ci case PA_SAMPLE_S24_32LE: 26353a5a1b3Sopenharmony_ci case PA_SAMPLE_FLOAT32LE: 26453a5a1b3Sopenharmony_ci return 1; 26553a5a1b3Sopenharmony_ci 26653a5a1b3Sopenharmony_ci case PA_SAMPLE_S16BE: 26753a5a1b3Sopenharmony_ci case PA_SAMPLE_S24BE: 26853a5a1b3Sopenharmony_ci case PA_SAMPLE_S32BE: 26953a5a1b3Sopenharmony_ci case PA_SAMPLE_S24_32BE: 27053a5a1b3Sopenharmony_ci case PA_SAMPLE_FLOAT32BE: 27153a5a1b3Sopenharmony_ci return 0; 27253a5a1b3Sopenharmony_ci 27353a5a1b3Sopenharmony_ci default: 27453a5a1b3Sopenharmony_ci return -1; 27553a5a1b3Sopenharmony_ci } 27653a5a1b3Sopenharmony_ci} 27753a5a1b3Sopenharmony_ci 27853a5a1b3Sopenharmony_ciint pa_sample_format_is_be(pa_sample_format_t f) { 27953a5a1b3Sopenharmony_ci int r; 28053a5a1b3Sopenharmony_ci 28153a5a1b3Sopenharmony_ci if ((r = pa_sample_format_is_le(f)) < 0) 28253a5a1b3Sopenharmony_ci return r; 28353a5a1b3Sopenharmony_ci 28453a5a1b3Sopenharmony_ci return !r; 28553a5a1b3Sopenharmony_ci} 286