xref: /third_party/pulseaudio/src/pulse/sample.c (revision 53a5a1b3)
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 <stdio.h>
26#include <string.h>
27
28#include <pulse/timeval.h>
29
30#include <pulsecore/core-util.h>
31#include <pulsecore/i18n.h>
32#include <pulsecore/macro.h>
33
34#include "sample.h"
35
36static const size_t size_table[] = {
37    [PA_SAMPLE_U8] = 1,
38    [PA_SAMPLE_ULAW] = 1,
39    [PA_SAMPLE_ALAW] = 1,
40    [PA_SAMPLE_S16LE] = 2,
41    [PA_SAMPLE_S16BE] = 2,
42    [PA_SAMPLE_FLOAT32LE] = 4,
43    [PA_SAMPLE_FLOAT32BE] = 4,
44    [PA_SAMPLE_S32LE] = 4,
45    [PA_SAMPLE_S32BE] = 4,
46    [PA_SAMPLE_S24LE] = 3,
47    [PA_SAMPLE_S24BE] = 3,
48    [PA_SAMPLE_S24_32LE] = 4,
49    [PA_SAMPLE_S24_32BE] = 4
50};
51
52size_t pa_sample_size_of_format(pa_sample_format_t f) {
53    pa_assert(pa_sample_format_valid(f));
54
55    return size_table[f];
56}
57
58size_t pa_sample_size(const pa_sample_spec *spec) {
59    pa_assert(spec);
60    pa_assert(pa_sample_spec_valid(spec));
61
62    return size_table[spec->format];
63}
64
65size_t pa_frame_size(const pa_sample_spec *spec) {
66    pa_assert(spec);
67    pa_assert(pa_sample_spec_valid(spec));
68
69    return size_table[spec->format] * spec->channels;
70}
71
72size_t pa_bytes_per_second(const pa_sample_spec *spec) {
73    pa_assert(spec);
74    pa_assert(pa_sample_spec_valid(spec));
75
76    return spec->rate * size_table[spec->format] * spec->channels;
77}
78
79pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
80    pa_assert(spec);
81    pa_assert(pa_sample_spec_valid(spec));
82
83    return (((pa_usec_t) (length / (size_table[spec->format] * spec->channels)) * PA_USEC_PER_SEC) / spec->rate);
84}
85
86size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
87    pa_assert(spec);
88    pa_assert(pa_sample_spec_valid(spec));
89
90    return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * (size_table[spec->format] * spec->channels);
91}
92
93pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec) {
94    pa_assert(spec);
95
96    spec->format = PA_SAMPLE_INVALID;
97    spec->rate = 0;
98    spec->channels = 0;
99
100    return spec;
101}
102
103int pa_sample_format_valid(unsigned format) {
104    return format < PA_SAMPLE_MAX;
105}
106
107int pa_sample_rate_valid(uint32_t rate) {
108    /* The extra 1% is due to module-loopback: it temporarily sets
109     * a higher-than-nominal rate to get rid of excessive buffer
110     * latency */
111    return rate > 0 && rate <= PA_RATE_MAX * 101 / 100;
112}
113
114int pa_channels_valid(uint8_t channels) {
115    return channels > 0 && channels <= PA_CHANNELS_MAX;
116}
117
118int pa_sample_spec_valid(const pa_sample_spec *spec) {
119    pa_assert(spec);
120
121    if (PA_UNLIKELY(!pa_sample_rate_valid(spec->rate) ||
122        !pa_channels_valid(spec->channels) ||
123        !pa_sample_format_valid(spec->format)))
124        return 0;
125
126    return 1;
127}
128
129int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) {
130    pa_assert(a);
131    pa_assert(b);
132
133    pa_return_val_if_fail(pa_sample_spec_valid(a), 0);
134
135    if (PA_UNLIKELY(a == b))
136        return 1;
137
138    pa_return_val_if_fail(pa_sample_spec_valid(b), 0);
139
140    return
141        (a->format == b->format) &&
142        (a->rate == b->rate) &&
143        (a->channels == b->channels);
144}
145
146const char *pa_sample_format_to_string(pa_sample_format_t f) {
147    static const char* const table[]= {
148        [PA_SAMPLE_U8] = "u8",
149        [PA_SAMPLE_ALAW] = "aLaw",
150        [PA_SAMPLE_ULAW] = "uLaw",
151        [PA_SAMPLE_S16LE] = "s16le",
152        [PA_SAMPLE_S16BE] = "s16be",
153        [PA_SAMPLE_FLOAT32LE] = "float32le",
154        [PA_SAMPLE_FLOAT32BE] = "float32be",
155        [PA_SAMPLE_S32LE] = "s32le",
156        [PA_SAMPLE_S32BE] = "s32be",
157        [PA_SAMPLE_S24LE] = "s24le",
158        [PA_SAMPLE_S24BE] = "s24be",
159        [PA_SAMPLE_S24_32LE] = "s24-32le",
160        [PA_SAMPLE_S24_32BE] = "s24-32be",
161    };
162
163    if (!pa_sample_format_valid(f))
164        return NULL;
165
166    return table[f];
167}
168
169char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
170    pa_assert(s);
171    pa_assert(l > 0);
172    pa_assert(spec);
173
174    pa_init_i18n();
175
176    if (!pa_sample_spec_valid(spec))
177        pa_snprintf(s, l, _("(invalid)"));
178    else
179        pa_snprintf(s, l, _("%s %uch %uHz"), pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
180
181    return s;
182}
183
184char* pa_bytes_snprint(char *s, size_t l, unsigned v) {
185    pa_assert(s);
186    pa_assert(l > 0);
187
188    pa_init_i18n();
189
190    if (v >= ((unsigned) 1024)*1024*1024)
191        pa_snprintf(s, l, _("%0.1f GiB"), ((double) v)/1024/1024/1024);
192    else if (v >= ((unsigned) 1024)*1024)
193        pa_snprintf(s, l, _("%0.1f MiB"), ((double) v)/1024/1024);
194    else if (v >= (unsigned) 1024)
195        pa_snprintf(s, l, _("%0.1f KiB"), ((double) v)/1024);
196    else
197        pa_snprintf(s, l, _("%u B"), (unsigned) v);
198
199    return s;
200}
201
202pa_sample_format_t pa_parse_sample_format(const char *format) {
203    pa_assert(format);
204
205    if (strcasecmp(format, "s16le") == 0)
206        return PA_SAMPLE_S16LE;
207    else if (strcasecmp(format, "s16be") == 0)
208        return PA_SAMPLE_S16BE;
209    else if (strcasecmp(format, "s16ne") == 0 || strcasecmp(format, "s16") == 0 || strcasecmp(format, "16") == 0)
210        return PA_SAMPLE_S16NE;
211    else if (strcasecmp(format, "s16re") == 0)
212        return PA_SAMPLE_S16RE;
213    else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0)
214        return PA_SAMPLE_U8;
215    else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0 || strcasecmp(format, "float") == 0)
216        return PA_SAMPLE_FLOAT32NE;
217    else if (strcasecmp(format, "float32re") == 0)
218        return PA_SAMPLE_FLOAT32RE;
219    else if (strcasecmp(format, "float32le") == 0)
220        return PA_SAMPLE_FLOAT32LE;
221    else if (strcasecmp(format, "float32be") == 0)
222        return PA_SAMPLE_FLOAT32BE;
223    else if (strcasecmp(format, "ulaw") == 0 || strcasecmp(format, "mulaw") == 0)
224        return PA_SAMPLE_ULAW;
225    else if (strcasecmp(format, "alaw") == 0)
226        return PA_SAMPLE_ALAW;
227    else if (strcasecmp(format, "s32le") == 0)
228        return PA_SAMPLE_S32LE;
229    else if (strcasecmp(format, "s32be") == 0)
230        return PA_SAMPLE_S32BE;
231    else if (strcasecmp(format, "s32ne") == 0 || strcasecmp(format, "s32") == 0 || strcasecmp(format, "32") == 0)
232        return PA_SAMPLE_S32NE;
233    else if (strcasecmp(format, "s32re") == 0)
234        return PA_SAMPLE_S24RE;
235    else if (strcasecmp(format, "s24le") == 0)
236        return PA_SAMPLE_S24LE;
237    else if (strcasecmp(format, "s24be") == 0)
238        return PA_SAMPLE_S24BE;
239    else if (strcasecmp(format, "s24ne") == 0 || strcasecmp(format, "s24") == 0 || strcasecmp(format, "24") == 0)
240        return PA_SAMPLE_S24NE;
241    else if (strcasecmp(format, "s24re") == 0)
242        return PA_SAMPLE_S24RE;
243    else if (strcasecmp(format, "s24-32le") == 0)
244        return PA_SAMPLE_S24_32LE;
245    else if (strcasecmp(format, "s24-32be") == 0)
246        return PA_SAMPLE_S24_32BE;
247    else if (strcasecmp(format, "s24-32ne") == 0 || strcasecmp(format, "s24-32") == 0)
248        return PA_SAMPLE_S24_32NE;
249    else if (strcasecmp(format, "s24-32re") == 0)
250        return PA_SAMPLE_S24_32RE;
251
252    return PA_SAMPLE_INVALID;
253}
254
255int pa_sample_format_is_le(pa_sample_format_t f) {
256    pa_assert(pa_sample_format_valid(f));
257
258    switch (f) {
259        case PA_SAMPLE_S16LE:
260        case PA_SAMPLE_S24LE:
261        case PA_SAMPLE_S32LE:
262        case PA_SAMPLE_S24_32LE:
263        case PA_SAMPLE_FLOAT32LE:
264            return 1;
265
266        case PA_SAMPLE_S16BE:
267        case PA_SAMPLE_S24BE:
268        case PA_SAMPLE_S32BE:
269        case PA_SAMPLE_S24_32BE:
270        case PA_SAMPLE_FLOAT32BE:
271            return 0;
272
273        default:
274            return -1;
275    }
276}
277
278int pa_sample_format_is_be(pa_sample_format_t f) {
279    int r;
280
281    if ((r = pa_sample_format_is_le(f)) < 0)
282        return r;
283
284    return !r;
285}
286