Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
306
Src/external_dependencies/openmpt-trunk/include/r8brain/r8butil.h
vendored
Normal file
306
Src/external_dependencies/openmpt-trunk/include/r8brain/r8butil.h
vendored
Normal file
|
@ -0,0 +1,306 @@
|
|||
//$ nobt
|
||||
//$ nocpp
|
||||
|
||||
/**
|
||||
* @file r8butil.h
|
||||
*
|
||||
* @brief The inclusion file with several utility functions.
|
||||
*
|
||||
* This file includes several utility functions used by various utility
|
||||
* programs like "calcErrorTable.cpp".
|
||||
*
|
||||
* r8brain-free-src Copyright (c) 2013-2021 Aleksey Vaneev
|
||||
* See the "LICENSE" file for license.
|
||||
*/
|
||||
|
||||
#ifndef R8BUTIL_INCLUDED
|
||||
#define R8BUTIL_INCLUDED
|
||||
|
||||
#include "r8bbase.h"
|
||||
|
||||
namespace r8b {
|
||||
|
||||
/**
|
||||
* @param re Real part of the frequency response.
|
||||
* @param im Imaginary part of the frequency response.
|
||||
* @return A magnitude response value converted from the linear scale to the
|
||||
* logarithmic scale.
|
||||
*/
|
||||
|
||||
inline double convertResponseToLog( const double re, const double im )
|
||||
{
|
||||
return( 4.34294481903251828 * log( re * re + im * im + 1e-100 ));
|
||||
}
|
||||
|
||||
/**
|
||||
* An utility function that performs frequency response scanning step update
|
||||
* based on the current magnitude response's slope.
|
||||
*
|
||||
* @param[in,out] step The current scanning step. Will be updated on
|
||||
* function's return. Must be a positive value.
|
||||
* @param curg Squared magnitude response at the current frequency point.
|
||||
* @param[in,out] prevg_log Previous magnitude response, log scale. Will be
|
||||
* updated on function's return.
|
||||
* @param prec Precision multiplier, affects the size of the step.
|
||||
* @param maxstep The maximal allowed step.
|
||||
* @param minstep The minimal allowed step.
|
||||
*/
|
||||
|
||||
inline void updateScanStep( double& step, const double curg,
|
||||
double& prevg_log, const double prec, const double maxstep,
|
||||
const double minstep = 1e-11 )
|
||||
{
|
||||
double curg_log = 4.34294481903251828 * log( curg + 1e-100 );
|
||||
curg_log += ( prevg_log - curg_log ) * 0.7;
|
||||
|
||||
const double slope = fabs( curg_log - prevg_log );
|
||||
prevg_log = curg_log;
|
||||
|
||||
if( slope > 0.0 )
|
||||
{
|
||||
step /= prec * slope;
|
||||
step = max( min( step, maxstep ), minstep );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function locates normalized frequency at which the minimum filter gain
|
||||
* is reached. The scanning is performed from lower (left) to higher
|
||||
* (right) frequencies, the whole range is scanned.
|
||||
*
|
||||
* Function expects that the magnitude response is always reducing from lower
|
||||
* to high frequencies, starting at "minth".
|
||||
*
|
||||
* @param flt Filter response.
|
||||
* @param fltlen Filter response's length in samples (taps).
|
||||
* @param[out] ming The current minimal gain (squared). On function's return
|
||||
* will contain the minimal gain value found (squared).
|
||||
* @param[out] minth The normalized frequency where the minimal gain is
|
||||
* currently at. On function's return will point to the normalized frequency
|
||||
* where the new minimum was found.
|
||||
* @param thend The ending frequency, inclusive.
|
||||
*/
|
||||
|
||||
inline void findFIRFilterResponseMinLtoR( const double* const flt,
|
||||
const int fltlen, double& ming, double& minth, const double thend )
|
||||
{
|
||||
const double maxstep = minth * 2e-3;
|
||||
double curth = minth;
|
||||
double re;
|
||||
double im;
|
||||
calcFIRFilterResponse( flt, fltlen, R8B_PI * curth, re, im );
|
||||
double prevg_log = convertResponseToLog( re, im );
|
||||
double step = 1e-11;
|
||||
|
||||
while( true )
|
||||
{
|
||||
curth += step;
|
||||
|
||||
if( curth > thend )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
calcFIRFilterResponse( flt, fltlen, R8B_PI * curth, re, im );
|
||||
const double curg = re * re + im * im;
|
||||
|
||||
if( curg > ming )
|
||||
{
|
||||
ming = curg;
|
||||
minth = curth;
|
||||
break;
|
||||
}
|
||||
|
||||
ming = curg;
|
||||
minth = curth;
|
||||
|
||||
updateScanStep( step, curg, prevg_log, 0.31, maxstep );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function locates normalized frequency at which the maximal filter gain
|
||||
* is reached. The scanning is performed from lower (left) to higher
|
||||
* (right) frequencies, the whole range is scanned.
|
||||
*
|
||||
* Note: this function may "stall" in very rare cases if the magnitude
|
||||
* response happens to be "saw-tooth" like, requiring a very small stepping to
|
||||
* be used. If this happens, it may take dozens of seconds to complete.
|
||||
*
|
||||
* @param flt Filter response.
|
||||
* @param fltlen Filter response's length in samples (taps).
|
||||
* @param[out] maxg The current maximal gain (squared). On function's return
|
||||
* will contain the maximal gain value (squared).
|
||||
* @param[out] maxth The normalized frequency where the maximal gain is
|
||||
* currently at. On function's return will point to the normalized frequency
|
||||
* where the maximum was reached.
|
||||
* @param thend The ending frequency, inclusive.
|
||||
*/
|
||||
|
||||
inline void findFIRFilterResponseMaxLtoR( const double* const flt,
|
||||
const int fltlen, double& maxg, double& maxth, const double thend )
|
||||
{
|
||||
const double maxstep = maxth * 1e-4;
|
||||
double premaxth = maxth;
|
||||
double premaxg = maxg;
|
||||
double postmaxth = maxth;
|
||||
double postmaxg = maxg;
|
||||
|
||||
double prevth = maxth;
|
||||
double prevg = maxg;
|
||||
double curth = maxth;
|
||||
double re;
|
||||
double im;
|
||||
calcFIRFilterResponse( flt, fltlen, R8B_PI * curth, re, im );
|
||||
double prevg_log = convertResponseToLog( re, im );
|
||||
double step = 1e-11;
|
||||
|
||||
bool WasPeak = false;
|
||||
int AfterPeakCount = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
curth += step;
|
||||
|
||||
if( curth > thend )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
calcFIRFilterResponse( flt, fltlen, R8B_PI * curth, re, im );
|
||||
const double curg = re * re + im * im;
|
||||
|
||||
if( curg > maxg )
|
||||
{
|
||||
premaxth = prevth;
|
||||
premaxg = prevg;
|
||||
maxg = curg;
|
||||
maxth = curth;
|
||||
WasPeak = true;
|
||||
AfterPeakCount = 0;
|
||||
}
|
||||
else
|
||||
if( WasPeak )
|
||||
{
|
||||
if( AfterPeakCount == 0 )
|
||||
{
|
||||
postmaxth = curth;
|
||||
postmaxg = curg;
|
||||
}
|
||||
|
||||
if( AfterPeakCount == 5 )
|
||||
{
|
||||
// Perform 2 approximate binary searches.
|
||||
|
||||
int k;
|
||||
|
||||
for( k = 0; k < 2; k++ )
|
||||
{
|
||||
double l = ( k == 0 ? premaxth : maxth );
|
||||
double curgl = ( k == 0 ? premaxg : maxg );
|
||||
double r = ( k == 0 ? maxth : postmaxth );
|
||||
double curgr = ( k == 0 ? maxg : postmaxg );
|
||||
|
||||
while( true )
|
||||
{
|
||||
const double c = ( l + r ) * 0.5;
|
||||
calcFIRFilterResponse( flt, fltlen, R8B_PI * c,
|
||||
re, im );
|
||||
|
||||
const double curg = re * re + im * im;
|
||||
|
||||
if( curgl > curgr )
|
||||
{
|
||||
r = c;
|
||||
curgr = curg;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = c;
|
||||
curgl = curg;
|
||||
}
|
||||
|
||||
if( r - l < 1e-11 )
|
||||
{
|
||||
if( curgl > curgr )
|
||||
{
|
||||
maxth = l;
|
||||
maxg = curgl;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxth = r;
|
||||
maxg = curgr;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
AfterPeakCount++;
|
||||
}
|
||||
|
||||
prevth = curth;
|
||||
prevg = curg;
|
||||
|
||||
updateScanStep( step, curg, prevg_log, 1.0, maxstep );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function locates normalized frequency at which the specified maximum
|
||||
* filter gain is reached. The scanning is performed from higher (right)
|
||||
* to lower (left) frequencies, scanning stops when the required gain
|
||||
* value was crossed. Function uses an extremely efficient binary search and
|
||||
* thus expects that the magnitude response has the "main lobe" form produced
|
||||
* by windowing, with a minimal pass-band ripple.
|
||||
*
|
||||
* @param flt Filter response.
|
||||
* @param fltlen Filter response's length in samples (taps).
|
||||
* @param maxg Maximal gain (squared).
|
||||
* @param[out] th The current normalized frequency. On function's return will
|
||||
* point to the normalized frequency where "maxg" is reached.
|
||||
* @param thend The leftmost frequency to scan, inclusive.
|
||||
*/
|
||||
|
||||
inline void findFIRFilterResponseLevelRtoL( const double* const flt,
|
||||
const int fltlen, const double maxg, double& th, const double thend )
|
||||
{
|
||||
// Perform exact binary search.
|
||||
|
||||
double l = thend;
|
||||
double r = th;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const double c = ( l + r ) * 0.5;
|
||||
|
||||
if( r - l < 1e-14 )
|
||||
{
|
||||
th = c;
|
||||
break;
|
||||
}
|
||||
|
||||
double re;
|
||||
double im;
|
||||
calcFIRFilterResponse( flt, fltlen, R8B_PI * c, re, im );
|
||||
const double curg = re * re + im * im;
|
||||
|
||||
if( curg > maxg )
|
||||
{
|
||||
l = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace r8b
|
||||
|
||||
#endif // R8BUTIL_INCLUDED
|
Loading…
Add table
Add a link
Reference in a new issue