winamp/Src/external_dependencies/openmpt-trunk/soundlib/SampleNormalize.h
2024-09-24 14:54:57 +02:00

192 lines
3.6 KiB
C++

/*
* SampleNormalize.h
* -----------------
* Purpose: Functions for normalizing samples.
* Notes : (currently none)
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/
#pragma once
#include "openmpt/all/BuildSettings.hpp"
OPENMPT_NAMESPACE_BEGIN
namespace SC
{ // SC = _S_ample_C_onversion
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 == std::numeric_limits<int32>::min())
{
maxVal = static_cast<uint32>(-static_cast<int64>(std::numeric_limits<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;
}
};
} // namespace SC
OPENMPT_NAMESPACE_END