1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
/*
* 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>
{
using input_t = int32;
using output_t = int32;
using peak_t = uint32;
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<somefloat32>
{
using input_t = somefloat32;
using output_t = somefloat32;
using peak_t = somefloat32;
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<somefloat64>
{
using input_t = somefloat64;
using output_t = somefloat64;
using peak_t = somefloat64;
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
{
using input_t = typename Func1::input_t;
using normalize_t = typename Func1::output_t;
using peak_t = typename Normalize<normalize_t>::peak_t;
using output_t = typename Func2::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
|