From: <man...@us...> - 2013-06-08 19:03:30
|
Revision: 2329 http://sourceforge.net/p/modplug/code/2329 Author: manxorist Date: 2013-06-08 19:03:21 +0000 (Sat, 08 Jun 2013) Log Message: ----------- [Fix] Correct truncation/rounding in C versions of output sample format converter functions. [Ref] Use overloading instead of function names to select the proper conversion function. [Ref] Tag the names of the old conversion functions with "Interleaved". [Ref] Move the declarations into Sndfile.h instead of duplicating them in multiple cpp files. Modified Paths: -------------- trunk/OpenMPT/common/typedefs.h trunk/OpenMPT/soundlib/Fastmix.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp trunk/OpenMPT/soundlib/Waveform.cpp Modified: trunk/OpenMPT/common/typedefs.h =================================================================== --- trunk/OpenMPT/common/typedefs.h 2013-06-08 18:11:19 UTC (rev 2328) +++ trunk/OpenMPT/common/typedefs.h 2013-06-08 19:03:21 UTC (rev 2329) @@ -234,6 +234,8 @@ } }; STATIC_ASSERT(sizeof(int24) == 3); +#define int24_min (0-0x00800000) +#define int24_max (0+0x007fffff) typedef float float32; STATIC_ASSERT(sizeof(float32) == 4); Modified: trunk/OpenMPT/soundlib/Fastmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Fastmix.cpp 2013-06-08 18:11:19 UTC (rev 2328) +++ trunk/OpenMPT/soundlib/Fastmix.cpp 2013-06-08 19:03:21 UTC (rev 2329) @@ -1728,13 +1728,71 @@ ////////////////////////////////////////////////////////////////////////////////////////// +template<typename Tsample> +forceinline Tsample ConvertSample(int val) +{ + STATIC_ASSERT(false); // unimplemented +} +template<> +forceinline uint8 ConvertSample(int val) +{ + val = (val + (1<<(23-MIXING_ATTENUATION))) >> (24-MIXING_ATTENUATION); + if(val < int8_min) val = int8_min; + if(val > int8_max) val = int8_max; + return (uint8)(val+0x80); // unsigned +} +template<> +forceinline int16 ConvertSample(int val) +{ + val = (val + (1<<(15-MIXING_ATTENUATION))) >> (16-MIXING_ATTENUATION); + if(val < int16_min) val = int16_min; + if(val > int16_max) val = int16_max; + return (int16)val; +} +template<> +forceinline int24 ConvertSample(int val) +{ + val = (val + (1<<(7-MIXING_ATTENUATION))) >> (8-MIXING_ATTENUATION); + if(val < int24_min) val = int24_min; + if(val > int24_max) val = int24_max; + return (int24)val; +} +template<> +forceinline int32 ConvertSample(int val) +{ + return (int32)(Clamp(val, (int)MIXING_CLIPMIN, (int)MIXING_CLIPMAX) << MIXING_ATTENUATION); +} + +template<typename Tsample> +forceinline void C_Convert32ToInterleaved(Tsample *p, const int *mixbuffer, std::size_t count) +{ + for(std::size_t i = 0; i < count; ++i) + { + p[i] = ConvertSample<Tsample>(mixbuffer[i]); + } +} + +template<typename Tsample> +forceinline void C_Convert32ToNonInterleaved(Tsample * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count) +{ + for(std::size_t i = 0; i < count; ++i) + { + for(std::size_t channel = 0; channel < channels; ++channel) + { + buffers[channel][i] = ConvertSample<Tsample>(*mixbuffer); + mixbuffer++; + } + } +} + + #ifdef ENABLE_X86 -static void X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//------------------------------------------------------------------------- +static void X86_Convert32To8(uint8 *lp8, const int *pBuffer, DWORD lSampleCount) +//------------------------------------------------------------------------------ { _asm { - mov ebx, lp16 // ebx = 8-bit buffer + mov ebx, lp8 // ebx = 8-bit buffer mov edx, pBuffer // edx = pBuffer mov edi, lSampleCount // edi = lSampleCount cliploop: @@ -1764,50 +1822,27 @@ } #endif -static void C_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//----------------------------------------------------------------------- -{ - uint8 * p = (uint8*)lp16; - for(DWORD i=0; i<lSampleCount; i++) - { - int v = pBuffer[i]; - if(v < MIXING_CLIPMIN) v = MIXING_CLIPMIN; - else if(v > MIXING_CLIPMAX) v = MIXING_CLIPMAX; - p[i] = (uint8)((v >> (24-MIXING_ATTENUATION))+0x80); // unsigned - } -} - // Clip and convert to 8 bit -void Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//-------------------------------------------------------------- +void Convert32ToInterleaved(uint8 *dest, const int *mixbuffer, std::size_t count) +//------------------------------------------------------------------------------- { #ifdef ENABLE_X86 - X86_Convert32To8(lp16, pBuffer, lSampleCount); + X86_Convert32To8(dest, mixbuffer, count); #else - C_Convert32To8(lp16, pBuffer, lSampleCount); + C_Convert32ToInterleaved(dest, mixbuffer, count); #endif } void Convert32ToNonInterleaved(uint8 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count) //-------------------------------------------------------------------------------------------------------------------------- { - for(std::size_t i = 0; i < count; ++i) - { - for(std::size_t channel = 0; channel < channels; ++channel) - { - int v = *mixbuffer; - if(v < MIXING_CLIPMIN) v = MIXING_CLIPMIN; - else if(v > MIXING_CLIPMAX) v = MIXING_CLIPMAX; - buffers[channel][i] = (uint8)((v >> (24-MIXING_ATTENUATION))+0x80); // unsigned - mixbuffer++; - } - } + C_Convert32ToNonInterleaved(buffers, mixbuffer, channels, count); } #ifdef ENABLE_X86 -static void X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//-------------------------------------------------------------------------- +static void X86_Convert32To16(int16 *lp16, const int *pBuffer, DWORD lSampleCount) +//-------------------------------------------------------------------------------- { _asm { mov ebx, lp16 // ebx = 16-bit buffer @@ -1839,50 +1874,30 @@ } #endif -static void C_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//------------------------------------------------------------------------ -{ - int16 * p = (int16*)lp16; - for(DWORD i=0; i<lSampleCount; i++) - { - int v = pBuffer[i]; - if(v < MIXING_CLIPMIN) v = MIXING_CLIPMIN; - else if(v > MIXING_CLIPMAX) v = MIXING_CLIPMAX; - p[i] = (int16)(v >> (16-MIXING_ATTENUATION)); - } -} - // Clip and convert to 16 bit -void Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//--------------------------------------------------------------- +void Convert32ToInterleaved(int16 *dest, const int *mixbuffer, std::size_t count) +//------------------------------------------------------------------------------- { #ifdef ENABLE_X86 - X86_Convert32To16(lp16, pBuffer, lSampleCount); + X86_Convert32To16(dest, mixbuffer, count); #else - C_Convert32To16(lp16, pBuffer, lSampleCount); + C_Convert32ToInterleaved(dest, mixbuffer, count); #endif } void Convert32ToNonInterleaved(int16 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count) //-------------------------------------------------------------------------------------------------------------------------- { - for(std::size_t i = 0; i < count; ++i) - { - for(std::size_t channel = 0; channel < channels; ++channel) - { - buffers[channel][i] = (int16)(Clamp(*mixbuffer, (int)MIXING_CLIPMIN, (int)MIXING_CLIPMAX) >> (16-MIXING_ATTENUATION)); - mixbuffer++; - } - } + C_Convert32ToNonInterleaved(buffers, mixbuffer, channels, count); } #ifdef ENABLE_X86 -static void X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//-------------------------------------------------------------------------- +static void X86_Convert32To24(int24 *lp24, const int *pBuffer, DWORD lSampleCount) +//-------------------------------------------------------------------------------- { _asm { - mov ebx, lp16 // ebx = 8-bit buffer + mov ebx, lp24 // ebx = 24-bit buffer mov edx, pBuffer // edx = pBuffer mov edi, lSampleCount // edi = lSampleCount cliploop: @@ -1913,51 +1928,30 @@ } #endif -static void C_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//------------------------------------------------------------------------ -{ - int24 * p = (int24*)lp16; - for(DWORD i=0; i<lSampleCount; i++) - { - int v = pBuffer[i]; - if(v < MIXING_CLIPMIN) v = MIXING_CLIPMIN; - else if(v > MIXING_CLIPMAX) v = MIXING_CLIPMAX; - v >>= (8-MIXING_ATTENUATION); - p[i] = (int24)v; - } -} - // Clip and convert to 24 bit -void Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//--------------------------------------------------------------- +void Convert32ToInterleaved(int24 *dest, const int *mixbuffer, std::size_t count) +//------------------------------------------------------------------------------- { #ifdef ENABLE_X86 - X86_Convert32To24(lp16, pBuffer, lSampleCount); + X86_Convert32To24(dest, mixbuffer, count); #else - C_Convert32To24(lp16, pBuffer, lSampleCount); + C_Convert32ToInterleaved(dest, mixbuffer, count); #endif } void Convert32ToNonInterleaved(int24 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count) //-------------------------------------------------------------------------------------------------------------------------- { - for(std::size_t i = 0; i < count; ++i) - { - for(std::size_t channel = 0; channel < channels; ++channel) - { - buffers[channel][i] = (int24)(Clamp(*mixbuffer, (int)MIXING_CLIPMIN, (int)MIXING_CLIPMAX) >> (8-MIXING_ATTENUATION)); - mixbuffer++; - } - } + C_Convert32ToNonInterleaved(buffers, mixbuffer, channels, count); } #ifdef ENABLE_X86 -static void X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//-------------------------------------------------------------------------- +static void X86_Convert32To32(int32 *lp32, const int *pBuffer, DWORD lSampleCount) +//-------------------------------------------------------------------------------- { _asm { - mov ebx, lp16 // ebx = 32-bit buffer + mov ebx, lp32 // ebx = 32-bit buffer mov edx, pBuffer // edx = pBuffer mov edi, lSampleCount // edi = lSampleCount cliploop: @@ -1985,53 +1979,32 @@ } #endif -static void C_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//------------------------------------------------------------------------ -{ - int32 * p = (int32*)lp16; - for(DWORD i=0; i<lSampleCount; i++) - { - int v = pBuffer[i]; - if(v < MIXING_CLIPMIN) v = MIXING_CLIPMIN; - else if(v > MIXING_CLIPMAX) v = MIXING_CLIPMAX; - p[i] = v << MIXING_ATTENUATION; - } -} - // Clip and convert to 32 bit -void Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount) -//--------------------------------------------------------------- +void Convert32ToInterleaved(int32 *dest, const int *mixbuffer, std::size_t count) +//------------------------------------------------------------------------------- { #ifdef ENABLE_X86 - X86_Convert32To32(lp16, pBuffer, lSampleCount); + X86_Convert32To32(dest, mixbuffer, count); #else - C_Convert32To32(lp16, pBuffer, lSampleCount); + C_Convert32ToInterleaved(dest, mixbuffer, count); #endif } void Convert32ToNonInterleaved(int32 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count) //-------------------------------------------------------------------------------------------------------------------------- { - for(std::size_t i = 0; i < count; ++i) - { - for(std::size_t channel = 0; channel < channels; ++channel) - { - buffers[channel][i] = (int32)(Clamp(*mixbuffer, (int)MIXING_CLIPMIN, (int)MIXING_CLIPMAX) << MIXING_ATTENUATION); - mixbuffer++; - } - } + C_Convert32ToNonInterleaved(buffers, mixbuffer, channels, count); } // convert to 32 bit floats and do NOT clip to [-1,1] -void Convert32ToFloat32(LPVOID lpBuffer, int *pBuffer, DWORD lSampleCount) -//------------------------------------------------------------------------ +void Convert32ToInterleaved(float *dest, const int *mixbuffer, std::size_t count) +//------------------------------------------------------------------------------- { const float factor = (1.0f/(float)MIXING_CLIPMAX); - float *out = (float*)lpBuffer; - for(DWORD i=0; i<lSampleCount; i++) + for(std::size_t i=0; i<count; i++) { - out[i] = pBuffer[i] * factor; + dest[i] = mixbuffer[i] * factor; } } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2013-06-08 18:11:19 UTC (rev 2328) +++ trunk/OpenMPT/soundlib/Sndfile.h 2013-06-08 19:03:21 UTC (rev 2329) @@ -191,7 +191,19 @@ void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount, const float _i2fc); void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount, const float _f2ic); +void Convert32ToInterleaved(uint8 *dest, const int *mixbuffer, std::size_t count); +void Convert32ToInterleaved(int16 *dest, const int *mixbuffer, std::size_t count); +void Convert32ToInterleaved(int24 *dest, const int *mixbuffer, std::size_t count); +void Convert32ToInterleaved(int32 *dest, const int *mixbuffer, std::size_t count); +void Convert32ToInterleaved(float *dest, const int *mixbuffer, std::size_t count); +void Convert32ToNonInterleaved(uint8 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); +void Convert32ToNonInterleaved(int16 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); +void Convert32ToNonInterleaved(int24 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); +void Convert32ToNonInterleaved(int32 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); +void Convert32ToNonInterleaved(float * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); + + #if MPT_COMPILER_MSVC #pragma warning(disable:4324) //structure was padded due to __declspec(align()) #endif Modified: trunk/OpenMPT/soundlib/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2013-06-08 18:11:19 UTC (rev 2328) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2013-06-08 19:03:21 UTC (rev 2329) @@ -35,18 +35,12 @@ typedef void (* LPCONVERTPROC)(LPVOID, int *, DWORD); -extern void Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples); -extern void Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples); -extern void Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples); -extern void Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples); -extern void Convert32ToFloat32(LPVOID lpBuffer, int *pBuffer, DWORD lSampleCount); +static void Convert32To8( LPVOID lpBuffer, int *pBuffer, DWORD nSamples) { return Convert32ToInterleaved((uint8*)lpBuffer, pBuffer, nSamples); } +static void Convert32To16(LPVOID lpBuffer, int *pBuffer, DWORD nSamples) { return Convert32ToInterleaved((int16*)lpBuffer, pBuffer, nSamples); } +static void Convert32To24(LPVOID lpBuffer, int *pBuffer, DWORD nSamples) { return Convert32ToInterleaved((int24*)lpBuffer, pBuffer, nSamples); } +static void Convert32To32(LPVOID lpBuffer, int *pBuffer, DWORD nSamples) { return Convert32ToInterleaved((int32*)lpBuffer, pBuffer, nSamples); } +static void Convert32ToFloat32(LPVOID lpBuffer, int *pBuffer, DWORD nSamples) { return Convert32ToInterleaved((float*)lpBuffer, pBuffer, nSamples); } -extern void Convert32ToNonInterleaved(uint8 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); -extern void Convert32ToNonInterleaved(int16 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); -extern void Convert32ToNonInterleaved(int24 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); -extern void Convert32ToNonInterleaved(int32 * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); -extern void Convert32ToNonInterleaved(float * const * const buffers, const int *mixbuffer, std::size_t channels, std::size_t count); - template<typename Tsample> void Convert32ToNonInterleaved(void * const *outputBuffers, std::size_t offset, const int *mixbuffer, std::size_t channels, std::size_t count) { Modified: trunk/OpenMPT/soundlib/Waveform.cpp =================================================================== --- trunk/OpenMPT/soundlib/Waveform.cpp 2013-06-08 18:11:19 UTC (rev 2328) +++ trunk/OpenMPT/soundlib/Waveform.cpp 2013-06-08 19:03:21 UTC (rev 2329) @@ -54,9 +54,6 @@ #endif extern void Dither(int *pBuffer, UINT nSamples, UINT nBits); -extern void Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples); -extern void Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples); -extern void Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples); UINT CSoundFile::Normalize24BitBuffer(LPBYTE pbuffer, UINT dwSize, DWORD lmax24, DWORD dwByteInc) //----------------------------------------------------------------------------------------------- @@ -71,9 +68,9 @@ Dither(tempbuf, nbuf, 8 * dwByteInc); switch(dwByteInc) { - case 2: Convert32To16(pbuffer, tempbuf, nbuf); break; - case 3: Convert32To24(pbuffer, tempbuf, nbuf); break; - default: Convert32To8(pbuffer, tempbuf, nbuf); break; + case 1: Convert32ToInterleaved((uint8*)pbuffer, tempbuf, nbuf); break; + case 2: Convert32ToInterleaved((int16*)pbuffer, tempbuf, nbuf); break; + case 3: Convert32ToInterleaved((int24*)pbuffer, tempbuf, nbuf); break; } n -= nbuf; pbuffer += dwByteInc * nbuf; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |