mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-09 13:29:59 -05:00
sconv: Change/fix conversion to/from float32
use (1<<15) instead of 0x7fff as a factor when converting from s16 to float32 use (1<<31) instead of 0x7fffffff as a factor when converting from s32 to float32 the change is motivated by the following desireable properties: * s16_from_f32(f32_from_s16(x)) == x for all possible s16 values * x / (1.0f << 15) == x * (1.0f / (1 << 15)) for all x in s16 above changes enable easier optimization while guaranteeing bit-exact results further, other audio sample conversion code (libavresample) does it the same way v3 (comments Tanu): * fix saturation in pa_sconv_s16le_from_f32ne_neon(), use vqrshrn v2 (comments Tanu): * fix comments in ARM NEON code * use llrintf() in pa_sconv_s32le_from_float32ne() Signed-off-by: Peter Meerwald <p.meerwald@bct-electronic.com> Cc: Tanu Kaskinen <tanuk@iki.fi>
This commit is contained in:
parent
596d9aa740
commit
e66e846418
3 changed files with 79 additions and 96 deletions
|
|
@ -85,11 +85,11 @@ void pa_sconv_s16le_to_float32ne(unsigned n, const int16_t *a, float *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
|
||||
for (; n > 0; n--)
|
||||
*(b++) = ((float) (*(a++)))/(float) 0x7FFF;
|
||||
*(b++) = *(a++) * (1.0f / (1 << 15));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -100,11 +100,11 @@ void pa_sconv_s32le_to_float32ne(unsigned n, const int32_t *a, float *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
|
||||
for (; n > 0; n--)
|
||||
*(b++) = (float) (((double) (*(a++)))/0x7FFFFFFF);
|
||||
*(b++) = *(a++) * (1.0f / (1U << 31));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -115,18 +115,16 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *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) lrintf(v * 0x7FFF);
|
||||
s = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF);
|
||||
*(b++) = INT16_TO(s);
|
||||
}
|
||||
#else
|
||||
for (; n > 0; n--) {
|
||||
float v = *(a++);
|
||||
float v = *(a++) * (1 << 15);
|
||||
|
||||
v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.f);
|
||||
*(b++) = (int16_t) lrintf(v * 0x7FFF);
|
||||
*(b++) = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -138,18 +136,16 @@ void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *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) lrint((double) v * (double) 0x7FFFFFFF);
|
||||
s = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL);
|
||||
*(b++) = INT32_TO(s);
|
||||
}
|
||||
#else
|
||||
for (; n > 0; n--) {
|
||||
float v = *(a++);
|
||||
float v = *(a++) * (1U << 31);
|
||||
|
||||
v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
|
||||
*(b++) = (int32_t) lrint((double) v * (double) 0x7FFFFFFF);
|
||||
*(b++) = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -160,7 +156,7 @@ 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;
|
||||
float k = INT16_FROM(s) * (1.0f / (1 << 15));
|
||||
k = PA_FLOAT32_SWAP(k);
|
||||
*(b++) = k;
|
||||
}
|
||||
|
|
@ -172,7 +168,7 @@ 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);
|
||||
float k = INT32_FROM(s) * (1.0f / (1U << 31));
|
||||
k = PA_FLOAT32_SWAP(k);
|
||||
*(b++) = k;
|
||||
}
|
||||
|
|
@ -185,9 +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++);
|
||||
v = PA_FLOAT32_SWAP(v);
|
||||
v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
|
||||
s = (int16_t) lrintf(v * 0x7FFF);
|
||||
v = PA_FLOAT32_SWAP(v) * (1 << 15);
|
||||
s = (int16_t) PA_CLAMP_UNLIKELY(lrintf(v), -0x8000, 0x7FFF);
|
||||
*(b++) = INT16_TO(s);
|
||||
}
|
||||
}
|
||||
|
|
@ -199,9 +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++);
|
||||
v = PA_FLOAT32_SWAP(v);
|
||||
v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
|
||||
s = (int32_t) lrint((double) v * 0x7FFFFFFF);
|
||||
v = PA_FLOAT32_SWAP(v) * (1U << 31);
|
||||
s = (int32_t) PA_CLAMP_UNLIKELY(llrintf(v), -0x80000000LL, 0x7FFFFFFFLL);
|
||||
*(b++) = INT32_TO(s);
|
||||
}
|
||||
}
|
||||
|
|
@ -304,9 +298,9 @@ void pa_sconv_s24le_to_float32ne(unsigned n, const uint8_t *a, float *b) {
|
|||
|
||||
for (; n > 0; n--) {
|
||||
int32_t s = READ24(a) << 8;
|
||||
*b = ((float) s) / 0x7FFFFFFF;
|
||||
*b = s * (1.0f / (1U << 31));
|
||||
a += 3;
|
||||
b ++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,12 +310,11 @@ void pa_sconv_s24le_from_float32ne(unsigned n, const float *a, uint8_t *b) {
|
|||
|
||||
for (; n > 0; n--) {
|
||||
int32_t s;
|
||||
float v = *a;
|
||||
v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
|
||||
s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF);
|
||||
float v = *a * (1U << 31);
|
||||
s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL);
|
||||
WRITE24(b, ((uint32_t) s) >> 8);
|
||||
a++;
|
||||
b+=3;
|
||||
b += 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,10 +324,10 @@ void pa_sconv_s24le_to_float32re(unsigned n, const uint8_t *a, float *b) {
|
|||
|
||||
for (; n > 0; n--) {
|
||||
int32_t s = READ24(a) << 8;
|
||||
float k = ((float) s) / 0x7FFFFFFF;
|
||||
float k = s * (1.0f / (1U << 31));
|
||||
*b = PA_FLOAT32_SWAP(k);
|
||||
a += 3;
|
||||
b ++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -345,9 +338,8 @@ void pa_sconv_s24le_from_float32re(unsigned n, const float *a, uint8_t *b) {
|
|||
for (; n > 0; n--) {
|
||||
int32_t s;
|
||||
float v = *a;
|
||||
v = PA_FLOAT32_SWAP(v);
|
||||
v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
|
||||
s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF);
|
||||
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;
|
||||
|
|
@ -406,9 +398,9 @@ void pa_sconv_s24_32le_to_float32ne(unsigned n, const uint32_t *a, float *b) {
|
|||
|
||||
for (; n > 0; n--) {
|
||||
int32_t s = (int32_t) (UINT32_FROM(*a) << 8);
|
||||
*b = (float) s / (float) 0x7FFFFFFF;
|
||||
a ++;
|
||||
b ++;
|
||||
*b = s * (1.0f / (1U << 31));
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -418,10 +410,10 @@ void pa_sconv_s24_32le_to_float32re(unsigned n, const uint32_t *a, float *b) {
|
|||
|
||||
for (; n > 0; n--) {
|
||||
int32_t s = (int32_t) (UINT32_FROM(*a) << 8);
|
||||
float k = (float) s / (float) 0x7FFFFFFF;
|
||||
float k = s * (1.0f / (1U << 31));
|
||||
*b = PA_FLOAT32_SWAP(k);
|
||||
a ++;
|
||||
b ++;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -431,9 +423,8 @@ void pa_sconv_s24_32le_from_float32ne(unsigned n, const float *a, uint32_t *b) {
|
|||
|
||||
for (; n > 0; n--) {
|
||||
int32_t s;
|
||||
float v = *a;
|
||||
v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
|
||||
s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF);
|
||||
float v = *a * (1U << 31);
|
||||
s = (int32_t) PA_CLAMP_UNLIKELY(llrint(v), -0x80000000LL, 0x7FFFFFFFLL);
|
||||
*b = UINT32_TO(((uint32_t) s) >> 8);
|
||||
a++;
|
||||
b++;
|
||||
|
|
@ -447,9 +438,8 @@ void pa_sconv_s24_32le_from_float32re(unsigned n, const float *a, uint32_t *b) {
|
|||
for (; n > 0; n--) {
|
||||
int32_t s;
|
||||
float v = *a;
|
||||
v = PA_FLOAT32_SWAP(v);
|
||||
v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
|
||||
s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF);
|
||||
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++;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue