diff options
Diffstat (limited to 'Src/nsutil/pcm.cpp')
-rw-r--r-- | Src/nsutil/pcm.cpp | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/Src/nsutil/pcm.cpp b/Src/nsutil/pcm.cpp new file mode 100644 index 00000000..f7c787d0 --- /dev/null +++ b/Src/nsutil/pcm.cpp @@ -0,0 +1,312 @@ +#include "pcm.h" +#include <math.h> +#include <ipps.h> +#include <intrin.h> +#include <mmintrin.h> + +#define PA_CLIP_( val, min, max )\ + { val = ((val) < (min)) ? (min) : (((val) > (max)) ? (max) : (val)); } + +#if defined(_M_IX86) +static __inline long float_to_long(double t) +{ + long r; + __asm fld t + __asm fistp r + return r; +} +#else +#define float_to_long(x) ((long)( x )) +#endif + +inline static void clip(double &x, double a, double b) +{ + double x1 = fabs (x - a); + double x2 = fabs (x - b); + x = x1 + (a + b); + x -= x2; + x *= 0.5; +} + +static void Float32_To_Int32_Clip(void *destinationBuffer, const float *src, size_t count, double gain) +{ + int32_t *dest = (int32_t *)destinationBuffer; + + gain*=65536.*32768.; + while ( count-- ) + { + /* convert to 32 bit and drop the low 8 bits */ + double scaled = *src++ * gain; + clip( scaled, -2147483648., 2147483647.); + signed long temp = (signed long) scaled; + *dest++ = temp; + } +} + +static void Float32_To_Int24_Clip(void *destinationBuffer, const float *src, size_t count, double gain) +{ + unsigned char *dest = (unsigned char*)destinationBuffer; + gain*=65536.*32768.; + while ( count-- ) + { + /* convert to 32 bit and drop the low 8 bits */ + double scaled = *src * gain; + clip( scaled, -2147483648., 2147483647.); + signed long temp = (signed long) scaled; + + dest[0] = (unsigned char)(temp >> 8); + dest[1] = (unsigned char)(temp >> 16); + dest[2] = (unsigned char)(temp >> 24); + + src++; + dest += 3; + } +} + +static void Float32_To_Int16_Clip(void *destinationBuffer, const float *src, size_t count, double gain) +{ + int16_t *dest = (signed short*)destinationBuffer; + + gain*=32768.0; + while ( count-- ) + { + long samp = float_to_long((*src) * gain/* - 0.5*/); + + PA_CLIP_( samp, -0x8000, 0x7FFF ); + *dest = (int16_t) samp; + + src ++; + dest ++; + } +} + +static void Float32_To_UInt8_Clip(void *destinationBuffer, const float *src, size_t count, double gain) +{ + uint8_t *dest = (uint8_t *)destinationBuffer; + + gain*=128.0; + while ( count-- ) + { + long samp = float_to_long((*src) * gain/* - 0.5*/) + 128; + + PA_CLIP_( samp, 0, 255); + *dest = (uint8_t) samp; + + src ++; + dest ++; + } +} + +int nsutil_pcm_FloatToInt_Interleaved_Gain(void *pcm, const float *input, int bps, size_t num_samples, float gain) +{ + switch(bps) + { + case 8: + Float32_To_UInt8_Clip(pcm, input, num_samples, gain); + return 0; + case 16: + Float32_To_Int16_Clip(pcm, input, num_samples, gain); + return 0; + case 24: + Float32_To_Int24_Clip(pcm, input, num_samples, gain); + return 0; + case 32: + Float32_To_Int32_Clip(pcm, input, num_samples, gain); + return 0; + } + return 0; +} + +int nsutil_pcm_FloatToInt_Interleaved(void *pcm, const float *input, int bps, size_t num_samples) +{ + switch(bps) + { + case 8: + Float32_To_UInt8_Clip(pcm, input, num_samples, 1.0f); + return 0; + case 16: + Float32_To_Int16_Clip(pcm, input, num_samples, 1.0f); + return 0; + case 24: + Float32_To_Int24_Clip(pcm, input, num_samples, 1.0f); + return 0; + case 32: + Float32_To_Int32_Clip(pcm, input, num_samples, 1.0f); + return 0; + } + return 0; +} + +int nsutil_pcm_IntToFloat_Interleaved(float *output, const void *pcm, int bps, size_t num_samples) +{ + switch (bps) + { + case 8: + { + unsigned __int8 *samples8 = (unsigned __int8 *)pcm; + for (size_t x = 0; x != num_samples; x ++) + { + output[x] = (float)(samples8[x]-128) * 0.00390625f /* 1/256 */; + } + } + break; + case 16: + { + short *samples16 = (short *)pcm; + for (size_t x = 0; x != num_samples; x ++) + { + output[x] = (float)samples16[x] * 0.000030517578125f /* 1/ 32768 */; + } + } + break; + case 24: + { + unsigned __int8 *samples8 = (unsigned __int8 *)pcm; + for (size_t x = 0; x != num_samples; x ++) + { + long temp = (((long)samples8[0]) << 8); + temp = temp | (((long)samples8[1]) << 16); + temp = temp | (((long)samples8[2]) << 24); + output[x] = (float)temp * 4.656612873077393e-10f /* 1/2147483648 */; + samples8+=3; + } + } + break; + case 32: + { + int32_t *samples32 = (int32_t *)pcm; + for (size_t x = 0; x != num_samples; x ++) + { + output[x] = (float)samples32[x] * 4.656612873077393e-10f /* 1/2147483648 */; + } + } + break; + } + return 0; +} + +int nsutil_pcm_IntToFloat_Interleaved_Gain(float *output, const void *pcm, int bps, size_t num_samples, float gain) +{ + switch (bps) + { + case 8: + { + gain /= 256.0f; + uint8_t *samples8 = (uint8_t *)pcm; + for (size_t x = 0; x != num_samples; x ++) + { + output[x] = (float)(samples8[x]-128) * gain; + } + } + break; + case 16: + { + gain /= 32768.0f; + int16_t *samples16 = (int16_t *)pcm; + for (size_t x = 0; x != num_samples; x ++) + { + output[x] = (float)samples16[x] * gain; + } + } + break; + case 24: + { + gain /= 2147483648.0f; + uint8_t *samples8 = (uint8_t *)pcm; + for (size_t x = 0; x != num_samples; x ++) + { + long temp = (((long)samples8[0]) << 8); + temp = temp | (((long)samples8[1]) << 16); + temp = temp | (((long)samples8[2]) << 24); + output[x] = (float)temp * gain; + samples8+=3; + } + } + break; + case 32: + { + gain /= 2147483648.0f; + int32_t *samples32 = (int32_t *)pcm; + for (size_t x = 0; x != num_samples; x ++) + { + output[x] = (float)samples32[x] * gain; + } + } + break; + } + return 0; +} + +int nsutil_pcm_S8ToS16_Interleaved(int16_t *output, const int8_t *pcm, size_t num_samples) +{ + //__m64 mmx_zero = _mm_setzero_si64(); + __m128i sse_zero = _mm_setzero_si128(); + //while (num_samples>7) + while (num_samples > 15) + { + //__m64 mmx_8 = *(const __m64 *)pcm; + __m128i sse_8 = *(const __m128i*)pcm; + //pcm+=8; + pcm += 16; + //__m64 mmx_16 = _mm_unpacklo_pi8(mmx_zero, mmx_8); + __m128i sse_16 = _mm_unpacklo_epi8(sse_zero, sse_8); + //*(__m64 *)output = mmx_16; + *(__m128i*)output = sse_16; + //output+=4; + output += 8; + //mmx_16 = _mm_unpackhi_pi8(mmx_zero, mmx_8); + sse_16 = _mm_unpackhi_epi8(sse_zero, sse_8); + //*(__m64 *)output = mmx_16; + *(__m128i *)output = sse_16; + //output+=4; + output += 8; + //num_samples-=8; + num_samples-=16; + } + while(num_samples--) + { + *output++ = (*pcm++) << 8; + } + //_mm_empty(); + return 0; +} + +int nsutil_pcm_U8ToS16_Interleaved(int16_t *output, const uint8_t *pcm, size_t num_samples) +{ + //__m64 mmx_zero = _mm_setzero_si64(); + __m128i sse_zero = _mm_setzero_si128(); + //__m64 mmx_128 = _mm_set1_pi8(-128); + __m128i sse_128 = _mm_set1_epi8(-128); + //while (num_samples>7) + while (num_samples > 15) + { + //__m64 mmx_8 = *(const __m64*)pcm; + __m128i sse_8 = *(const __m128i *)pcm; + + //mmx_8 = _mm_add_pi8(mmx_8, mmx_128); + sse_8 = _mm_add_epi8(sse_8, sse_128); + + //pcm+=8; + pcm += 16; + //__m64 mmx_16 = _mm_unpacklo_pi8(mmx_zero, mmx_8); + __m128i sse_16 = _mm_unpacklo_epi8(sse_zero, sse_8); + //*(__m64 *)output = mmx_16; + *(__m128i*)output = sse_16; + //output+=4; + output += 8; + //mmx_16 = _mm_unpackhi_pi8(mmx_zero, mmx_8); + sse_16 = _mm_unpackhi_epi8(sse_zero, sse_8); + //*(__m64 *)output = mmx_16; + *(__m128i*)output = sse_16; + //output+=4; + output += 8; + //num_samples-=8; + num_samples -= 16; + } + while(num_samples--) + { + *output++ = (*pcm++ - 128) << 8; + } + //_mm_empty(); + return 0; +}
\ No newline at end of file |