These attempt to flush buffers and go back to reading directly if ratios
are set back to 1. They don't work; the speed shift buffer won't line up perfectly for all channels, and the resampler would need to be lined up with the window and lerped. Make these only read directly if the buffers are empty, so these filters are cheap if their ratios are never used. Fixes clicks when moving the ratio around 1.0.
This commit is contained in:
@@ -204,7 +204,6 @@ struct PolyphaseFilter
|
||||
void Generate( const float *pFIR );
|
||||
int RunPolyphaseFilter( State &State, const float *pIn, int iSamplesIn, int iDownFactor,
|
||||
float *pOut, int iSamplesOut ) const;
|
||||
int ReadBuffer( State &State, float *pOut, int iSamplesOut ) const;
|
||||
int GetLatency() const { return L/2; }
|
||||
|
||||
int NumInputsForOutputSamples( const State &State, int iOut, int iDownFactor ) const;
|
||||
@@ -345,24 +344,6 @@ int PolyphaseFilter::RunPolyphaseFilter(
|
||||
return pOut - pOutOrig;
|
||||
}
|
||||
|
||||
int PolyphaseFilter::ReadBuffer( State &State, float *pOut, int iSamplesOut ) const
|
||||
{
|
||||
float *pOutOrig = pOut;
|
||||
|
||||
while( State.m_iFilled && iSamplesOut-- )
|
||||
{
|
||||
*pOut = State.m_fBuf[State.m_iBufNext];
|
||||
++pOut;
|
||||
--State.m_iFilled;
|
||||
|
||||
float fRot = State.m_fBuf[0];
|
||||
memmove( State.m_fBuf, State.m_fBuf+1, ((L*2)-1) * sizeof(float) );
|
||||
State.m_fBuf[L*2-1] = fRot;
|
||||
}
|
||||
|
||||
return pOut - pOutOrig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of input samples needed to produce the given number of output
|
||||
* samples. This is dependent on the number of bytes in the buffer and the current
|
||||
@@ -513,11 +494,6 @@ public:
|
||||
return m_pPolyphase->RunPolyphaseFilter( *m_pState, pIn, iSamplesIn, m_iDownFactor, pOut, iSamplesOut );
|
||||
}
|
||||
|
||||
int FlushBuffer( float *pOut, int iSamplesOut ) const
|
||||
{
|
||||
return m_pPolyphase->ReadBuffer( *m_pState, pOut, iSamplesOut );
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
delete m_pState;
|
||||
@@ -684,29 +660,8 @@ int RageSoundReader_Resample_Good::Read( char *pBuf_, int iFrames )
|
||||
int iDownFactor, iUpFactor;
|
||||
GetFactors( iDownFactor, iUpFactor );
|
||||
|
||||
if( iDownFactor == iUpFactor && m_fRate == 1.0f )
|
||||
{
|
||||
/* Before reading directly, flush the data from the polyphase filters. */
|
||||
if( m_apResamplers[0]->GetFilled() )
|
||||
{
|
||||
float *pFloatOut = (float *) alloca( iFrames * sizeof(float) );
|
||||
for( int iChannel = 0; iChannel < iChannels; ++iChannel )
|
||||
{
|
||||
int iGotFrames = m_apResamplers[iChannel]->FlushBuffer( pFloatOut, iFrames );
|
||||
ASSERT( iGotFrames <= iFrames );
|
||||
|
||||
for( int i = 0; i < iGotFrames; ++i )
|
||||
pBuf[i*iChannels+iChannel] = int16_t(lrintf(clamp(pFloatOut[i], -32768, 32767)));
|
||||
if( iChannel == 0 )
|
||||
iFramesRead += iGotFrames;
|
||||
}
|
||||
|
||||
return iFramesRead;
|
||||
}
|
||||
|
||||
// XXX: errors
|
||||
if( m_apResamplers[0]->GetFilled() == 0 && iDownFactor == iUpFactor && m_fRate == 1.0f )
|
||||
return m_pSource->Read( pBuf_, iFrames );
|
||||
}
|
||||
|
||||
{
|
||||
int iFramesNeeded = m_apResamplers[0]->NumInputsForOutputSamples(iFrames);
|
||||
|
||||
@@ -242,7 +242,7 @@ int RageSoundReader_SpeedChange::Read( char *buf, int iFrames )
|
||||
// m_iDataBufferAvailFrames-m_iCorrelatedPos < GetWindowSizeFrames when flushing
|
||||
int iCursorAvail = GetCursorAvail();
|
||||
|
||||
if( iCursorAvail == 0 && m_fTrailingSpeedRatio == m_fSpeedRatio && m_fSpeedRatio == 1.0f )
|
||||
if( m_iDataBufferAvailFrames == 0 && m_fTrailingSpeedRatio == m_fSpeedRatio && m_fSpeedRatio == 1.0f )
|
||||
{
|
||||
/* Fast path: the buffer is empty, and we're not scaling the audio. Read directly
|
||||
* into the output buffer, to eliminate memory and copying overhead. */
|
||||
|
||||
Reference in New Issue
Block a user