1/***
2  This file is part of PulseAudio.
3
4  Copyright 2004-2006 Lennart Poettering
5
6  PulseAudio is free software; you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation; either version 2.1 of the License,
9  or (at your option) any later version.
10
11  PulseAudio is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  General Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public License
17  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18***/
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/* Despite the name of this file we implement S32 and S24 handling here, too. */
25
26#include <inttypes.h>
27#include <stdio.h>
28#include <math.h>
29
30#include <pulsecore/sconv.h>
31#include <pulsecore/macro.h>
32#include <pulsecore/endianmacros.h>
33
34#include "sconv-s16le.h"
35
36#ifndef INT16_FROM
37#define INT16_FROM PA_INT16_FROM_LE
38#endif
39#ifndef UINT16_FROM
40#define UINT16_FROM PA_UINT16_FROM_LE
41#endif
42
43#ifndef INT16_TO
44#define INT16_TO PA_INT16_TO_LE
45#endif
46#ifndef UINT16_TO
47#define UINT16_TO PA_UINT16_TO_LE
48#endif
49
50#ifndef INT32_FROM
51#define INT32_FROM PA_INT32_FROM_LE
52#endif
53#ifndef UINT32_FROM
54#define UINT32_FROM PA_UINT32_FROM_LE
55#endif
56
57#ifndef INT32_TO
58#define INT32_TO PA_INT32_TO_LE
59#endif
60#ifndef UINT32_TO
61#define UINT32_TO PA_UINT32_TO_LE
62#endif
63
64#ifndef READ24
65#define READ24 PA_READ24LE
66#endif
67#ifndef WRITE24
68#define WRITE24 PA_WRITE24LE
69#endif
70
71#ifndef SWAP_WORDS
72#ifdef WORDS_BIGENDIAN
73#define SWAP_WORDS 1
74#else
75#define SWAP_WORDS 0
76#endif
77#endif
78
79void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b) {
80    pa_assert(a);
81    pa_assert(b);
82
83#if SWAP_WORDS == 1
84    for (; n > 0; n--) {
85        int16_t s = *(a++);
86        *(b++) = INT16_FROM(s) * (1.0f / (1 << 15));
87    }
88#else
89    for (; n > 0; n--)
90        *(b++) = *(a++) * (1.0f / (1 << 15));
91#endif
92}
93
94void pa_sconv_s32le_to_float32ne(unsigned n, const int32_t *a, float *b) {
95    pa_assert(a);
96    pa_assert(b);
97
98#if SWAP_WORDS == 1
99    for (; n > 0; n--) {
100        int32_t s = *(a++);
101        *(b++) = INT32_FROM(s) * (1.0f / (1U << 31));
102    }
103#else
104    for (; n > 0; n--)
105        *(b++) = *(a++) * (1.0f / (1U << 31));
106#endif
107}
108
109void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) {
110    pa_assert(a);
111    pa_assert(b);
112
113#if SWAP_WORDS == 1
114    for (; n > 0; n--) {
115        int16_t s;
116        float v = *(a++) * (1 << 15);
117
118        s = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF);
119        *(b++) = INT16_TO(s);
120    }
121#else
122    for (; n > 0; n--) {
123        float v = *(a++) * (1 << 15);
124
125        *(b++) = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF);
126    }
127#endif
128}
129
130void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *b) {
131    pa_assert(a);
132    pa_assert(b);
133
134#if SWAP_WORDS == 1
135    for (; n > 0; n--) {
136        int32_t s;
137        float v = *(a++) * (1U << 31);
138
139        s = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL);
140        *(b++) = INT32_TO(s);
141    }
142#else
143    for (; n > 0; n--) {
144        float v = *(a++) * (1U << 31);
145
146        *(b++) = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL);
147    }
148#endif
149}
150
151void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) {
152    pa_assert(a);
153    pa_assert(b);
154
155    for (; n > 0; n--) {
156        int16_t s = *(a++);
157        float k = INT16_FROM(s) * (1.0f / (1 << 15));
158        PA_WRITE_FLOAT32RE(b++, k);
159    }
160}
161
162void pa_sconv_s32le_to_float32re(unsigned n, const int32_t *a, float *b) {
163    pa_assert(a);
164    pa_assert(b);
165
166    for (; n > 0; n--) {
167        int32_t s = *(a++);
168        float k = INT32_FROM(s) * (1.0f / (1U << 31));
169        PA_WRITE_FLOAT32RE(b++, k);
170    }
171}
172
173void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) {
174    pa_assert(a);
175    pa_assert(b);
176
177    for (; n > 0; n--) {
178        int16_t s;
179        float v = PA_READ_FLOAT32RE(a++) * (1 << 15);
180        s = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF);
181        *(b++) = INT16_TO(s);
182    }
183}
184
185void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b) {
186    pa_assert(a);
187    pa_assert(b);
188
189    for (; n > 0; n--) {
190        int32_t s;
191        float v = PA_READ_FLOAT32RE(a++) * (1U << 31);
192        s = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL);
193        *(b++) = INT32_TO(s);
194    }
195}
196
197void pa_sconv_s32le_to_s16ne(unsigned n, const int32_t*a, int16_t *b) {
198    pa_assert(a);
199    pa_assert(b);
200
201    for (; n > 0; n--) {
202        *b = (int16_t) (INT32_FROM(*a) >> 16);
203        a++;
204        b++;
205    }
206}
207
208void pa_sconv_s32le_to_s16re(unsigned n, const int32_t*a, int16_t *b) {
209    pa_assert(a);
210    pa_assert(b);
211
212    for (; n > 0; n--) {
213        int16_t s = (int16_t) (INT32_FROM(*a) >> 16);
214        *b = PA_INT16_SWAP(s);
215        a++;
216        b++;
217    }
218}
219
220void pa_sconv_s32le_from_s16ne(unsigned n, const int16_t *a, int32_t *b) {
221    pa_assert(a);
222    pa_assert(b);
223
224    for (; n > 0; n--) {
225        *b = INT32_TO(((int32_t) *a) << 16);
226        a++;
227        b++;
228    }
229}
230
231void pa_sconv_s32le_from_s16re(unsigned n, const int16_t *a, int32_t *b) {
232    pa_assert(a);
233    pa_assert(b);
234
235    for (; n > 0; n--) {
236        int32_t s = ((int32_t) PA_INT16_SWAP(*a)) << 16;
237        *b = INT32_TO(s);
238        a++;
239        b++;
240    }
241}
242
243void pa_sconv_s24le_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) {
244    pa_assert(a);
245    pa_assert(b);
246
247    for (; n > 0; n--) {
248        *b = (int16_t) (READ24(a) >> 8);
249        a += 3;
250        b++;
251    }
252}
253
254void pa_sconv_s24le_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) {
255    pa_assert(a);
256    pa_assert(b);
257
258    for (; n > 0; n--) {
259        WRITE24(b, ((uint32_t) *a) << 8);
260        a++;
261        b += 3;
262    }
263}
264
265void pa_sconv_s24le_to_s16re(unsigned n, const uint8_t *a, int16_t *b) {
266    pa_assert(a);
267    pa_assert(b);
268
269    for (; n > 0; n--) {
270        int16_t s = (int16_t) (READ24(a) >> 8);
271        *b = PA_INT16_SWAP(s);
272        a += 3;
273        b++;
274    }
275}
276
277void pa_sconv_s24le_from_s16re(unsigned n, const int16_t *a, uint8_t *b) {
278    pa_assert(a);
279    pa_assert(b);
280
281    for (; n > 0; n--) {
282        uint32_t s = ((uint32_t) PA_INT16_SWAP(*a)) << 8;
283        WRITE24(b, s);
284        a++;
285        b += 3;
286    }
287}
288
289void pa_sconv_s24le_to_float32ne(unsigned n, const uint8_t *a, float *b) {
290    pa_assert(a);
291    pa_assert(b);
292
293    for (; n > 0; n--) {
294        int32_t s = READ24(a) << 8;
295        *b = s * (1.0f / (1U << 31));
296        a += 3;
297        b++;
298    }
299}
300
301void pa_sconv_s24le_from_float32ne(unsigned n, const float *a, uint8_t *b) {
302    pa_assert(a);
303    pa_assert(b);
304
305    for (; n > 0; n--) {
306        int32_t s;
307        float v = *a * (1U << 31);
308        s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL);
309        WRITE24(b, ((uint32_t) s) >> 8);
310        a++;
311        b += 3;
312    }
313}
314
315void pa_sconv_s24le_to_float32re(unsigned n, const uint8_t *a, float *b) {
316    pa_assert(a);
317    pa_assert(b);
318
319    for (; n > 0; n--) {
320        int32_t s = READ24(a) << 8;
321        float k = s * (1.0f / (1U << 31));
322        PA_WRITE_FLOAT32RE(b, k);
323        a += 3;
324        b++;
325    }
326}
327
328void pa_sconv_s24le_from_float32re(unsigned n, const float *a, uint8_t *b) {
329    pa_assert(a);
330    pa_assert(b);
331
332    for (; n > 0; n--) {
333        int32_t s;
334        float v = PA_READ_FLOAT32RE(a) * (1U << 31);
335        s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL);
336        WRITE24(b, ((uint32_t) s) >> 8);
337        a++;
338        b+=3;
339    }
340}
341
342void pa_sconv_s24_32le_to_s16ne(unsigned n, const uint32_t *a, int16_t *b) {
343    pa_assert(a);
344    pa_assert(b);
345
346    for (; n > 0; n--) {
347        *b = (int16_t) (((int32_t) (UINT32_FROM(*a) << 8)) >> 16);
348        a++;
349        b++;
350    }
351}
352
353void pa_sconv_s24_32le_to_s16re(unsigned n, const uint32_t *a, int16_t *b) {
354    pa_assert(a);
355    pa_assert(b);
356
357    for (; n > 0; n--) {
358        int16_t s = (int16_t) ((int32_t) (UINT32_FROM(*a) << 8) >> 16);
359        *b = PA_INT16_SWAP(s);
360        a++;
361        b++;
362    }
363}
364
365void pa_sconv_s24_32le_from_s16ne(unsigned n, const int16_t *a, uint32_t *b) {
366    pa_assert(a);
367    pa_assert(b);
368
369    for (; n > 0; n--) {
370        *b = UINT32_TO(((uint32_t) ((int32_t) *a << 16)) >> 8);
371        a++;
372        b++;
373    }
374}
375
376void pa_sconv_s24_32le_from_s16re(unsigned n, const int16_t *a, uint32_t *b) {
377    pa_assert(a);
378    pa_assert(b);
379
380    for (; n > 0; n--) {
381        uint32_t s = ((uint32_t) ((int32_t) PA_INT16_SWAP(*a) << 16)) >> 8;
382        *b = UINT32_TO(s);
383        a++;
384        b++;
385    }
386}
387
388void pa_sconv_s24_32le_to_float32ne(unsigned n, const uint32_t *a, float *b) {
389    pa_assert(a);
390    pa_assert(b);
391
392    for (; n > 0; n--) {
393        int32_t s = (int32_t) (UINT32_FROM(*a) << 8);
394        *b = s * (1.0f / (1U << 31));
395        a++;
396        b++;
397    }
398}
399
400void pa_sconv_s24_32le_to_float32re(unsigned n, const uint32_t *a, float *b) {
401    pa_assert(a);
402    pa_assert(b);
403
404    for (; n > 0; n--) {
405        int32_t s = (int32_t) (UINT32_FROM(*a) << 8);
406        float k = s * (1.0f / (1U << 31));
407        PA_WRITE_FLOAT32RE(b, k);
408        a++;
409        b++;
410    }
411}
412
413void pa_sconv_s24_32le_from_float32ne(unsigned n, const float *a, uint32_t *b) {
414    pa_assert(a);
415    pa_assert(b);
416
417    for (; n > 0; n--) {
418        int32_t s;
419        float v = *a * (1U << 31);
420        s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL);
421        *b = UINT32_TO(((uint32_t) s) >> 8);
422        a++;
423        b++;
424    }
425}
426
427void pa_sconv_s24_32le_from_float32re(unsigned n, const float *a, uint32_t *b) {
428    pa_assert(a);
429    pa_assert(b);
430
431    for (; n > 0; n--) {
432        int32_t s;
433        float v = PA_READ_FLOAT32RE(a) * (1U << 31);
434        s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL);
435        *b = UINT32_TO(((uint32_t) s) >> 8);
436        a++;
437        b++;
438    }
439}
440