/* * SampleFormatConverters.h * ------------------------ * Purpose: Functions and functors for reading and converting pretty much any uncompressed sample format supported by OpenMPT. * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ #pragma once #include "BuildSettings.h" #include "../common/Endianness.h" OPENMPT_NAMESPACE_BEGIN // Byte offsets, from lowest significant to highest significant byte (for various functor template parameters) #define littleEndian64 0, 1, 2, 3, 4, 5, 6, 7 #define littleEndian32 0, 1, 2, 3 #define littleEndian24 0, 1, 2 #define littleEndian16 0, 1 #define bigEndian64 7, 6, 5, 4, 3, 2, 1, 0 #define bigEndian32 3, 2, 1, 0 #define bigEndian24 2, 1, 0 #define bigEndian16 1, 0 namespace SC { // SC = _S_ample_C_onversion #if MPT_COMPILER_MSVC #define MPT_SC_AVOID_ROUND 1 #else #define MPT_SC_AVOID_ROUND 0 #endif #if MPT_SC_AVOID_ROUND #define MPT_SC_FASTROUND(x) std::floor((x) + 0.5f) #else #define MPT_SC_FASTROUND(x) mpt::round(x) #endif #if MPT_COMPILER_SHIFT_SIGNED #define MPT_SC_RSHIFT_SIGNED(val, shift) ((val) >> (shift)) #define MPT_SC_LSHIFT_SIGNED(val, shift) ((val) << (shift)) #else #define MPT_SC_RSHIFT_SIGNED(val, shift) mpt::rshift_signed((val), (shift)) #define MPT_SC_LSHIFT_SIGNED(val, shift) mpt::lshift_signed((val), (shift)) #endif // Every sample decoding functor has to typedef its input_t and output_t // and has to provide a static constexpr input_inc member // which describes by how many input_t elements inBuf has to be incremented between invocations. // input_inc is normally 1 except when decoding e.g. bigger sample values // from multiple std::byte values. // decodes signed 7bit values stored as signed int8 struct DecodeInt7 { typedef std::byte input_t; typedef int8 output_t; static constexpr std::size_t input_inc = 1; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return Clamp(mpt::byte_cast(*inBuf), static_cast(-64), static_cast(63)) * 2; } }; struct DecodeInt8 { typedef std::byte input_t; typedef int8 output_t; static constexpr std::size_t input_inc = 1; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return mpt::byte_cast(*inBuf); } }; struct DecodeUint8 { typedef std::byte input_t; typedef int8 output_t; static constexpr std::size_t input_inc = 1; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return static_cast(int(mpt::byte_cast(*inBuf)) - 128); } }; struct DecodeInt8Delta { typedef std::byte input_t; typedef int8 output_t; static constexpr std::size_t input_inc = 1; uint8 delta; DecodeInt8Delta() : delta(0) { } MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { delta += mpt::byte_cast(*inBuf); return static_cast(delta); } }; template struct DecodeInt16 { typedef std::byte input_t; typedef int16 output_t; static constexpr std::size_t input_inc = 2; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return (mpt::byte_cast(inBuf[loByteIndex]) | (mpt::byte_cast(inBuf[hiByteIndex]) << 8)) - offset; } }; template struct DecodeInt16Delta { typedef std::byte input_t; typedef int16 output_t; static constexpr std::size_t input_inc = 2; uint16 delta; DecodeInt16Delta() : delta(0) { } MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { delta += mpt::byte_cast(inBuf[loByteIndex]) | (mpt::byte_cast(inBuf[hiByteIndex]) << 8); return static_cast(delta); } }; struct DecodeInt16Delta8 { typedef std::byte input_t; typedef int16 output_t; static constexpr std::size_t input_inc = 2; uint16 delta; DecodeInt16Delta8() : delta(0) { } MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { delta += mpt::byte_cast(inBuf[0]); int16 result = delta & 0xFF; delta += mpt::byte_cast(inBuf[1]); result |= (delta << 8); return result; } }; template struct DecodeInt24 { typedef std::byte input_t; typedef int32 output_t; static constexpr std::size_t input_inc = 3; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return ((mpt::byte_cast(inBuf[loByteIndex]) << 8) | (mpt::byte_cast(inBuf[midByteIndex]) << 16) | (mpt::byte_cast(inBuf[hiByteIndex]) << 24)) - offset; } }; template struct DecodeInt32 { typedef std::byte input_t; typedef int32 output_t; static constexpr std::size_t input_inc = 4; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return (mpt::byte_cast(inBuf[loLoByteIndex]) | (mpt::byte_cast(inBuf[loHiByteIndex]) << 8) | (mpt::byte_cast(inBuf[hiLoByteIndex]) << 16) | (mpt::byte_cast(inBuf[hiHiByteIndex]) << 24)) - offset; } }; template struct DecodeInt64 { typedef std::byte input_t; typedef int64 output_t; static constexpr std::size_t input_inc = 8; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return (uint64(0) | (static_cast(mpt::byte_cast(inBuf[b0])) << 0) | (static_cast(mpt::byte_cast(inBuf[b1])) << 8) | (static_cast(mpt::byte_cast(inBuf[b2])) << 16) | (static_cast(mpt::byte_cast(inBuf[b3])) << 24) | (static_cast(mpt::byte_cast(inBuf[b4])) << 32) | (static_cast(mpt::byte_cast(inBuf[b5])) << 40) | (static_cast(mpt::byte_cast(inBuf[b6])) << 48) | (static_cast(mpt::byte_cast(inBuf[b7])) << 56) ) - offset; } }; template struct DecodeFloat32 { typedef std::byte input_t; typedef float32 output_t; static constexpr std::size_t input_inc = 4; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { float32 val = IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]); val = mpt::sanitize_nan(val); if(std::isinf(val)) { if(val >= 0.0f) { val = 1.0f; } else { val = -1.0f; } } return val; } }; template struct DecodeScaledFloat32 { typedef std::byte input_t; typedef float32 output_t; static constexpr std::size_t input_inc = 4; float factor; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { float32 val = IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]); val = mpt::sanitize_nan(val); if(std::isinf(val)) { if(val >= 0.0f) { val = 1.0f; } else { val = -1.0f; } } return factor * val; } MPT_FORCEINLINE DecodeScaledFloat32(float scaleFactor) : factor(scaleFactor) { return; } }; template struct DecodeFloat64 { typedef std::byte input_t; typedef float64 output_t; static constexpr std::size_t input_inc = 8; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { float64 val = IEEE754binary64LE(inBuf[b0], inBuf[b1], inBuf[b2], inBuf[b3], inBuf[b4], inBuf[b5], inBuf[b6], inBuf[b7]); val = mpt::sanitize_nan(val); if(std::isinf(val)) { if(val >= 0.0) { val = 1.0; } else { val = -1.0; } } return val; } }; template struct DecodeIdentity { typedef Tsample input_t; typedef Tsample output_t; static constexpr std::size_t input_inc = 1; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return *inBuf; } }; // Shift input_t down by shift and saturate to output_t. template struct ConvertShift { typedef Tsrc input_t; typedef Tdst output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return mpt::saturate_cast(MPT_SC_RSHIFT_SIGNED(val, shift)); } }; // Shift input_t up by shift and saturate to output_t. template struct ConvertShiftUp { typedef Tsrc input_t; typedef Tdst output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return mpt::saturate_cast(MPT_SC_LSHIFT_SIGNED(val, shift)); } }; // Every sample conversion functor has to typedef its input_t and output_t. // The input_t argument is taken by value because we only deal with per-single-sample conversions here. // straight forward type conversions, clamping when converting from floating point. template struct Convert; template struct Convert { typedef Tid input_t; typedef Tid output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val; } }; template <> struct Convert { typedef int8 input_t; typedef uint8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(val+0x80); } }; template <> struct Convert { typedef int16 input_t; typedef uint8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(static_cast(MPT_SC_RSHIFT_SIGNED(val, 8))+0x80); } }; template <> struct Convert { typedef int24 input_t; typedef uint8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(static_cast(MPT_SC_RSHIFT_SIGNED(static_cast(val), 16))+0x80); } }; template <> struct Convert { typedef int32 input_t; typedef uint8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(static_cast(MPT_SC_RSHIFT_SIGNED(val, 24))+0x80); } }; template <> struct Convert { typedef int64 input_t; typedef uint8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(static_cast(MPT_SC_RSHIFT_SIGNED(val, 56))+0x80); } }; template <> struct Convert { typedef float32 input_t; typedef uint8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0f, 1.0f); val *= 128.0f; return static_cast(mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val)))+0x80); } }; template <> struct Convert { typedef double input_t; typedef uint8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0, 1.0); val *= 128.0; return static_cast(mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val)))+0x80); } }; template <> struct Convert { typedef uint8 input_t; typedef int8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(static_cast(val)-0x80); } }; template <> struct Convert { typedef int16 input_t; typedef int8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(val, 8)); } }; template <> struct Convert { typedef int24 input_t; typedef int8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(static_cast(val), 16)); } }; template <> struct Convert { typedef int32 input_t; typedef int8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(val, 24)); } }; template <> struct Convert { typedef int64 input_t; typedef int8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(val, 56)); } }; template <> struct Convert { typedef float32 input_t; typedef int8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0f, 1.0f); val *= 128.0f; return mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val))); } }; template <> struct Convert { typedef double input_t; typedef int8 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0, 1.0); val *= 128.0; return mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val))); } }; template <> struct Convert { typedef uint8 input_t; typedef int16 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(static_cast(val)-0x80, 8)); } }; template <> struct Convert { typedef int8 input_t; typedef int16 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(val, 8)); } }; template <> struct Convert { typedef int24 input_t; typedef int16 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(static_cast(val), 8)); } }; template <> struct Convert { typedef int32 input_t; typedef int16 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(val, 16)); } }; template <> struct Convert { typedef int64 input_t; typedef int16 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(val, 48)); } }; template <> struct Convert { typedef float32 input_t; typedef int16 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0f, 1.0f); val *= 32768.0f; return mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val))); } }; template <> struct Convert { typedef double input_t; typedef int16 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0, 1.0); val *= 32768.0; return mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val))); } }; template <> struct Convert { typedef uint8 input_t; typedef int24 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(static_cast(val)-0x80, 16)); } }; template <> struct Convert { typedef int8 input_t; typedef int24 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(val, 16)); } }; template <> struct Convert { typedef int16 input_t; typedef int24 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(val, 8)); } }; template <> struct Convert { typedef int32 input_t; typedef int24 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(val, 8)); } }; template <> struct Convert { typedef int64 input_t; typedef int24 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(val, 40)); } }; template <> struct Convert { typedef float32 input_t; typedef int24 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0f, 1.0f); val *= 2147483648.0f; return static_cast(MPT_SC_RSHIFT_SIGNED(mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val))), 8)); } }; template <> struct Convert { typedef double input_t; typedef int24 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0, 1.0); val *= 2147483648.0; return static_cast(MPT_SC_RSHIFT_SIGNED(mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val))), 8)); } }; template <> struct Convert { typedef uint8 input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(static_cast(val)-0x80, 24)); } }; template <> struct Convert { typedef int8 input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(val, 24)); } }; template <> struct Convert { typedef int16 input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(val, 16)); } }; template <> struct Convert { typedef int24 input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_LSHIFT_SIGNED(static_cast(val), 8)); } }; template <> struct Convert { typedef int64 input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(MPT_SC_RSHIFT_SIGNED(val, 32)); } }; template <> struct Convert { typedef float32 input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0f, 1.0f); val *= 2147483648.0f; return mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val))); } }; template <> struct Convert { typedef double input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0, 1.0); val *= 2147483648.0; return mpt::saturate_cast(static_cast(MPT_SC_FASTROUND(val))); } }; template <> struct Convert { typedef uint8 input_t; typedef int64 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return MPT_SC_LSHIFT_SIGNED(static_cast(val)-0x80, 56); } }; template <> struct Convert { typedef int8 input_t; typedef int64 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return MPT_SC_LSHIFT_SIGNED(static_cast(val), 56); } }; template <> struct Convert { typedef int16 input_t; typedef int64 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return MPT_SC_LSHIFT_SIGNED(static_cast(val), 48); } }; template <> struct Convert { typedef int24 input_t; typedef int64 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return MPT_SC_LSHIFT_SIGNED(static_cast(val), 40); } }; template <> struct Convert { typedef int32 input_t; typedef int64 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return MPT_SC_LSHIFT_SIGNED(static_cast(val), 32); } }; template <> struct Convert { typedef float32 input_t; typedef int64 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0f, 1.0f); val *= static_cast(uint64(1)<<63); return mpt::saturate_cast(MPT_SC_FASTROUND(val)); } }; template <> struct Convert { typedef double input_t; typedef int64 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { val = mpt::safe_clamp(val, -1.0, 1.0); val *= static_cast(uint64(1)<<63); return mpt::saturate_cast(MPT_SC_FASTROUND(val)); } }; template <> struct Convert { typedef uint8 input_t; typedef float32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return (static_cast(val)-0x80) * (1.0f / static_cast(static_cast(1)<<7)); } }; template <> struct Convert { typedef int8 input_t; typedef float32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0f / static_cast(static_cast(1)<<7)); } }; template <> struct Convert { typedef int16 input_t; typedef float32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0f / static_cast(static_cast(1)<<15)); } }; template <> struct Convert { typedef int24 input_t; typedef float32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0f / static_cast(static_cast(1)<<23)); } }; template <> struct Convert { typedef int32 input_t; typedef float32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0f / static_cast(static_cast(1)<<31)); } }; template <> struct Convert { typedef int64 input_t; typedef float32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0f / static_cast(static_cast(1)<<63)); } }; template <> struct Convert { typedef uint8 input_t; typedef double output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return (static_cast(val)-0x80) * (1.0 / static_cast(static_cast(1)<<7)); } }; template <> struct Convert { typedef int8 input_t; typedef double output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0 / static_cast(static_cast(1)<<7)); } }; template <> struct Convert { typedef int16 input_t; typedef double output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0 / static_cast(static_cast(1)<<15)); } }; template <> struct Convert { typedef int24 input_t; typedef double output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0 / static_cast(static_cast(1)<<23)); } }; template <> struct Convert { typedef int32 input_t; typedef double output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0 / static_cast(static_cast(1)<<31)); } }; template <> struct Convert { typedef int64 input_t; typedef double output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return val * (1.0 / static_cast(static_cast(1)<<63)); } }; template <> struct Convert { typedef float input_t; typedef double output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(val); } }; template <> struct Convert { typedef double input_t; typedef float output_t; MPT_FORCEINLINE output_t operator() (input_t val) { return static_cast(val); } }; template struct ConvertFixedPoint; template struct ConvertFixedPoint { typedef int32 input_t; typedef uint8 output_t; static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); static_assert(shiftBits >= 1); val = MPT_SC_RSHIFT_SIGNED((val + (1<<(shiftBits-1))), shiftBits); // round if(val < int8_min) val = int8_min; if(val > int8_max) val = int8_max; return static_cast(val+0x80); // unsigned } }; template struct ConvertFixedPoint { typedef int32 input_t; typedef int8 output_t; static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); static_assert(shiftBits >= 1); val = MPT_SC_RSHIFT_SIGNED((val + (1<<(shiftBits-1))), shiftBits); // round if(val < int8_min) val = int8_min; if(val > int8_max) val = int8_max; return static_cast(val); } }; template struct ConvertFixedPoint { typedef int32 input_t; typedef int16 output_t; static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); static_assert(shiftBits >= 1); val = MPT_SC_RSHIFT_SIGNED((val + (1<<(shiftBits-1))), shiftBits); // round if(val < int16_min) val = int16_min; if(val > int16_max) val = int16_max; return static_cast(val); } }; template struct ConvertFixedPoint { typedef int32 input_t; typedef int24 output_t; static constexpr int shiftBits = fractionalBits + 1 - sizeof(output_t) * 8; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); static_assert(shiftBits >= 1); val = MPT_SC_RSHIFT_SIGNED((val + (1<<(shiftBits-1))), shiftBits); // round if(val < int24_min) val = int24_min; if(val > int24_max) val = int24_max; return static_cast(val); } }; template struct ConvertFixedPoint { typedef int32 input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); return static_cast(Clamp(val, static_cast(-((1<(1< struct ConvertFixedPoint { typedef int32 input_t; typedef float32 output_t; const float factor; MPT_FORCEINLINE ConvertFixedPoint() : factor( 1.0f / static_cast(1 << fractionalBits) ) { return; } MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); return val * factor; } }; template struct ConvertFixedPoint { typedef int32 input_t; typedef float64 output_t; const double factor; MPT_FORCEINLINE ConvertFixedPoint() : factor( 1.0 / static_cast(1 << fractionalBits) ) { return; } MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); return val * factor; } }; template struct ConvertToFixedPoint; template struct ConvertToFixedPoint { typedef uint8 input_t; typedef int32 output_t; static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1); static_assert(shiftBits >= 1); return MPT_SC_LSHIFT_SIGNED(static_cast(static_cast(val)-0x80), shiftBits); } }; template struct ConvertToFixedPoint { typedef int8 input_t; typedef int32 output_t; static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1); static_assert(shiftBits >= 1); return MPT_SC_LSHIFT_SIGNED(static_cast(val), shiftBits); } }; template struct ConvertToFixedPoint { typedef int16 input_t; typedef int32 output_t; static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1); static_assert(shiftBits >= 1); return MPT_SC_LSHIFT_SIGNED(static_cast(val), shiftBits); } }; template struct ConvertToFixedPoint { typedef int24 input_t; typedef int32 output_t; static constexpr int shiftBits = fractionalBits + 1 - sizeof(input_t) * 8; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1); static_assert(shiftBits >= 1); return MPT_SC_LSHIFT_SIGNED(static_cast(val), shiftBits); } }; template struct ConvertToFixedPoint { typedef int32 input_t; typedef int32 output_t; MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1); return MPT_SC_RSHIFT_SIGNED(static_cast(val), (sizeof(input_t)*8-1-fractionalBits)); } }; template struct ConvertToFixedPoint { typedef float32 input_t; typedef int32 output_t; const float factor; MPT_FORCEINLINE ConvertToFixedPoint() : factor( static_cast(1 << fractionalBits) ) { return; } MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); val = mpt::sanitize_nan(val); return mpt::saturate_cast(MPT_SC_FASTROUND(val * factor)); } }; template struct ConvertToFixedPoint { typedef float64 input_t; typedef int32 output_t; const double factor; MPT_FORCEINLINE ConvertToFixedPoint() : factor( static_cast(1 << fractionalBits) ) { return; } MPT_FORCEINLINE output_t operator() (input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1); val = mpt::sanitize_nan(val); return mpt::saturate_cast(MPT_SC_FASTROUND(val * factor)); } }; // Reads sample data with Func and passes it directly to Func2. // Func1::output_t and Func2::input_t must be identical template struct ConversionChain { typedef typename Func1::input_t input_t; typedef typename Func2::output_t output_t; static constexpr std::size_t input_inc = Func1::input_inc; Func1 func1; Func2 func2; MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return func2(func1(inBuf)); } MPT_FORCEINLINE ConversionChain(Func2 f2 = Func2(), Func1 f1 = Func1()) : func1(f1) , func2(f2) { return; } }; template struct ClipFixed { typedef Tfixed input_t; typedef Tfixed output_t; MPT_FORCEINLINE Tfixed operator() (Tfixed val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t)*8-1); if constexpr(clipOutput) { constexpr Tfixed clip_max = (Tfixed(1) << fractionalBits) - Tfixed(1); constexpr Tfixed clip_min = Tfixed(0) - (Tfixed(1) << fractionalBits); if(val < clip_min) val = clip_min; if(val > clip_max) val = clip_max; return val; } else { return val; } } }; template struct ClipFloat; template struct ClipFloat { typedef float input_t; typedef float output_t; MPT_FORCEINLINE float operator() (float val) { if constexpr(clipOutput) { if(val < -1.0f) val = -1.0f; if(val > 1.0f) val = 1.0f; return val; } else { return val; } } }; template struct ClipFloat { typedef double input_t; typedef double output_t; MPT_FORCEINLINE double operator() (double val) { if constexpr(clipOutput) { if(val < -1.0) val = -1.0; if(val > 1.0) val = 1.0; return val; } else { return val; } } }; template struct Normalize; template <> struct Normalize { typedef int32 input_t; typedef int32 output_t; typedef uint32 peak_t; uint32 maxVal; MPT_FORCEINLINE Normalize() : maxVal(0) { } MPT_FORCEINLINE void FindMax(input_t val) { if(val < 0) { if(val == int32_min) { maxVal = static_cast(-static_cast(int32_min)); return; } val = -val; } if(static_cast(val) > maxVal) { maxVal = static_cast(val); } } MPT_FORCEINLINE bool IsSilent() const { return maxVal == 0; } MPT_FORCEINLINE output_t operator() (input_t val) { return Util::muldivrfloor(val, static_cast(1) << 31, maxVal); } MPT_FORCEINLINE peak_t GetSrcPeak() const { return maxVal; } }; template <> struct Normalize { typedef float32 input_t; typedef float32 output_t; typedef float32 peak_t; float maxVal; float maxValInv; MPT_FORCEINLINE Normalize() : maxVal(0.0f), maxValInv(1.0f) { } MPT_FORCEINLINE void FindMax(input_t val) { float absval = std::fabs(val); if(absval > maxVal) { maxVal = absval; } } MPT_FORCEINLINE bool IsSilent() { if(maxVal == 0.0f) { maxValInv = 1.0f; return true; } else { maxValInv = 1.0f / maxVal; return false; } } MPT_FORCEINLINE output_t operator() (input_t val) { return val * maxValInv; } MPT_FORCEINLINE peak_t GetSrcPeak() const { return maxVal; } }; template <> struct Normalize { typedef float64 input_t; typedef float64 output_t; typedef float64 peak_t; double maxVal; double maxValInv; MPT_FORCEINLINE Normalize() : maxVal(0.0), maxValInv(1.0) { } MPT_FORCEINLINE void FindMax(input_t val) { double absval = std::fabs(val); if(absval > maxVal) { maxVal = absval; } } MPT_FORCEINLINE bool IsSilent() { if(maxVal == 0.0) { maxValInv = 1.0; return true; } else { maxValInv = 1.0 / maxVal; return false; } } MPT_FORCEINLINE output_t operator() (input_t val) { return val * maxValInv; } MPT_FORCEINLINE peak_t GetSrcPeak() const { return maxVal; } }; // Reads sample data with Func1, then normalizes the sample data, and then converts it with Func2. // Func1::output_t and Func2::input_t must be identical. // Func1 can also be the identity decode (DecodeIdentity). // Func2 can also be the identity conversion (Convert). template struct NormalizationChain { typedef typename Func1::input_t input_t; typedef typename Func1::output_t normalize_t; typedef typename Normalize::peak_t peak_t; typedef typename Func2::output_t output_t; static constexpr std::size_t input_inc = Func1::input_inc; Func1 func1; Normalize normalize; Func2 func2; MPT_FORCEINLINE void FindMax(const input_t *inBuf) { normalize.FindMax(func1(inBuf)); } MPT_FORCEINLINE bool IsSilent() { return normalize.IsSilent(); } MPT_FORCEINLINE output_t operator() (const input_t *inBuf) { return func2(normalize(func1(inBuf))); } MPT_FORCEINLINE peak_t GetSrcPeak() const { return normalize.GetSrcPeak(); } MPT_FORCEINLINE NormalizationChain(Func2 f2 = Func2(), Func1 f1 = Func1()) : func1(f1) , func2(f2) { return; } }; #undef MPT_SC_RSHIFT_SIGNED #undef MPT_SC_LSHIFT_SIGNED #undef MPT_SC_FASTROUND } // namespace SC OPENMPT_NAMESPACE_END