X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/b7026bf248948a6a30386ddbcc137f48f369a51e..eca082a93f2619cfa10733947a81fa779cb49573:/src/pulsecore/sconv-s16le.c diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c index 693d529b..45cf9729 100644 --- a/src/pulsecore/sconv-s16le.c +++ b/src/pulsecore/sconv-s16le.c @@ -5,7 +5,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but @@ -23,36 +23,52 @@ #include #endif -/* Despite the name of this file we implement S32 handling here, too. */ +/* Despite the name of this file we implement S32 and S24 handling here, too. */ #include #include - -#include +#include #include #include -#include - -#include "endianmacros.h" +#include #include "sconv-s16le.h" #ifndef INT16_FROM #define INT16_FROM PA_INT16_FROM_LE #endif +#ifndef UINT16_FROM +#define UINT16_FROM PA_UINT16_FROM_LE +#endif #ifndef INT16_TO #define INT16_TO PA_INT16_TO_LE #endif +#ifndef UINT16_TO +#define UINT16_TO PA_UINT16_TO_LE +#endif #ifndef INT32_FROM #define INT32_FROM PA_INT32_FROM_LE #endif +#ifndef UINT32_FROM +#define UINT32_FROM PA_UINT32_FROM_LE +#endif #ifndef INT32_TO #define INT32_TO PA_INT32_TO_LE #endif +#ifndef UINT32_TO +#define UINT32_TO PA_UINT32_TO_LE +#endif + +#ifndef READ24 +#define READ24 PA_READ24LE +#endif +#ifndef WRITE24 +#define WRITE24 PA_WRITE24LE +#endif #ifndef SWAP_WORDS #ifdef WORDS_BIGENDIAN @@ -67,17 +83,13 @@ void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *b) { pa_assert(b); #if SWAP_WORDS == 1 - for (; n > 0; n--) { int16_t s = *(a++); - *(b++) = ((float) INT16_FROM(s))/(float) 0x7FFF; + *(b++) = INT16_FROM(s) * (1.0f / (1 << 15)); } - #else -{ - static const double add = 0, factor = 1.0/0x7FFF; - oil_scaleconv_f32_s16(b, a, (int) n, &add, &factor); -} + for (; n > 0; n--) + *(b++) = *(a++) * (1.0f / (1 << 15)); #endif } @@ -86,17 +98,13 @@ void pa_sconv_s32le_to_float32ne(unsigned n, const int32_t *a, float *b) { pa_assert(b); #if SWAP_WORDS == 1 - for (; n > 0; n--) { int32_t s = *(a++); - *(b++) = (float) (((double) INT32_FROM(s))/0x7FFFFFFF); + *(b++) = INT32_FROM(s) * (1.0f / (1U << 31)); } - #else -{ - static const double add = 0, factor = 1.0/0x7FFFFFFF; - oil_scaleconv_f32_s32(b, a, (int) n, &add, &factor); -} + for (; n > 0; n--) + *(b++) = *(a++) * (1.0f / (1U << 31)); #endif } @@ -105,21 +113,19 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) { pa_assert(b); #if SWAP_WORDS == 1 - for (; n > 0; n--) { int16_t s; - float v = *(a++); + float v = *(a++) * (1 << 15); - v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.f); - s = (int16_t) (v * 0x7FFF); + s = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF); *(b++) = INT16_TO(s); } - #else -{ - static const double add = 0, factor = 0x7FFF; - oil_scaleconv_s16_f32(b, a, (int) n, &add, &factor); -} + for (; n > 0; n--) { + float v = *(a++) * (1 << 15); + + *(b++) = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF); + } #endif } @@ -128,21 +134,19 @@ void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *b) { pa_assert(b); #if SWAP_WORDS == 1 - for (; n > 0; n--) { int32_t s; - float v = *(a++); + float v = *(a++) * (1U << 31); - v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); - s = (int32_t) ((double) v * (double) 0x7FFFFFFF); + s = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL); *(b++) = INT32_TO(s); } - #else -{ - static const double add = 0, factor = 0x7FFFFFFF; - oil_scaleconv_s32_f32(b, a, (int) n, &add, &factor); -} + for (; n > 0; n--) { + float v = *(a++) * (1U << 31); + + *(b++) = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL); + } #endif } @@ -152,9 +156,8 @@ void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) { for (; n > 0; n--) { int16_t s = *(a++); - float k = ((float) INT16_FROM(s))/0x7FFF; - uint32_t *j = (uint32_t*) &k; - *j = PA_UINT32_SWAP(*j); + float k = INT16_FROM(s) * (1.0f / (1 << 15)); + k = PA_FLOAT32_SWAP(k); *(b++) = k; } } @@ -165,9 +168,8 @@ void pa_sconv_s32le_to_float32re(unsigned n, const int32_t *a, float *b) { for (; n > 0; n--) { int32_t s = *(a++); - float k = (float) (((double) INT32_FROM(s))/0x7FFFFFFF); - uint32_t *j = (uint32_t*) &k; - *j = PA_UINT32_SWAP(*j); + float k = INT32_FROM(s) * (1.0f / (1U << 31)); + k = PA_FLOAT32_SWAP(k); *(b++) = k; } } @@ -179,10 +181,8 @@ void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) { for (; n > 0; n--) { int16_t s; float v = *(a++); - uint32_t *j = (uint32_t*) &v; - *j = PA_UINT32_SWAP(*j); - v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); - s = (int16_t) (v * 0x7FFF); + v = PA_FLOAT32_SWAP(v) * (1 << 15); + s = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF); *(b++) = INT16_TO(s); } } @@ -194,10 +194,8 @@ void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b) { for (; n > 0; n--) { int32_t s; float v = *(a++); - uint32_t *j = (uint32_t*) &v; - *j = PA_UINT32_SWAP(*j); - v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f); - s = (int32_t) ((double) v * 0x7FFFFFFF); + v = PA_FLOAT32_SWAP(v) * (1U << 31); + s = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL); *(b++) = INT32_TO(s); } } @@ -247,3 +245,203 @@ void pa_sconv_s32le_from_s16re(unsigned n, const int16_t *a, int32_t *b) { b++; } } + +void pa_sconv_s24le_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + *b = (int16_t) (READ24(a) >> 8); + a += 3; + b++; + } +} + +void pa_sconv_s24le_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + WRITE24(b, ((uint32_t) *a) << 8); + a++; + b += 3; + } +} + +void pa_sconv_s24le_to_s16re(unsigned n, const uint8_t *a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int16_t s = (int16_t) (READ24(a) >> 8); + *b = PA_INT16_SWAP(s); + a += 3; + b++; + } +} + +void pa_sconv_s24le_from_s16re(unsigned n, const int16_t *a, uint8_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + uint32_t s = ((uint32_t) PA_INT16_SWAP(*a)) << 8; + WRITE24(b, s); + a++; + b += 3; + } +} + +void pa_sconv_s24le_to_float32ne(unsigned n, const uint8_t *a, float *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s = READ24(a) << 8; + *b = s * (1.0f / (1U << 31)); + a += 3; + b++; + } +} + +void pa_sconv_s24le_from_float32ne(unsigned n, const float *a, uint8_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s; + float v = *a * (1U << 31); + s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL); + WRITE24(b, ((uint32_t) s) >> 8); + a++; + b += 3; + } +} + +void pa_sconv_s24le_to_float32re(unsigned n, const uint8_t *a, float *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s = READ24(a) << 8; + float k = s * (1.0f / (1U << 31)); + *b = PA_FLOAT32_SWAP(k); + a += 3; + b++; + } +} + +void pa_sconv_s24le_from_float32re(unsigned n, const float *a, uint8_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s; + float v = *a; + v = PA_FLOAT32_SWAP(v) * (1U << 31); + s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL); + WRITE24(b, ((uint32_t) s) >> 8); + a++; + b+=3; + } +} + +void pa_sconv_s24_32le_to_s16ne(unsigned n, const uint32_t *a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + *b = (int16_t) (((int32_t) (UINT32_FROM(*a) << 8)) >> 16); + a++; + b++; + } +} + +void pa_sconv_s24_32le_to_s16re(unsigned n, const uint32_t *a, int16_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int16_t s = (int16_t) ((int32_t) (UINT32_FROM(*a) << 8) >> 16); + *b = PA_INT16_SWAP(s); + a++; + b++; + } +} + +void pa_sconv_s24_32le_from_s16ne(unsigned n, const int16_t *a, uint32_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + *b = UINT32_TO(((uint32_t) ((int32_t) *a << 16)) >> 8); + a++; + b++; + } +} + +void pa_sconv_s24_32le_from_s16re(unsigned n, const int16_t *a, uint32_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + uint32_t s = ((uint32_t) ((int32_t) PA_INT16_SWAP(*a) << 16)) >> 8; + *b = UINT32_TO(s); + a++; + b++; + } +} + +void pa_sconv_s24_32le_to_float32ne(unsigned n, const uint32_t *a, float *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s = (int32_t) (UINT32_FROM(*a) << 8); + *b = s * (1.0f / (1U << 31)); + a++; + b++; + } +} + +void pa_sconv_s24_32le_to_float32re(unsigned n, const uint32_t *a, float *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s = (int32_t) (UINT32_FROM(*a) << 8); + float k = s * (1.0f / (1U << 31)); + *b = PA_FLOAT32_SWAP(k); + a++; + b++; + } +} + +void pa_sconv_s24_32le_from_float32ne(unsigned n, const float *a, uint32_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s; + float v = *a * (1U << 31); + s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL); + *b = UINT32_TO(((uint32_t) s) >> 8); + a++; + b++; + } +} + +void pa_sconv_s24_32le_from_float32re(unsigned n, const float *a, uint32_t *b) { + pa_assert(a); + pa_assert(b); + + for (; n > 0; n--) { + int32_t s; + float v = *a; + v = PA_FLOAT32_SWAP(v) * (1U << 31); + s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL); + *b = UINT32_TO(((uint32_t) s) >> 8); + a++; + b++; + } +}