Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
769
Src/external_dependencies/openmpt-trunk/include/r8brain/CDSPResampler.h
vendored
Normal file
769
Src/external_dependencies/openmpt-trunk/include/r8brain/CDSPResampler.h
vendored
Normal file
|
@ -0,0 +1,769 @@
|
|||
//$ nobt
|
||||
//$ nocpp
|
||||
|
||||
/**
|
||||
* @file CDSPResampler.h
|
||||
*
|
||||
* @brief The master sample rate converter (resampler) class.
|
||||
*
|
||||
* This file includes the master sample rate converter (resampler) class that
|
||||
* combines all elements of this library into a single front-end class.
|
||||
*
|
||||
* r8brain-free-src Copyright (c) 2013-2022 Aleksey Vaneev
|
||||
* See the "LICENSE" file for license.
|
||||
*/
|
||||
|
||||
#ifndef R8B_CDSPRESAMPLER_INCLUDED
|
||||
#define R8B_CDSPRESAMPLER_INCLUDED
|
||||
|
||||
#include "CDSPHBDownsampler.h"
|
||||
#include "CDSPHBUpsampler.h"
|
||||
#include "CDSPBlockConvolver.h"
|
||||
#include "CDSPFracInterpolator.h"
|
||||
|
||||
namespace r8b {
|
||||
|
||||
/**
|
||||
* @brief The master sample rate converter (resampler) class.
|
||||
*
|
||||
* This class can be considered the "master" sample rate converter (resampler)
|
||||
* class since it combines all functionality of this library into a single
|
||||
* front-end class to perform sample rate conversion to/from any sample rate,
|
||||
* including non-integer sample rates.
|
||||
*
|
||||
* Note that objects of this class can be constructed on the stack as it has a
|
||||
* small member data size. The default template parameters of this class are
|
||||
* suited for 27-bit fixed point resampling.
|
||||
*
|
||||
* Use the CDSPResampler16 class for 16-bit resampling.
|
||||
*
|
||||
* Use the CDSPResampler16IR class for 16-bit impulse response resampling.
|
||||
*
|
||||
* Use the CDSPResampler24 class for 24-bit resampling (including 32-bit
|
||||
* floating point resampling).
|
||||
*/
|
||||
|
||||
class CDSPResampler : public CDSPProcessor
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor initalizes the resampler object.
|
||||
*
|
||||
* Note that increasing the transition band and decreasing attenuation
|
||||
* reduces the filter length, this in turn reduces the "input before
|
||||
* output" delay. However, the filter length has only a minor influence on
|
||||
* the overall resampling speed.
|
||||
*
|
||||
* It should be noted that the ReqAtten specifies the minimal difference
|
||||
* between the loudest input signal component and the produced aliasing
|
||||
* artifacts during resampling. For example, if ReqAtten=100 was specified
|
||||
* when performing 2x upsampling, the analysis of the resulting signal may
|
||||
* display high-frequency components which are quieter than the loudest
|
||||
* part of the input signal by only 100 decibel meaning the high-frequency
|
||||
* part did not become "magically" completely silent after resampling. You
|
||||
* have to specify a higher ReqAtten value if you need a totally clean
|
||||
* high-frequency content. On the other hand, it may not be reasonable to
|
||||
* have a high-frequency content cleaner than the input signal itself: if
|
||||
* the input signal is 16-bit, setting ReqAtten to 180 will make its
|
||||
* high-frequency content 24-bit, but the original part of the signal will
|
||||
* remain 16-bit.
|
||||
*
|
||||
* @param SrcSampleRate Source signal sample rate. Both sample rates can
|
||||
* be specified as a ratio, e.g. SrcSampleRate = 1.0, DstSampleRate = 2.0.
|
||||
* @param DstSampleRate Destination signal sample rate. The "power of 2"
|
||||
* ratios between the source and destination sample rates force resampler
|
||||
* to use several fast "power of 2" resampling steps, without using
|
||||
* fractional interpolation at all.
|
||||
* @param aMaxInLen The maximal planned length of the input buffer (in
|
||||
* samples) that will be passed to the resampler. The resampler relies on
|
||||
* this value as it allocates intermediate buffers. Input buffers longer
|
||||
* than this value should never be supplied to the resampler. Note that
|
||||
* upsampling produces more samples than was provided on input, so at
|
||||
* higher upsampling ratios it is advisable to use smaller MaxInLen
|
||||
* values to reduce memory footprint. When downsampling, a larger MaxInLen
|
||||
* is suggested in order to increase downsampling performance.
|
||||
* @param ReqTransBand Required transition band, in percent of the
|
||||
* spectral space of the input signal (or the output signal if
|
||||
* downsampling is performed) between filter's -3 dB point and the Nyquist
|
||||
* frequency. The range is from CDSPFIRFilter::getLPMinTransBand() to
|
||||
* CDSPFIRFilter::getLPMaxTransBand(), inclusive. When upsampling 88200 or
|
||||
* 96000 audio to a higher sample rates the ReqTransBand can be
|
||||
* considerably increased, up to 30. The selection of ReqTransBand depends
|
||||
* on the level of desire to preserve the high-frequency content. While
|
||||
* values 0.5 to 2 are extremely "greedy" settings, not necessary in most
|
||||
* cases, values 2 to 3 can be used in most cases. Values 3 to 4 are
|
||||
* relaxed settings, but they still offer a flat frequency response up to
|
||||
* 21kHz with 44.1k source or destination sample rate.
|
||||
* @param ReqAtten Required stop-band attenuation in decibel, in the
|
||||
* range CDSPFIRFilter::getLPMinAtten() to CDSPFIRFilter::getLPMaxAtten(),
|
||||
* inclusive. The actual attenuation may be 0.40-4.46 dB higher. The
|
||||
* general formula for selecting the ReqAtten is 6.02 * Bits + 40, where
|
||||
* "Bits" is the bit resolution (e.g. 16, 24), "40" is an added resolution
|
||||
* for dynamic signals; this value can be decreased to 20 to 10 if the
|
||||
* signal being resampled is non-dynamic (e.g., an impulse response or
|
||||
* filter, with a non-steep frequency response).
|
||||
* @param ReqPhase Required filter's phase response. Note that this
|
||||
* setting does not affect interpolator's phase response which is always
|
||||
* linear-phase. Also note that if the "power of 2" resampling was engaged
|
||||
* by the resampler together with the minimum-phase response, the audio
|
||||
* stream may become fractionally delayed, depending on the minimum-phase
|
||||
* filter's actual fractional delay. Linear-phase filters do not have
|
||||
* fractional delay.
|
||||
* @see CDSPFIRFilterCache::getLPFilter()
|
||||
*/
|
||||
|
||||
CDSPResampler( const double SrcSampleRate, const double DstSampleRate,
|
||||
const int aMaxInLen, const double ReqTransBand = 2.0,
|
||||
const double ReqAtten = 206.91,
|
||||
const EDSPFilterPhaseResponse ReqPhase = fprLinearPhase )
|
||||
: StepCapacity( 0 )
|
||||
, StepCount( 0 )
|
||||
, MaxInLen( aMaxInLen )
|
||||
, CurMaxOutLen( aMaxInLen )
|
||||
, LatencyFrac( 0.0 )
|
||||
{
|
||||
R8BASSERT( SrcSampleRate > 0.0 );
|
||||
R8BASSERT( DstSampleRate > 0.0 );
|
||||
R8BASSERT( MaxInLen > 0 );
|
||||
|
||||
R8BCONSOLE( "* CDSPResampler: src=%.1f dst=%.1f len=%i tb=%.1f "
|
||||
"att=%.2f ph=%i\n", SrcSampleRate, DstSampleRate, aMaxInLen,
|
||||
ReqTransBand, ReqAtten, (int) ReqPhase );
|
||||
|
||||
if( SrcSampleRate == DstSampleRate )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TmpBufCapacities[ 0 ] = 0;
|
||||
TmpBufCapacities[ 1 ] = 0;
|
||||
CurTmpBuf = 0;
|
||||
|
||||
// Try some common efficient ratios requiring only a single step.
|
||||
|
||||
const int CommonRatioCount = 5;
|
||||
const int CommonRatios[ CommonRatioCount ][ 2 ] = {
|
||||
{ 1, 2 },
|
||||
{ 1, 3 },
|
||||
{ 2, 3 },
|
||||
{ 3, 2 },
|
||||
{ 3, 4 }
|
||||
};
|
||||
|
||||
int i;
|
||||
|
||||
for( i = 0; i < CommonRatioCount; i++ )
|
||||
{
|
||||
const int num = CommonRatios[ i ][ 0 ];
|
||||
const int den = CommonRatios[ i ][ 1 ];
|
||||
|
||||
if( SrcSampleRate * num == DstSampleRate * den )
|
||||
{
|
||||
addProcessor( new CDSPBlockConvolver(
|
||||
CDSPFIRFilterCache :: getLPFilter(
|
||||
1.0 / ( num > den ? num : den ), ReqTransBand,
|
||||
ReqAtten, ReqPhase, num ), num, den, LatencyFrac ));
|
||||
|
||||
createTmpBuffers();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try whole-number power-of-2 or 3*power-of-2 upsampling.
|
||||
|
||||
for( i = 2; i <= 3; i++ )
|
||||
{
|
||||
bool WasFound = false;
|
||||
int c = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const double NewSR = SrcSampleRate * ( i << c );
|
||||
|
||||
if( NewSR == DstSampleRate )
|
||||
{
|
||||
WasFound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if( NewSR > DstSampleRate )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
|
||||
if( WasFound )
|
||||
{
|
||||
addProcessor( new CDSPBlockConvolver(
|
||||
CDSPFIRFilterCache :: getLPFilter( 1.0 / i, ReqTransBand,
|
||||
ReqAtten, ReqPhase, i ), i, 1, LatencyFrac ));
|
||||
|
||||
const bool IsThird = ( i == 3 );
|
||||
|
||||
for( i = 0; i < c; i++ )
|
||||
{
|
||||
addProcessor( new CDSPHBUpsampler( ReqAtten, i, IsThird,
|
||||
LatencyFrac ));
|
||||
}
|
||||
|
||||
createTmpBuffers();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( DstSampleRate * 2.0 > SrcSampleRate )
|
||||
{
|
||||
// Upsampling or fractional downsampling down to 2X.
|
||||
|
||||
const double NormFreq = ( DstSampleRate > SrcSampleRate ? 0.5 :
|
||||
0.5 * DstSampleRate / SrcSampleRate );
|
||||
|
||||
addProcessor( new CDSPBlockConvolver(
|
||||
CDSPFIRFilterCache :: getLPFilter( NormFreq, ReqTransBand,
|
||||
ReqAtten, ReqPhase, 2.0 ), 2, 1, LatencyFrac ));
|
||||
|
||||
// Try intermediate interpolated resampling with subsequent 2X
|
||||
// or 3X upsampling.
|
||||
|
||||
const double tbw = 0.0175; // Intermediate filter's transition
|
||||
// band extension coefficient.
|
||||
const double ThreshSampleRate = SrcSampleRate /
|
||||
( 1.0 - tbw * ReqTransBand ); // Make sure intermediate
|
||||
// filter's transition band is not steeper than ReqTransBand
|
||||
// (this keeps the latency under control).
|
||||
|
||||
int c = 0;
|
||||
int div = 1;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const int ndiv = div * 2;
|
||||
|
||||
if( DstSampleRate < ThreshSampleRate * ndiv )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
div = ndiv;
|
||||
c++;
|
||||
}
|
||||
|
||||
int c2 = 0;
|
||||
int div2 = 1;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const int ndiv = div * ( c2 == 0 ? 3 : 2 );
|
||||
|
||||
if( DstSampleRate < ThreshSampleRate * ndiv )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
div2 = ndiv;
|
||||
c2++;
|
||||
}
|
||||
|
||||
const double SrcSampleRate2 = SrcSampleRate * 2.0;
|
||||
int tmp1;
|
||||
int tmp2;
|
||||
|
||||
if( c == 1 && getWholeStepping( SrcSampleRate2, DstSampleRate,
|
||||
tmp1, tmp2 ))
|
||||
{
|
||||
// Do not use intermediate interpolation if whole stepping is
|
||||
// available as it performs very fast.
|
||||
|
||||
c = 0;
|
||||
}
|
||||
|
||||
if( c > 0 )
|
||||
{
|
||||
// Add steps using intermediate interpolation.
|
||||
|
||||
int num;
|
||||
|
||||
if( c2 > 0 && div2 > div )
|
||||
{
|
||||
div = div2;
|
||||
c = c2;
|
||||
num = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
num = 2;
|
||||
}
|
||||
|
||||
addProcessor( new CDSPFracInterpolator( SrcSampleRate2 * div,
|
||||
DstSampleRate, ReqAtten, false, LatencyFrac ));
|
||||
|
||||
double tb = ( 1.0 - SrcSampleRate * div / DstSampleRate ) /
|
||||
tbw; // Divide TransBand by a constant that assures a
|
||||
// linear response in the pass-band.
|
||||
|
||||
if( tb > CDSPFIRFilter :: getLPMaxTransBand() )
|
||||
{
|
||||
tb = CDSPFIRFilter :: getLPMaxTransBand();
|
||||
}
|
||||
|
||||
addProcessor( new CDSPBlockConvolver(
|
||||
CDSPFIRFilterCache :: getLPFilter( 1.0 / num, tb,
|
||||
ReqAtten, ReqPhase, num ), num, 1, LatencyFrac ));
|
||||
|
||||
const bool IsThird = ( num == 3 );
|
||||
|
||||
for( i = 1; i < c; i++ )
|
||||
{
|
||||
addProcessor( new CDSPHBUpsampler( ReqAtten, i - 1,
|
||||
IsThird, LatencyFrac ));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addProcessor( new CDSPFracInterpolator( SrcSampleRate2,
|
||||
DstSampleRate, ReqAtten, false, LatencyFrac ));
|
||||
}
|
||||
|
||||
createTmpBuffers();
|
||||
return;
|
||||
}
|
||||
|
||||
// Use downsampling steps, including power-of-2 downsampling.
|
||||
|
||||
double CheckSR = DstSampleRate * 4.0;
|
||||
int c = 0;
|
||||
double FinGain = 1.0;
|
||||
|
||||
while( CheckSR <= SrcSampleRate )
|
||||
{
|
||||
c++;
|
||||
CheckSR *= 2.0;
|
||||
FinGain *= 0.5;
|
||||
}
|
||||
|
||||
const int SrcSRDiv = ( 1 << c );
|
||||
int downf;
|
||||
double NormFreq = 0.5;
|
||||
bool UseInterp = true;
|
||||
bool IsThird = false;
|
||||
|
||||
for( downf = 2; downf <= 3; downf++ )
|
||||
{
|
||||
if( DstSampleRate * SrcSRDiv * downf == SrcSampleRate )
|
||||
{
|
||||
NormFreq = 1.0 / downf;
|
||||
UseInterp = false;
|
||||
IsThird = ( downf == 3 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( UseInterp )
|
||||
{
|
||||
downf = 1;
|
||||
NormFreq = DstSampleRate * SrcSRDiv / SrcSampleRate;
|
||||
IsThird = ( NormFreq * 3.0 <= 1.0 );
|
||||
}
|
||||
|
||||
for( i = 0; i < c; i++ )
|
||||
{
|
||||
// Use a fixed very relaxed 2X downsampling filters, that at
|
||||
// the final stage only guarantees stop-band between 0.75 and
|
||||
// pi. 0.5-0.75 range will be aliased to 0.25-0.5 range which
|
||||
// will then be filtered out by the final filter.
|
||||
|
||||
addProcessor( new CDSPHBDownsampler( ReqAtten, c - 1 - i, IsThird,
|
||||
LatencyFrac ));
|
||||
}
|
||||
|
||||
addProcessor( new CDSPBlockConvolver(
|
||||
CDSPFIRFilterCache :: getLPFilter( NormFreq, ReqTransBand,
|
||||
ReqAtten, ReqPhase, FinGain ), 1, downf, LatencyFrac ));
|
||||
|
||||
if( UseInterp )
|
||||
{
|
||||
addProcessor( new CDSPFracInterpolator( SrcSampleRate,
|
||||
DstSampleRate * SrcSRDiv, ReqAtten, IsThird, LatencyFrac ));
|
||||
}
|
||||
|
||||
createTmpBuffers();
|
||||
}
|
||||
|
||||
virtual ~CDSPResampler()
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < StepCount; i++ )
|
||||
{
|
||||
delete Steps[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
virtual int getLatency() const
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
virtual double getLatencyFrac() const
|
||||
{
|
||||
return( LatencyFrac );
|
||||
}
|
||||
|
||||
/**
|
||||
* This function ignores the supplied parameter and returns the maximal
|
||||
* output buffer length that depends on the MaxInLen supplied to the
|
||||
* constructor.
|
||||
*/
|
||||
|
||||
virtual int getMaxOutLen( const int/* MaxInLen */ ) const
|
||||
{
|
||||
return( CurMaxOutLen );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function clears (resets) the state of *this object and returns it to
|
||||
* the state after construction. All input data accumulated in the
|
||||
* internal buffer so far will be discarded.
|
||||
*
|
||||
* This function makes it possible to use *this object for converting
|
||||
* separate streams from the same source sample rate to the same
|
||||
* destination sample rate without reconstructing the object. It is more
|
||||
* efficient to clear the state of the resampler object than to destroy it
|
||||
* and create a new object.
|
||||
*/
|
||||
|
||||
virtual void clear()
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < StepCount; i++ )
|
||||
{
|
||||
Steps[ i ] -> clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function performs sample rate conversion.
|
||||
*
|
||||
* If the source and destination sample rates are equal, the resampler
|
||||
* will do nothing and will simply return the input buffer unchanged.
|
||||
*
|
||||
* You do not need to allocate an intermediate output buffer for use with
|
||||
* this function. If required, the resampler will allocate a suitable
|
||||
* intermediate output buffer itself.
|
||||
*
|
||||
* @param ip0 Input buffer. This buffer is never used as output buffer by
|
||||
* this function. This pointer may be returned in "op0" if no resampling
|
||||
* is happening (source sample rate equals destination sample rate).
|
||||
* @param l The number of samples available in the input buffer. Should
|
||||
* not exceed the MaxInLen supplied in the constructor.
|
||||
* @param[out] op0 This variable receives the pointer to the resampled
|
||||
* data. On function's return, this pointer points to *this object's
|
||||
* internal buffer. In real-time applications it is suggested to pass this
|
||||
* pointer to the next output audio block and consume any data left from
|
||||
* the previous output audio block first before calling the process()
|
||||
* function again. The buffer pointed to by the "op0" on return is owned
|
||||
* by the resampler, so it should not be freed by the caller.
|
||||
* @return The number of samples available in the "op0" output buffer. If
|
||||
* the data from the output buffer "op0" is going to be written to a
|
||||
* bigger output buffer, it is suggested to check the returned number of
|
||||
* samples so that no overflow of the bigger output buffer happens.
|
||||
*/
|
||||
|
||||
virtual int process( double* ip0, int l, double*& op0 )
|
||||
{
|
||||
R8BASSERT( l >= 0 );
|
||||
|
||||
double* ip = ip0;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < StepCount; i++ )
|
||||
{
|
||||
double* op = TmpBufs[ i & 1 ];
|
||||
l = Steps[ i ] -> process( ip, l, op );
|
||||
ip = op;
|
||||
}
|
||||
|
||||
op0 = ip;
|
||||
return( l );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function performs resampling of an input sample buffer of the specified
|
||||
* length in the "one-shot" mode. This function can be useful when impulse
|
||||
* response resampling is required.
|
||||
*
|
||||
* @param ip Input buffer pointer.
|
||||
* @param iplen Length of the input buffer in samples.
|
||||
* @param[out] op Output buffer pointer.
|
||||
* @param oplen Length of the output buffer in samples.
|
||||
* @tparam Tin Input buffer's element type.
|
||||
* @tparam Tout Output buffer's element type.
|
||||
*/
|
||||
|
||||
template< typename Tin, typename Tout >
|
||||
void oneshot( const Tin* ip, int iplen, Tout* op, int oplen )
|
||||
{
|
||||
CFixedBuffer< double > Buf( MaxInLen );
|
||||
bool IsZero = false;
|
||||
|
||||
while( oplen > 0 )
|
||||
{
|
||||
int rc;
|
||||
double* p;
|
||||
int i;
|
||||
|
||||
if( iplen == 0 )
|
||||
{
|
||||
rc = MaxInLen;
|
||||
p = &Buf[ 0 ];
|
||||
|
||||
if( !IsZero )
|
||||
{
|
||||
IsZero = true;
|
||||
memset( p, 0, MaxInLen * sizeof( p[ 0 ]));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = min( iplen, MaxInLen );
|
||||
|
||||
if( sizeof( Tin ) == sizeof( double ))
|
||||
{
|
||||
p = (double*) ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = &Buf[ 0 ];
|
||||
|
||||
for( i = 0; i < rc; i++ )
|
||||
{
|
||||
p[ i ] = ip[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
ip += rc;
|
||||
iplen -= rc;
|
||||
}
|
||||
|
||||
double* op0;
|
||||
int wc = process( p, rc, op0 );
|
||||
wc = min( oplen, wc );
|
||||
|
||||
for( i = 0; i < wc; i++ )
|
||||
{
|
||||
op[ i ] = (Tout) op0[ i ];
|
||||
}
|
||||
|
||||
op += wc;
|
||||
oplen -= wc;
|
||||
}
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function obtains overall input sample count required to produce first
|
||||
* output sample. Function works by iteratively passing 1 sample at a time
|
||||
* until output begins. This is a relatively CPU-consuming operation. This
|
||||
* function should be called after the clear() function call or after
|
||||
* object's construction. The function itself calls the clear() function
|
||||
* before return.
|
||||
*
|
||||
* Note that it is advisable to cache the value returned by this function,
|
||||
* for each SrcSampleRate/DstSampleRate pair, if it is called frequently.
|
||||
*/
|
||||
|
||||
int getInLenBeforeOutStart()
|
||||
{
|
||||
int inc = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
double ins = 0.0;
|
||||
double* op;
|
||||
|
||||
if( process( &ins, 1, op ) > 0 )
|
||||
{
|
||||
clear();
|
||||
return( inc );
|
||||
}
|
||||
|
||||
inc++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
CFixedBuffer< CDSPProcessor* > Steps; ///< Array of processing steps.
|
||||
///<
|
||||
int StepCapacity; ///< The capacity of the Steps array.
|
||||
///<
|
||||
int StepCount; ///< The number of created processing steps.
|
||||
///<
|
||||
int MaxInLen; ///< Maximal input length.
|
||||
///<
|
||||
CFixedBuffer< double > TmpBufAll; ///< Buffer containing both temporary
|
||||
///< buffers.
|
||||
///<
|
||||
double* TmpBufs[ 2 ]; ///< Temporary output buffers.
|
||||
///<
|
||||
int TmpBufCapacities[ 2 ]; ///< Capacities of temporary buffers, updated
|
||||
///< during processing steps building.
|
||||
///<
|
||||
int CurTmpBuf; ///< Current temporary buffer.
|
||||
///<
|
||||
int CurMaxOutLen; ///< Current maximal output length.
|
||||
///<
|
||||
double LatencyFrac; ///< Current fractional latency. After object's
|
||||
///< construction, equals to the remaining fractional latency in the
|
||||
///< output.
|
||||
///<
|
||||
|
||||
/**
|
||||
* Function adds processor, updates MaxOutLen variable and adjusts length
|
||||
* of temporary internal buffers.
|
||||
*
|
||||
* @param Proc Processor to add. This pointer is inherited and will be
|
||||
* destroyed on *this object's destruction.
|
||||
*/
|
||||
|
||||
void addProcessor( CDSPProcessor* const Proc )
|
||||
{
|
||||
if( StepCount == StepCapacity )
|
||||
{
|
||||
// Reallocate and increase Steps array's capacity.
|
||||
|
||||
const int NewCapacity = StepCapacity + 8;
|
||||
Steps.realloc( StepCapacity, NewCapacity );
|
||||
StepCapacity = NewCapacity;
|
||||
}
|
||||
|
||||
LatencyFrac = Proc -> getLatencyFrac();
|
||||
CurMaxOutLen = Proc -> getMaxOutLen( CurMaxOutLen );
|
||||
|
||||
if( CurMaxOutLen > TmpBufCapacities[ CurTmpBuf ])
|
||||
{
|
||||
TmpBufCapacities[ CurTmpBuf ] = CurMaxOutLen;
|
||||
}
|
||||
|
||||
CurTmpBuf ^= 1;
|
||||
|
||||
Steps[ StepCount ] = Proc;
|
||||
StepCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function creates temporary buffers.
|
||||
*/
|
||||
|
||||
void createTmpBuffers()
|
||||
{
|
||||
const int ol = TmpBufCapacities[ 0 ] + TmpBufCapacities[ 1 ];
|
||||
|
||||
if( ol > 0 )
|
||||
{
|
||||
TmpBufAll.alloc( ol );
|
||||
TmpBufs[ 0 ] = &TmpBufAll[ 0 ];
|
||||
TmpBufs[ 1 ] = &TmpBufAll[ TmpBufCapacities[ 0 ]];
|
||||
}
|
||||
|
||||
R8BCONSOLE( "* CDSPResampler: init done\n" );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The resampler class for 16-bit resampling.
|
||||
*
|
||||
* This class defines resampling parameters suitable for 16-bit resampling,
|
||||
* using linear-phase low-pass filter. See the r8b::CDSPResampler class for
|
||||
* details.
|
||||
*/
|
||||
|
||||
class CDSPResampler16 : public CDSPResampler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor initializes the 16-bit resampler. See the
|
||||
* r8b::CDSPResampler class for details.
|
||||
*
|
||||
* @param SrcSampleRate Source signal sample rate.
|
||||
* @param DstSampleRate Destination signal sample rate.
|
||||
* @param aMaxInLen The maximal planned length of the input buffer (in
|
||||
* samples) that will be passed to the resampler.
|
||||
* @param ReqTransBand Required transition band, in percent.
|
||||
*/
|
||||
|
||||
CDSPResampler16( const double SrcSampleRate, const double DstSampleRate,
|
||||
const int aMaxInLen, const double ReqTransBand = 2.0 )
|
||||
: CDSPResampler( SrcSampleRate, DstSampleRate, aMaxInLen, ReqTransBand,
|
||||
136.45, fprLinearPhase )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The resampler class for 16-bit impulse response resampling.
|
||||
*
|
||||
* This class defines resampling parameters suitable for 16-bit impulse
|
||||
* response resampling, using linear-phase low-pass filter. Impulse responses
|
||||
* are non-dynamic signals, and thus need resampler with a lesser SNR. See the
|
||||
* r8b::CDSPResampler class for details.
|
||||
*/
|
||||
|
||||
class CDSPResampler16IR : public CDSPResampler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor initializes the 16-bit impulse response resampler. See the
|
||||
* r8b::CDSPResampler class for details.
|
||||
*
|
||||
* @param SrcSampleRate Source signal sample rate.
|
||||
* @param DstSampleRate Destination signal sample rate.
|
||||
* @param aMaxInLen The maximal planned length of the input buffer (in
|
||||
* samples) that will be passed to the resampler.
|
||||
* @param ReqTransBand Required transition band, in percent.
|
||||
*/
|
||||
|
||||
CDSPResampler16IR( const double SrcSampleRate, const double DstSampleRate,
|
||||
const int aMaxInLen, const double ReqTransBand = 2.0 )
|
||||
: CDSPResampler( SrcSampleRate, DstSampleRate, aMaxInLen, ReqTransBand,
|
||||
109.56, fprLinearPhase )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The resampler class for 24-bit resampling.
|
||||
*
|
||||
* This class defines resampling parameters suitable for 24-bit resampling
|
||||
* (including 32-bit floating point resampling), using linear-phase low-pass
|
||||
* filter. See the r8b::CDSPResampler class for details.
|
||||
*/
|
||||
|
||||
class CDSPResampler24 : public CDSPResampler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor initializes the 24-bit resampler (including 32-bit floating
|
||||
* point). See the r8b::CDSPResampler class for details.
|
||||
*
|
||||
* @param SrcSampleRate Source signal sample rate.
|
||||
* @param DstSampleRate Destination signal sample rate.
|
||||
* @param aMaxInLen The maximal planned length of the input buffer (in
|
||||
* samples) that will be passed to the resampler.
|
||||
* @param ReqTransBand Required transition band, in percent.
|
||||
*/
|
||||
|
||||
CDSPResampler24( const double SrcSampleRate, const double DstSampleRate,
|
||||
const int aMaxInLen, const double ReqTransBand = 2.0 )
|
||||
: CDSPResampler( SrcSampleRate, DstSampleRate, aMaxInLen, ReqTransBand,
|
||||
180.15, fprLinearPhase )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace r8b
|
||||
|
||||
#endif // R8B_CDSPRESAMPLER_INCLUDED
|
Loading…
Add table
Add a link
Reference in a new issue