Browse Source

memops: Use right-aligned S24LE to float conversion

ALSA expects right-aligned samples (0x00******) as mentioned in the
source code for SND_PCM_FORMAT_S24_LE:
Signed 24 bit Little Endian using low three bytes in 32-bit word
See http://git.alsa-project.org/?p=alsa-
lib.git;a=blob;f=include/pcm.h;h=5b0782315585de1d5ab82c9f2036b62c168f5a48;hb=HEAD#l140

Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>
tags/v1.9.13
Timo Wischer Filipe Coelho <falktx@falktx.com> 7 years ago
parent
commit
e753254313
1 changed files with 19 additions and 14 deletions
  1. +19
    -14
      common/memops.c

+ 19
- 14
common/memops.c View File

@@ -73,8 +73,8 @@
So, for now (October 2008) we use 2^(N-1)-1 as the scaling factor. So, for now (October 2008) we use 2^(N-1)-1 as the scaling factor.
*/ */


#define SAMPLE_24BIT_SCALING 8388607.0f
#define SAMPLE_16BIT_SCALING 32767.0f
#define SAMPLE_24BIT_SCALING 8388607
#define SAMPLE_16BIT_SCALING 32767


/* these are just values to use if the floating point value was out of range /* these are just values to use if the floating point value was out of range
@@ -414,8 +414,10 @@ void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigne


void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip)
{ {
const jack_default_audio_sample_t scaling = 1.0 / (SAMPLE_24BIT_SCALING << 8);

#if defined (__ARM_NEON__) || defined (__ARM_NEON) #if defined (__ARM_NEON__) || defined (__ARM_NEON)
float32x4_t factor = vdupq_n_f32(1.0 / SAMPLE_24BIT_SCALING);
float32x4_t factor = vdupq_n_f32(scaling);
unsigned long unrolled = nsamples / 4; unsigned long unrolled = nsamples / 4;
while (unrolled--) { while (unrolled--) {
int32x4_t src128; int32x4_t src128;
@@ -435,7 +437,8 @@ void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsign
break; break;
} }
src128 = vreinterpretq_s32_u8(vrev32q_u8(vreinterpretq_u8_s32(src128))); src128 = vreinterpretq_s32_u8(vrev32q_u8(vreinterpretq_u8_s32(src128)));
int32x4_t shifted = vshrq_n_s32(src128, 8);
/* sign extension - left shift will be reverted by scaling */
int32x4_t shifted = vshlq_n_s32(src128, 8);
float32x4_t as_float = vcvtq_f32_s32(shifted); float32x4_t as_float = vcvtq_f32_s32(shifted);
float32x4_t divided = vmulq_f32(as_float, factor); float32x4_t divided = vmulq_f32(as_float, factor);
vst1q_f32(dst, divided); vst1q_f32(dst, divided);
@@ -448,8 +451,6 @@ void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsign


/* ALERT: signed sign-extension portability !!! */ /* ALERT: signed sign-extension portability !!! */


const jack_default_audio_sample_t scaling = 1.0/SAMPLE_24BIT_SCALING;

while (nsamples--) { while (nsamples--) {
int x; int x;
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -469,7 +470,8 @@ void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsign
x <<= 8; x <<= 8;
x |= (unsigned char)(src[0]); x |= (unsigned char)(src[0]);
#endif #endif
*dst = (x >> 8) * scaling;
/* sign extension - left shift will be reverted by scaling */
*dst = (x << 8) * scaling;
dst++; dst++;
src += src_skip; src += src_skip;
} }
@@ -477,10 +479,11 @@ void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsign


void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip)
{ {
const jack_default_audio_sample_t scaling = 1.0 / (SAMPLE_24BIT_SCALING << 8);

#if defined (__SSE2__) && !defined (__sun__) #if defined (__SSE2__) && !defined (__sun__)
unsigned long unrolled = nsamples / 4; unsigned long unrolled = nsamples / 4;
static float inv_sample_max_24bit = 1.0 / SAMPLE_24BIT_SCALING;
__m128 factor = _mm_set1_ps(inv_sample_max_24bit);
__m128 factor = _mm_set1_ps(scaling);
while (unrolled--) while (unrolled--)
{ {
int i1 = *((int *) src); int i1 = *((int *) src);
@@ -493,7 +496,8 @@ void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigne
src+= src_skip; src+= src_skip;


__m128i src = _mm_set_epi32(i4, i3, i2, i1); __m128i src = _mm_set_epi32(i4, i3, i2, i1);
__m128i shifted = _mm_srai_epi32(src, 8);
/* sign extension - left shift will be reverted by scaling */
__m128i shifted = _mm_slli_epi32(src, 8);


__m128 as_float = _mm_cvtepi32_ps(shifted); __m128 as_float = _mm_cvtepi32_ps(shifted);
__m128 divided = _mm_mul_ps(as_float, factor); __m128 divided = _mm_mul_ps(as_float, factor);
@@ -505,7 +509,7 @@ void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigne
nsamples = nsamples & 3; nsamples = nsamples & 3;
#elif defined (__ARM_NEON__) || defined (__ARM_NEON) #elif defined (__ARM_NEON__) || defined (__ARM_NEON)
unsigned long unrolled = nsamples / 4; unsigned long unrolled = nsamples / 4;
float32x4_t factor = vdupq_n_f32(1.0 / SAMPLE_24BIT_SCALING);
float32x4_t factor = vdupq_n_f32(scaling);
while (unrolled--) { while (unrolled--) {
int32x4_t src128; int32x4_t src128;
switch(src_skip) { switch(src_skip) {
@@ -522,7 +526,8 @@ void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigne
src128 = vld1q_lane_s32((int32_t*)(src+3*src_skip), src128, 3); src128 = vld1q_lane_s32((int32_t*)(src+3*src_skip), src128, 3);
break; break;
} }
int32x4_t shifted = vshrq_n_s32(src128, 8);
/* sign extension - left shift will be reverted by scaling */
int32x4_t shifted = vshlq_n_s32(src128, 8);
float32x4_t as_float = vcvtq_f32_s32(shifted); float32x4_t as_float = vcvtq_f32_s32(shifted);
float32x4_t divided = vmulq_f32(as_float, factor); float32x4_t divided = vmulq_f32(as_float, factor);
vst1q_f32(dst, divided); vst1q_f32(dst, divided);
@@ -535,9 +540,9 @@ void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigne


/* ALERT: signed sign-extension portability !!! */ /* ALERT: signed sign-extension portability !!! */


const jack_default_audio_sample_t scaling = 1.0/SAMPLE_24BIT_SCALING;
while (nsamples--) { while (nsamples--) {
*dst = (*((int *) src) >> 8) * scaling;
/* sign extension - left shift will be reverted by scaling */
*dst = (*((int *) src) << 8) * scaling;
dst++; dst++;
src += src_skip; src += src_skip;
} }


Loading…
Cancel
Save