cog/Frameworks/OpenMPT.old/OpenMPT/soundbase/SampleFormatConverters.h

1442 lines
33 KiB
C++

/*
* 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<int8>(*inBuf), static_cast<int8>(-64), static_cast<int8>(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<int8>(*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<int8>(int(mpt::byte_cast<uint8>(*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<uint8>(*inBuf);
return static_cast<int8>(delta);
}
};
template <uint16 offset, size_t loByteIndex, size_t hiByteIndex>
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<uint8>(inBuf[loByteIndex]) | (mpt::byte_cast<uint8>(inBuf[hiByteIndex]) << 8)) - offset;
}
};
template <size_t loByteIndex, size_t hiByteIndex>
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<uint8>(inBuf[loByteIndex]) | (mpt::byte_cast<uint8>(inBuf[hiByteIndex]) << 8);
return static_cast<int16>(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<uint8>(inBuf[0]);
int16 result = delta & 0xFF;
delta += mpt::byte_cast<uint8>(inBuf[1]);
result |= (delta << 8);
return result;
}
};
template <uint32 offset, size_t loByteIndex, size_t midByteIndex, size_t hiByteIndex>
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<uint8>(inBuf[loByteIndex]) << 8) | (mpt::byte_cast<uint8>(inBuf[midByteIndex]) << 16) | (mpt::byte_cast<uint8>(inBuf[hiByteIndex]) << 24)) - offset;
}
};
template <uint32 offset, size_t loLoByteIndex, size_t loHiByteIndex, size_t hiLoByteIndex, size_t hiHiByteIndex>
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<uint8>(inBuf[loLoByteIndex]) | (mpt::byte_cast<uint8>(inBuf[loHiByteIndex]) << 8) | (mpt::byte_cast<uint8>(inBuf[hiLoByteIndex]) << 16) | (mpt::byte_cast<uint8>(inBuf[hiHiByteIndex]) << 24)) - offset;
}
};
template <uint64 offset, size_t b0, size_t b1, size_t b2, size_t b3, size_t b4, size_t b5, size_t b6, size_t b7>
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<uint64>(mpt::byte_cast<uint8>(inBuf[b0])) << 0)
| (static_cast<uint64>(mpt::byte_cast<uint8>(inBuf[b1])) << 8)
| (static_cast<uint64>(mpt::byte_cast<uint8>(inBuf[b2])) << 16)
| (static_cast<uint64>(mpt::byte_cast<uint8>(inBuf[b3])) << 24)
| (static_cast<uint64>(mpt::byte_cast<uint8>(inBuf[b4])) << 32)
| (static_cast<uint64>(mpt::byte_cast<uint8>(inBuf[b5])) << 40)
| (static_cast<uint64>(mpt::byte_cast<uint8>(inBuf[b6])) << 48)
| (static_cast<uint64>(mpt::byte_cast<uint8>(inBuf[b7])) << 56)
) - offset;
}
};
template <size_t loLoByteIndex, size_t loHiByteIndex, size_t hiLoByteIndex, size_t hiHiByteIndex>
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)
{
return IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]);
}
};
template <size_t loLoByteIndex, size_t loHiByteIndex, size_t hiLoByteIndex, size_t hiHiByteIndex>
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)
{
return factor * IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]);
}
MPT_FORCEINLINE DecodeScaledFloat32(float scaleFactor)
: factor(scaleFactor)
{
return;
}
};
template <size_t b0, size_t b1, size_t b2, size_t b3, size_t b4, size_t b5, size_t b6, size_t b7>
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)
{
return IEEE754binary64LE(inBuf[b0], inBuf[b1], inBuf[b2], inBuf[b3], inBuf[b4], inBuf[b5], inBuf[b6], inBuf[b7]);
}
};
template <typename Tsample>
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 <typename Tdst, typename Tsrc, int shift>
struct ConvertShift
{
typedef Tsrc input_t;
typedef Tdst output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return mpt::saturate_cast<output_t>(MPT_SC_RSHIFT_SIGNED(val, shift));
}
};
// Shift input_t up by shift and saturate to output_t.
template <typename Tdst, typename Tsrc, int shift>
struct ConvertShiftUp
{
typedef Tsrc input_t;
typedef Tdst output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return mpt::saturate_cast<output_t>(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 <typename Tdst, typename Tsrc>
struct Convert;
template <typename Tid>
struct Convert<Tid, Tid>
{
typedef Tid input_t;
typedef Tid output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val;
}
};
template <>
struct Convert<uint8, int8>
{
typedef int8 input_t;
typedef uint8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<uint8>(val+0x80);
}
};
template <>
struct Convert<uint8, int16>
{
typedef int16 input_t;
typedef uint8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<uint8>(static_cast<int8>(MPT_SC_RSHIFT_SIGNED(val, 8))+0x80);
}
};
template <>
struct Convert<uint8, int24>
{
typedef int24 input_t;
typedef uint8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<uint8>(static_cast<int8>(MPT_SC_RSHIFT_SIGNED(static_cast<int>(val), 16))+0x80);
}
};
template <>
struct Convert<uint8, int32>
{
typedef int32 input_t;
typedef uint8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<uint8>(static_cast<int8>(MPT_SC_RSHIFT_SIGNED(val, 24))+0x80);
}
};
template <>
struct Convert<uint8, int64>
{
typedef int64 input_t;
typedef uint8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<uint8>(static_cast<int8>(MPT_SC_RSHIFT_SIGNED(val, 56))+0x80);
}
};
template <>
struct Convert<uint8, float32>
{
typedef float32 input_t;
typedef uint8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0f, 1.0f);
val *= 128.0f;
return static_cast<uint8>(mpt::saturate_cast<int8>(static_cast<int>(MPT_SC_FASTROUND(val)))+0x80);
}
};
template <>
struct Convert<uint8, double>
{
typedef double input_t;
typedef uint8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0, 1.0);
val *= 128.0;
return static_cast<uint8>(mpt::saturate_cast<int8>(static_cast<int>(MPT_SC_FASTROUND(val)))+0x80);
}
};
template <>
struct Convert<int8, uint8>
{
typedef uint8 input_t;
typedef int8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int8>(static_cast<int>(val)-0x80);
}
};
template <>
struct Convert<int8, int16>
{
typedef int16 input_t;
typedef int8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int8>(MPT_SC_RSHIFT_SIGNED(val, 8));
}
};
template <>
struct Convert<int8, int24>
{
typedef int24 input_t;
typedef int8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int8>(MPT_SC_RSHIFT_SIGNED(static_cast<int>(val), 16));
}
};
template <>
struct Convert<int8, int32>
{
typedef int32 input_t;
typedef int8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int8>(MPT_SC_RSHIFT_SIGNED(val, 24));
}
};
template <>
struct Convert<int8, int64>
{
typedef int64 input_t;
typedef int8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int8>(MPT_SC_RSHIFT_SIGNED(val, 56));
}
};
template <>
struct Convert<int8, float32>
{
typedef float32 input_t;
typedef int8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0f, 1.0f);
val *= 128.0f;
return mpt::saturate_cast<int8>(static_cast<int>(MPT_SC_FASTROUND(val)));
}
};
template <>
struct Convert<int8, double>
{
typedef double input_t;
typedef int8 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0, 1.0);
val *= 128.0;
return mpt::saturate_cast<int8>(static_cast<int>(MPT_SC_FASTROUND(val)));
}
};
template <>
struct Convert<int16, uint8>
{
typedef uint8 input_t;
typedef int16 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int16>(MPT_SC_LSHIFT_SIGNED(static_cast<int>(val)-0x80, 8));
}
};
template <>
struct Convert<int16, int8>
{
typedef int8 input_t;
typedef int16 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int16>(MPT_SC_LSHIFT_SIGNED(val, 8));
}
};
template <>
struct Convert<int16, int24>
{
typedef int24 input_t;
typedef int16 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int16>(MPT_SC_RSHIFT_SIGNED(static_cast<int>(val), 8));
}
};
template <>
struct Convert<int16, int32>
{
typedef int32 input_t;
typedef int16 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int16>(MPT_SC_RSHIFT_SIGNED(val, 16));
}
};
template <>
struct Convert<int16, int64>
{
typedef int64 input_t;
typedef int16 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int16>(MPT_SC_RSHIFT_SIGNED(val, 48));
}
};
template <>
struct Convert<int16, float32>
{
typedef float32 input_t;
typedef int16 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0f, 1.0f);
val *= 32768.0f;
return mpt::saturate_cast<int16>(static_cast<int>(MPT_SC_FASTROUND(val)));
}
};
template <>
struct Convert<int16, double>
{
typedef double input_t;
typedef int16 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0, 1.0);
val *= 32768.0;
return mpt::saturate_cast<int16>(static_cast<int>(MPT_SC_FASTROUND(val)));
}
};
template <>
struct Convert<int24, uint8>
{
typedef uint8 input_t;
typedef int24 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int24>(MPT_SC_LSHIFT_SIGNED(static_cast<int>(val)-0x80, 16));
}
};
template <>
struct Convert<int24, int8>
{
typedef int8 input_t;
typedef int24 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int24>(MPT_SC_LSHIFT_SIGNED(val, 16));
}
};
template <>
struct Convert<int24, int16>
{
typedef int16 input_t;
typedef int24 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int24>(MPT_SC_LSHIFT_SIGNED(val, 8));
}
};
template <>
struct Convert<int24, int32>
{
typedef int32 input_t;
typedef int24 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int24>(MPT_SC_RSHIFT_SIGNED(val, 8));
}
};
template <>
struct Convert<int24, int64>
{
typedef int64 input_t;
typedef int24 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int24>(MPT_SC_RSHIFT_SIGNED(val, 40));
}
};
template <>
struct Convert<int24, float32>
{
typedef float32 input_t;
typedef int24 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0f, 1.0f);
val *= 2147483648.0f;
return static_cast<int24>(MPT_SC_RSHIFT_SIGNED(mpt::saturate_cast<int32>(static_cast<int64>(MPT_SC_FASTROUND(val))), 8));
}
};
template <>
struct Convert<int24, double>
{
typedef double input_t;
typedef int24 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0, 1.0);
val *= 2147483648.0;
return static_cast<int24>(MPT_SC_RSHIFT_SIGNED(mpt::saturate_cast<int32>(static_cast<int64>(MPT_SC_FASTROUND(val))), 8));
}
};
template <>
struct Convert<int32, uint8>
{
typedef uint8 input_t;
typedef int32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int32>(MPT_SC_LSHIFT_SIGNED(static_cast<int>(val)-0x80, 24));
}
};
template <>
struct Convert<int32, int8>
{
typedef int8 input_t;
typedef int32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int32>(MPT_SC_LSHIFT_SIGNED(val, 24));
}
};
template <>
struct Convert<int32, int16>
{
typedef int16 input_t;
typedef int32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int32>(MPT_SC_LSHIFT_SIGNED(val, 16));
}
};
template <>
struct Convert<int32, int24>
{
typedef int24 input_t;
typedef int32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int32>(MPT_SC_LSHIFT_SIGNED(static_cast<int>(val), 8));
}
};
template <>
struct Convert<int32, int64>
{
typedef int64 input_t;
typedef int32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<int32>(MPT_SC_RSHIFT_SIGNED(val, 32));
}
};
template <>
struct Convert<int32, float32>
{
typedef float32 input_t;
typedef int32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0f, 1.0f);
val *= 2147483648.0f;
return mpt::saturate_cast<int32>(static_cast<int64>(MPT_SC_FASTROUND(val)));
}
};
template <>
struct Convert<int32, double>
{
typedef double input_t;
typedef int32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0, 1.0);
val *= 2147483648.0;
return mpt::saturate_cast<int32>(static_cast<int64>(MPT_SC_FASTROUND(val)));
}
};
template <>
struct Convert<int64, uint8>
{
typedef uint8 input_t;
typedef int64 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return MPT_SC_LSHIFT_SIGNED(static_cast<int64>(val)-0x80, 56);
}
};
template <>
struct Convert<int64, int8>
{
typedef int8 input_t;
typedef int64 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return MPT_SC_LSHIFT_SIGNED(static_cast<int64>(val), 56);
}
};
template <>
struct Convert<int64, int16>
{
typedef int16 input_t;
typedef int64 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return MPT_SC_LSHIFT_SIGNED(static_cast<int64>(val), 48);
}
};
template <>
struct Convert<int64, int24>
{
typedef int24 input_t;
typedef int64 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return MPT_SC_LSHIFT_SIGNED(static_cast<int64>(val), 40);
}
};
template <>
struct Convert<int64, int32>
{
typedef int32 input_t;
typedef int64 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return MPT_SC_LSHIFT_SIGNED(static_cast<int64>(val), 32);
}
};
template <>
struct Convert<int64, float32>
{
typedef float32 input_t;
typedef int64 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0f, 1.0f);
val *= static_cast<float>(uint64(1)<<63);
return mpt::saturate_cast<int64>(MPT_SC_FASTROUND(val));
}
};
template <>
struct Convert<int64, double>
{
typedef double input_t;
typedef int64 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
Limit(val, -1.0, 1.0);
val *= static_cast<double>(uint64(1)<<63);
return mpt::saturate_cast<int64>(MPT_SC_FASTROUND(val));
}
};
template <>
struct Convert<float32, uint8>
{
typedef uint8 input_t;
typedef float32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return (static_cast<int>(val)-0x80) * (1.0f / static_cast<float32>(static_cast<unsigned int>(1)<<7));
}
};
template <>
struct Convert<float32, int8>
{
typedef int8 input_t;
typedef float32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0f / static_cast<float>(static_cast<unsigned int>(1)<<7));
}
};
template <>
struct Convert<float32, int16>
{
typedef int16 input_t;
typedef float32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0f / static_cast<float>(static_cast<unsigned int>(1)<<15));
}
};
template <>
struct Convert<float32, int24>
{
typedef int24 input_t;
typedef float32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0f / static_cast<float>(static_cast<unsigned int>(1)<<23));
}
};
template <>
struct Convert<float32, int32>
{
typedef int32 input_t;
typedef float32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0f / static_cast<float>(static_cast<unsigned int>(1)<<31));
}
};
template <>
struct Convert<float32, int64>
{
typedef int64 input_t;
typedef float32 output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0f / static_cast<float>(static_cast<uint64>(1)<<63));
}
};
template <>
struct Convert<double, uint8>
{
typedef uint8 input_t;
typedef double output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return (static_cast<int>(val)-0x80) * (1.0 / static_cast<double>(static_cast<unsigned int>(1)<<7));
}
};
template <>
struct Convert<double, int8>
{
typedef int8 input_t;
typedef double output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0 / static_cast<double>(static_cast<unsigned int>(1)<<7));
}
};
template <>
struct Convert<double, int16>
{
typedef int16 input_t;
typedef double output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0 / static_cast<double>(static_cast<unsigned int>(1)<<15));
}
};
template <>
struct Convert<double, int24>
{
typedef int24 input_t;
typedef double output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0 / static_cast<double>(static_cast<unsigned int>(1)<<23));
}
};
template <>
struct Convert<double, int32>
{
typedef int32 input_t;
typedef double output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0 / static_cast<double>(static_cast<unsigned int>(1)<<31));
}
};
template <>
struct Convert<double, int64>
{
typedef int64 input_t;
typedef double output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return val * (1.0 / static_cast<double>(static_cast<uint64>(1)<<63));
}
};
template <>
struct Convert<double, float>
{
typedef float input_t;
typedef double output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<double>(val);
}
};
template <>
struct Convert<float, double>
{
typedef double input_t;
typedef float output_t;
MPT_FORCEINLINE output_t operator() (input_t val)
{
return static_cast<float>(val);
}
};
template <typename Tdst, typename Tsrc, int fractionalBits>
struct ConvertFixedPoint;
template <int fractionalBits>
struct ConvertFixedPoint<uint8, int32, fractionalBits>
{
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<uint8>(val+0x80); // unsigned
}
};
template <int fractionalBits>
struct ConvertFixedPoint<int8, int32, fractionalBits>
{
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<int8>(val);
}
};
template <int fractionalBits>
struct ConvertFixedPoint<int16, int32, fractionalBits>
{
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<int16>(val);
}
};
template <int fractionalBits>
struct ConvertFixedPoint<int24, int32, fractionalBits>
{
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<int24>(val);
}
};
template <int fractionalBits>
struct ConvertFixedPoint<int32, int32, fractionalBits>
{
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<int32>(Clamp(val, static_cast<int>(-((1<<fractionalBits)-1)), static_cast<int>(1<<fractionalBits)-1)) << (sizeof(input_t)*8-1-fractionalBits);
}
};
template <int fractionalBits>
struct ConvertFixedPoint<float32, int32, fractionalBits>
{
typedef int32 input_t;
typedef float32 output_t;
const float factor;
MPT_FORCEINLINE ConvertFixedPoint()
: factor( 1.0f / static_cast<float>(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 <int fractionalBits>
struct ConvertFixedPoint<float64, int32, fractionalBits>
{
typedef int32 input_t;
typedef float64 output_t;
const double factor;
MPT_FORCEINLINE ConvertFixedPoint()
: factor( 1.0 / static_cast<double>(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 <typename Tdst, typename Tsrc, int fractionalBits>
struct ConvertToFixedPoint;
template <int fractionalBits>
struct ConvertToFixedPoint<int32, uint8, fractionalBits>
{
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<output_t>(static_cast<int>(val)-0x80), shiftBits);
}
};
template <int fractionalBits>
struct ConvertToFixedPoint<int32, int8, fractionalBits>
{
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<output_t>(val), shiftBits);
}
};
template <int fractionalBits>
struct ConvertToFixedPoint<int32, int16, fractionalBits>
{
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<output_t>(val), shiftBits);
}
};
template <int fractionalBits>
struct ConvertToFixedPoint<int32, int24, fractionalBits>
{
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<output_t>(val), shiftBits);
}
};
template <int fractionalBits>
struct ConvertToFixedPoint<int32, int32, fractionalBits>
{
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<output_t>(val), (sizeof(input_t)*8-1-fractionalBits));
}
};
template <int fractionalBits>
struct ConvertToFixedPoint<int32, float32, fractionalBits>
{
typedef float32 input_t;
typedef int32 output_t;
const float factor;
MPT_FORCEINLINE ConvertToFixedPoint()
: factor( static_cast<float>(1 << fractionalBits) )
{
return;
}
MPT_FORCEINLINE output_t operator() (input_t val)
{
static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
return mpt::saturate_cast<output_t>(MPT_SC_FASTROUND(val * factor));
}
};
template <int fractionalBits>
struct ConvertToFixedPoint<int32, float64, fractionalBits>
{
typedef float64 input_t;
typedef int32 output_t;
const double factor;
MPT_FORCEINLINE ConvertToFixedPoint()
: factor( static_cast<double>(1 << fractionalBits) )
{
return;
}
MPT_FORCEINLINE output_t operator() (input_t val)
{
static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
return mpt::saturate_cast<output_t>(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 <typename Func2, typename Func1>
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 <typename Tfixed, int fractionalBits, bool clipOutput>
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 <typename Tfloat, bool clipOutput>
struct ClipFloat;
template <bool clipOutput>
struct ClipFloat<float, clipOutput>
{
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 <bool clipOutput>
struct ClipFloat<double, clipOutput>
{
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 <typename Tsample>
struct Normalize;
template <>
struct Normalize<int32>
{
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<uint32>(-static_cast<int64>(int32_min));
return;
}
val = -val;
}
if(static_cast<uint32>(val) > maxVal)
{
maxVal = static_cast<uint32>(val);
}
}
MPT_FORCEINLINE bool IsSilent() const
{
return maxVal == 0;
}
MPT_FORCEINLINE output_t operator() (input_t val)
{
return Util::muldivrfloor(val, static_cast<uint32>(1) << 31, maxVal);
}
MPT_FORCEINLINE peak_t GetSrcPeak() const
{
return maxVal;
}
};
template <>
struct Normalize<float32>
{
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<float64>
{
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<T>).
// Func2 can also be the identity conversion (Convert<T,T>).
template <typename Func2, typename Func1>
struct NormalizationChain
{
typedef typename Func1::input_t input_t;
typedef typename Func1::output_t normalize_t;
typedef typename Normalize<normalize_t>::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_t> 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