Simplify audio conversion code

This commit is contained in:
twinaphex 2017-01-31 07:33:58 +01:00
parent 75133941a9
commit ed3d75738c
4 changed files with 45 additions and 291 deletions

View File

@ -31,8 +31,12 @@
#include <features/features_cpu.h> #include <features/features_cpu.h>
#include <audio/conversion/float_to_s16.h> #include <audio/conversion/float_to_s16.h>
#if defined(__ARM_NEON__)
void convert_float_s16_asm(int16_t *out, const float *in, size_t samples);
#endif
/** /**
* convert_float_to_s16_C: * convert_float_to_s16:
* @out : output buffer * @out : output buffer
* @in : input buffer * @in : input buffer
* @samples : size of samples to be converted * @samples : size of samples to be converted
@ -42,34 +46,11 @@
* *
* C implementation callback function. * C implementation callback function.
**/ **/
void convert_float_to_s16_C(int16_t *out, void convert_float_to_s16(int16_t *out,
const float *in, size_t samples) const float *in, size_t samples)
{ {
size_t i; size_t i;
for (i = 0; i < samples; i++)
{
int32_t val = (int32_t)(in[i] * 0x8000);
out[i] = (val > 0x7FFF) ? 0x7FFF :
(val < -0x8000 ? -0x8000 : (int16_t)val);
}
}
#if defined(__SSE2__) #if defined(__SSE2__)
/**
* convert_float_to_s16_SSE2:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
*
* Converts floating point
* to signed integer 16-bit.
*
* SSE2 implementation callback function.
**/
void convert_float_to_s16_SSE2(int16_t *out,
const float *in, size_t samples)
{
size_t i;
__m128 factor = _mm_set1_ps((float)0x8000); __m128 factor = _mm_set1_ps((float)0x8000);
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8) for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
@ -85,23 +66,9 @@ void convert_float_to_s16_SSE2(int16_t *out,
_mm_storeu_si128((__m128i *)out, packed); _mm_storeu_si128((__m128i *)out, packed);
} }
convert_float_to_s16_C(out, in, samples - i); samples = samples - i;
} i = 0;
#elif defined(__ALTIVEC__) #elif defined(__ALTIVEC__)
/**
* convert_float_to_s16_altivec:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
*
* Converts floating point
* to signed integer 16-bit.
*
* AltiVec implementation callback function.
**/
void convert_float_to_s16_altivec(int16_t *out,
const float *in, size_t samples)
{
int samples_in = samples; int samples_in = samples;
/* Unaligned loads/store is a bit expensive, /* Unaligned loads/store is a bit expensive,
@ -120,47 +87,19 @@ void convert_float_to_s16_altivec(int16_t *out,
samples_in -= i; samples_in -= i;
} }
convert_float_to_s16_C(out, in, samples_in);
} samples = samples_in;
i = 0;
#elif defined(__ARM_NEON__) #elif defined(__ARM_NEON__)
void convert_float_s16_asm(int16_t *out, const float *in, size_t samples);
/**
* convert_float_to_s16_neon:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
*
* Converts floating point
* to signed integer 16-bit.
*
* ARM NEON implementation callback function.
**/
static void convert_float_to_s16_neon(int16_t *out,
const float *in, size_t samples)
{
size_t aligned_samples = samples & ~7; size_t aligned_samples = samples & ~7;
if (aligned_samples) if (aligned_samples)
convert_float_s16_asm(out, in, aligned_samples); convert_float_s16_asm(out, in, aligned_samples);
convert_float_to_s16_C(out + aligned_samples, in + aligned_samples, out = out + aligned_samples;
samples - aligned_samples); in = in + aligned_samples;
} samples = samples - aligned_samples;
i = 0;
#elif defined(_MIPS_ARCH_ALLEGREX) #elif defined(_MIPS_ARCH_ALLEGREX)
/**
* convert_float_to_s16_ALLEGREX:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
*
* Converts floating point
* to signed integer 16-bit.
*
* MIPS ALLEGREX implementation callback function.
**/
void convert_float_to_s16_ALLEGREX(int16_t *out,
const float *in, size_t samples)
{
size_t i;
#ifdef DEBUG #ifdef DEBUG
/* Make sure the buffers are 16 byte aligned, this should be /* Make sure the buffers are 16 byte aligned, this should be
@ -190,6 +129,8 @@ void convert_float_to_s16_ALLEGREX(int16_t *out,
:: "r"(in + i), "r"(out + i)); :: "r"(in + i), "r"(out + i));
} }
#endif
for (; i < samples; i++) for (; i < samples; i++)
{ {
int32_t val = (int32_t)(in[i] * 0x8000); int32_t val = (int32_t)(in[i] * 0x8000);
@ -197,7 +138,6 @@ void convert_float_to_s16_ALLEGREX(int16_t *out,
(val < -0x8000 ? -0x8000 : (int16_t)val); (val < -0x8000 ? -0x8000 : (int16_t)val);
} }
} }
#endif
/** /**
* convert_float_to_s16_init_simd: * convert_float_to_s16_init_simd:

View File

@ -29,8 +29,14 @@
#include <features/features_cpu.h> #include <features/features_cpu.h>
#include <audio/conversion/s16_to_float.h> #include <audio/conversion/s16_to_float.h>
#if defined(__ARM_NEON__)
/* Avoid potential hard-float/soft-float ABI issues. */
void convert_s16_float_asm(float *out, const int16_t *in,
size_t samples, const float *gain);
#endif
/** /**
* convert_s16_to_float_C: * convert_s16_to_float:
* @out : output buffer * @out : output buffer
* @in : input buffer * @in : input buffer
* @samples : size of samples to be converted * @samples : size of samples to be converted
@ -38,35 +44,13 @@
* *
* Converts from signed integer 16-bit * Converts from signed integer 16-bit
* to floating point. * to floating point.
*
* C implementation callback function.
**/ **/
void convert_s16_to_float_C(float *out, void convert_s16_to_float(float *out,
const int16_t *in, size_t samples, float gain) const int16_t *in, size_t samples, float gain)
{ {
size_t i; size_t i = 0;
gain = gain / 0x8000;
for (i = 0; i < samples; i++)
out[i] = (float)in[i] * gain;
}
#if defined(__SSE2__) #if defined(__SSE2__)
/**
* convert_s16_to_float_SSE2:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
* @gain : gain applied (e.g. audio volume)
*
* Converts from signed integer 16-bit
* to floating point.
*
* SSE2 implementation callback function.
**/
void convert_s16_to_float_SSE2(float *out,
const int16_t *in, size_t samples, float gain)
{
size_t i;
float fgain = gain / UINT32_C(0x80000000); float fgain = gain / UINT32_C(0x80000000);
__m128 factor = _mm_set1_ps(fgain); __m128 factor = _mm_set1_ps(fgain);
@ -82,25 +66,9 @@ void convert_s16_to_float_SSE2(float *out,
_mm_storeu_ps(out + 4, output_r); _mm_storeu_ps(out + 4, output_r);
} }
convert_s16_to_float_C(out, in, samples - i, gain); samples = samples - i;
} i = 0;
#elif defined(__ALTIVEC__) #elif defined(__ALTIVEC__)
/**
* convert_s16_to_float_altivec:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
* @gain : gain applied (e.g. audio volume)
*
* Converts from signed integer 16-bit
* to floating point.
*
* AltiVec implementation callback function.
**/
void convert_s16_to_float_altivec(float *out,
const int16_t *in, size_t samples, float gain)
{
size_t samples_in = samples; size_t samples_in = samples;
/* Unaligned loads/store is a bit expensive, so we /* Unaligned loads/store is a bit expensive, so we
@ -125,54 +93,22 @@ void convert_s16_to_float_altivec(float *out,
samples_in -= i; samples_in -= i;
} }
convert_s16_to_float_C(out, in, samples_in, gain);
} samples = samples_in;
i = 0;
#elif defined(__ARM_NEON__) #elif defined(__ARM_NEON__)
/* Avoid potential hard-float/soft-float ABI issues. */
void convert_s16_float_asm(float *out, const int16_t *in,
size_t samples, const float *gain);
/**
* convert_s16_to_float_neon:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
* @gain : gain applied (.e.g audio volume)
*
* Converts from signed integer 16-bit
* to floating point.
*
* ARM NEON implementation callback function.
**/
static void convert_s16_to_float_neon(float *out,
const int16_t *in, size_t samples, float gain)
{
size_t aligned_samples = samples & ~7; size_t aligned_samples = samples & ~7;
if (aligned_samples) if (aligned_samples)
convert_s16_float_asm(out, in, aligned_samples, &gain); convert_s16_float_asm(out, in, aligned_samples, &gain);
/* Could do all conversion in ASM, but keep it simple for now. */ /* Could do all conversion in ASM, but keep it simple for now. */
convert_s16_to_float_C(out + aligned_samples, in + aligned_samples, out = out + aligned_samples;
samples - aligned_samples, gain); in = in + aligned_samples;
} samples = samples - aligned_samples;
#elif defined(_MIPS_ARCH_ALLEGREX) i = 0;
/** #elif defined(_MIPS_ARCH_ALLEGREX)
* convert_s16_to_float_ALLEGREX:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
* @gain : gain applied (.e.g audio volume)
*
* Converts from signed integer 16-bit
* to floating point.
*
* MIPS ALLEGREX implementation callback function.
**/
void convert_s16_to_float_ALLEGREX(float *out,
const int16_t *in, size_t samples, float gain)
{
#ifdef DEBUG #ifdef DEBUG
/* Make sure the buffer is 16 byte aligned, this should be the /* Make sure the buffer is 16 byte aligned, this should be the
* default behaviour of malloc in the PSPSDK. * default behaviour of malloc in the PSPSDK.
@ -180,7 +116,6 @@ void convert_s16_to_float_ALLEGREX(float *out,
retro_assert(((uintptr_t)out & 0xf) == 0); retro_assert(((uintptr_t)out & 0xf) == 0);
#endif #endif
size_t i;
gain = gain / 0x8000; gain = gain / 0x8000;
__asm__ ( __asm__ (
".set push \n" ".set push \n"
@ -225,10 +160,12 @@ void convert_s16_to_float_ALLEGREX(float *out,
:: "r"(in + i), "r"(out + i)); :: "r"(in + i), "r"(out + i));
} }
#endif
gain = gain / 0x8000;
for (; i < samples; i++) for (; i < samples; i++)
out[i] = (float)in[i] * gain; out[i] = (float)in[i] * gain;
} }
#endif
/** /**
* convert_s16_to_float_init_simd: * convert_s16_to_float_init_simd:

View File

@ -31,75 +31,17 @@ RETRO_BEGIN_DECLS
#include <stddef.h> #include <stddef.h>
/** /**
* convert_float_to_s16_C: * convert_float_to_s16:
* @out : output buffer * @out : output buffer
* @in : input buffer * @in : input buffer
* @samples : size of samples to be converted * @samples : size of samples to be converted
* *
* Converts floating point * Converts floating point
* to signed integer 16-bit. * to signed integer 16-bit.
*
* C implementation callback function.
**/ **/
void convert_float_to_s16_C(int16_t *out, void convert_float_to_s16(int16_t *out,
const float *in, size_t samples); const float *in, size_t samples);
#if defined(__SSE2__)
#define convert_float_to_s16 convert_float_to_s16_SSE2
/**
* convert_float_to_s16_SSE2:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
*
* Converts floating point
* to signed integer 16-bit.
*
* SSE2 implementation callback function.
**/
void convert_float_to_s16_SSE2(int16_t *out,
const float *in, size_t samples);
#elif defined(__ALTIVEC__)
#define convert_float_to_s16 convert_float_to_s16_altivec
/**
* convert_float_to_s16_altivec:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
*
* Converts floating point
* to signed integer 16-bit.
*
* AltiVec implementation callback function.
**/
void convert_float_to_s16_altivec(int16_t *out,
const float *in, size_t samples);
#elif defined(__ARM_NEON__)
#define convert_float_to_s16 convert_float_to_s16_arm
void (*convert_float_to_s16_arm)(int16_t *out,
const float *in, size_t samples);
void convert_float_s16_asm(int16_t *out, const float *in, size_t samples);
#elif defined(_MIPS_ARCH_ALLEGREX)
#define convert_float_to_s16 convert_float_to_s16_ALLEGREX
/**
* convert_float_to_s16_ALLEGREX:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
*
* Converts floating point
* to signed integer 16-bit.
*
* MIPS ALLEGREX implementation callback function.
**/
void convert_float_to_s16_ALLEGREX(int16_t *out,
const float *in, size_t samples);
#else
#define convert_float_to_s16 convert_float_to_s16_C
#endif
/** /**
* convert_float_to_s16_init_simd: * convert_float_to_s16_init_simd:
* *

View File

@ -29,11 +29,8 @@
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
#if defined(__SSE2__)
#define convert_s16_to_float convert_s16_to_float_SSE2
/** /**
* convert_s16_to_float_SSE2: * convert_s16_to_float:
* @out : output buffer * @out : output buffer
* @in : input buffer * @in : input buffer
* @samples : size of samples to be converted * @samples : size of samples to be converted
@ -41,70 +38,8 @@ RETRO_BEGIN_DECLS
* *
* Converts from signed integer 16-bit * Converts from signed integer 16-bit
* to floating point. * to floating point.
*
* SSE2 implementation callback function.
**/ **/
void convert_s16_to_float_SSE2(float *out, void convert_s16_to_float(float *out,
const int16_t *in, size_t samples, float gain);
#elif defined(__ALTIVEC__)
#define convert_s16_to_float convert_s16_to_float_altivec
/**
* convert_s16_to_float_altivec:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
* @gain : gain applied (.e.g. audio volume)
*
* Converts from signed integer 16-bit
* to floating point.
*
* AltiVec implementation callback function.
**/
void convert_s16_to_float_altivec(float *out,
const int16_t *in, size_t samples, float gain);
#elif defined(__ARM_NEON__)
#define convert_s16_to_float convert_s16_to_float_arm
void (*convert_s16_to_float_arm)(float *out,
const int16_t *in, size_t samples, float gain);
#elif defined(_MIPS_ARCH_ALLEGREX)
#define convert_s16_to_float convert_s16_to_float_ALLEGREX
/**
* convert_s16_to_float_ALLEGREX:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
* @gain : gain applied (.e.g. audio volume)
*
* Converts from signed integer 16-bit
* to floating point.
*
* MIPS ALLEGREX implementation callback function.
**/
void convert_s16_to_float_ALLEGREX(float *out,
const int16_t *in, size_t samples, float gain);
#else
#define convert_s16_to_float convert_s16_to_float_C
#endif
/**
* convert_s16_to_float_C:
* @out : output buffer
* @in : input buffer
* @samples : size of samples to be converted
* @gain : gain applied (.e.g. audio volume)
*
* Converts from signed integer 16-bit
* to floating point.
*
* C implementation callback function.
**/
void convert_s16_to_float_C(float *out,
const int16_t *in, size_t samples, float gain); const int16_t *in, size_t samples, float gain);
/** /**