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:
Glenn Maynard
2006-12-27 09:19:02 +00:00
parent ad5b3543a6
commit 3551367fe4
2 changed files with 2 additions and 47 deletions
@@ -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. */