/* SPDX-License-Identifier: BSD-3-Clause */ /* SPDX-FileCopyrightText: OpenMPT Project Developers and Contributors */ #pragma once #include "openmpt/all/BuildSettings.hpp" #include "mpt/base/arithmetic_shift.hpp" #include "mpt/base/macros.hpp" #include "mpt/base/math.hpp" #include "mpt/base/saturate_cast.hpp" #include "openmpt/base/Int24.hpp" #include "openmpt/base/Types.hpp" #include "openmpt/soundbase/SampleConvert.hpp" #include #include OPENMPT_NAMESPACE_BEGIN namespace SC { // SC = _S_ample_C_onversion template struct ConvertFixedPoint; template struct ConvertFixedPoint { using input_t = int32; using output_t = uint8; 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::rshift_signed((val + (1 << (shiftBits - 1))), shiftBits); // round if(val < std::numeric_limits::min()) val = std::numeric_limits::min(); if(val > std::numeric_limits::max()) val = std::numeric_limits::max(); return static_cast(val + 0x80); // unsigned } }; template struct ConvertFixedPoint { using input_t = int32; using output_t = int8; 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::rshift_signed((val + (1 << (shiftBits - 1))), shiftBits); // round if(val < std::numeric_limits::min()) val = std::numeric_limits::min(); if(val > std::numeric_limits::max()) val = std::numeric_limits::max(); return static_cast(val); } }; template struct ConvertFixedPoint { using input_t = int32; using output_t = int16; 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::rshift_signed((val + (1 << (shiftBits - 1))), shiftBits); // round if(val < std::numeric_limits::min()) val = std::numeric_limits::min(); if(val > std::numeric_limits::max()) val = std::numeric_limits::max(); return static_cast(val); } }; template struct ConvertFixedPoint { using input_t = int32; using output_t = int24; 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::rshift_signed((val + (1 << (shiftBits - 1))), shiftBits); // round if(val < std::numeric_limits::min()) val = std::numeric_limits::min(); if(val > std::numeric_limits::max()) val = std::numeric_limits::max(); return static_cast(val); } }; template struct ConvertFixedPoint { using input_t = int32; using output_t = int32; MPT_FORCEINLINE output_t operator()(input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1); return static_cast(std::clamp(val, static_cast(-((1 << fractionalBits) - 1)), static_cast(1 << fractionalBits) - 1)) << (sizeof(input_t) * 8 - 1 - fractionalBits); } }; template struct ConvertFixedPoint { using input_t = int32; using output_t = float32; 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 { using input_t = int32; using output_t = float64; 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 { using input_t = uint8; using output_t = int32; 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::lshift_signed(static_cast(static_cast(val) - 0x80), shiftBits); } }; template struct ConvertToFixedPoint { using input_t = int8; using output_t = int32; 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::lshift_signed(static_cast(val), shiftBits); } }; template struct ConvertToFixedPoint { using input_t = int16; using output_t = int32; 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::lshift_signed(static_cast(val), shiftBits); } }; template struct ConvertToFixedPoint { using input_t = int24; using output_t = int32; 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::lshift_signed(static_cast(val), shiftBits); } }; template struct ConvertToFixedPoint { using input_t = int32; using output_t = int32; MPT_FORCEINLINE output_t operator()(input_t val) { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(output_t) * 8 - 1); return mpt::rshift_signed(static_cast(val), (sizeof(input_t) * 8 - 1 - fractionalBits)); } }; template struct ConvertToFixedPoint { using input_t = float32; using output_t = int32; 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(SC::fastround(val * factor)); } }; template struct ConvertToFixedPoint { using input_t = float64; using output_t = int32; 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(SC::fastround(val * factor)); } }; } // namespace SC OPENMPT_NAMESPACE_END