exact ratio (no fixed-point granularity)

This commit is contained in:
Glenn Maynard
2006-12-27 07:51:57 +00:00
parent 8f9885c229
commit 9f577de2e5
2 changed files with 28 additions and 24 deletions
+25 -19
View File
@@ -10,23 +10,24 @@ RageSoundReader_SpeedChange::RageSoundReader_SpeedChange( RageSoundReader *pSour
RageSoundReader_Filter( pSource ) RageSoundReader_Filter( pSource )
{ {
m_Channels.resize( pSource->GetNumChannels() ); m_Channels.resize( pSource->GetNumChannels() );
SetSpeedRatio( 1.3f ); m_fSpeedRatio = m_fTrailingSpeedRatio = 1.0f;
SetSpeedRatio( 1.0f );
Reset(); Reset();
} }
void RageSoundReader_SpeedChange::SetSpeedRatio( float fRatio ) void RageSoundReader_SpeedChange::SetSpeedRatio( float fRatio )
{ {
fSpeed = fRatio; m_fSpeedRatio = fRatio;
m_iDeltaFrames = lrintf( GetWindowSizeFrames() * fRatio ); m_iDeltaFrames = lrintf( GetWindowSizeFrames() * fRatio );
/* If we havn't read any data yet, put the new delta into effect immediately. */ /* If we havn't read any data yet, put the new delta into effect immediately. */
if( m_iDataBufferAvailFrames == 0 ) if( m_iDataBufferAvailFrames == 0 )
m_iTrailingDeltaFrames = m_iDeltaFrames; m_fTrailingSpeedRatio = m_fSpeedRatio;
} }
float RageSoundReader_SpeedChange::GetRatio() const float RageSoundReader_SpeedChange::GetRatio() const
{ {
return float(m_iDeltaFrames) / GetWindowSizeFrames(); return m_fSpeedRatio;
} }
int RageSoundReader_SpeedChange::GetWindowSizeFrames() const int RageSoundReader_SpeedChange::GetWindowSizeFrames() const
@@ -34,14 +35,9 @@ int RageSoundReader_SpeedChange::GetWindowSizeFrames() const
return (WINDOW_SIZE_MS * GetSampleRate()) / 1000; return (WINDOW_SIZE_MS * GetSampleRate()) / 1000;
} }
float RageSoundReader_SpeedChange::GetTrailingRatio() const
{
return float(m_iTrailingDeltaFrames) / GetWindowSizeFrames();
}
void RageSoundReader_SpeedChange::Reset() void RageSoundReader_SpeedChange::Reset()
{ {
m_iTrailingDeltaFrames = m_iDeltaFrames; m_fTrailingSpeedRatio = m_fSpeedRatio;
m_iDataBufferAvailFrames = 0; m_iDataBufferAvailFrames = 0;
for( size_t i = 0; i < m_Channels.size(); ++i ) for( size_t i = 0; i < m_Channels.size(); ++i )
{ {
@@ -51,6 +47,7 @@ void RageSoundReader_SpeedChange::Reset()
} }
m_iUncorrelatedPos = 0; m_iUncorrelatedPos = 0;
m_iPos = 0; m_iPos = 0;
m_fErrorFrames = 0;
} }
static int FindClosestMatch( const int16_t *pBuffer, int iBufferSize, const int16_t *pCorrelateBuffer, int iCorrelateBufferSize, int iStride ) static int FindClosestMatch( const int16_t *pBuffer, int iBufferSize, const int16_t *pCorrelateBuffer, int iCorrelateBufferSize, int iStride )
@@ -164,13 +161,22 @@ int RageSoundReader_SpeedChange::Step()
m_Channels[i].m_iCorrelatedPos += m_iPos; m_Channels[i].m_iCorrelatedPos += m_iPos;
} }
/* Advance m_iUncorrelatedPos to the position we'd prefer to continue playing from. */ /* Advance m_iUncorrelatedPos to the position we'd prefer to continue playing from.
m_iUncorrelatedPos += m_iTrailingDeltaFrames; * This rounds the position, making the ratio imprecise. Record the amount of
* error introduced here. If we want to advance by 2.3 frames, we'll advance
* by 2.0 frames, and advance by 0.3 more the next time around. */
float fAdvanceFrames = GetWindowSizeFrames() * m_fTrailingSpeedRatio;
fAdvanceFrames += m_fErrorFrames;
int iTrailingDeltaFrames = lrintf( fAdvanceFrames );
m_fErrorFrames = fAdvanceFrames - iTrailingDeltaFrames;
m_iUncorrelatedPos += iTrailingDeltaFrames;
m_iPos = 0; m_iPos = 0;
} }
m_iTrailingDeltaFrames = m_iDeltaFrames; /* Update m_fTrailingSpeedRatio. Do this after advancing m_iUncorrelatedPos,
* so changes to m_iUncorrelatedPos line up with GetNextSourceFrame. */
m_fTrailingSpeedRatio = m_fSpeedRatio;
/* We don't need any data before the earlier of m_iUncorrelatedPos or m_iCorrelatedPos. */ /* We don't need any data before the earlier of m_iUncorrelatedPos or m_iCorrelatedPos. */
int iToDelete = m_iUncorrelatedPos; int iToDelete = m_iUncorrelatedPos;
@@ -242,7 +248,7 @@ int RageSoundReader_SpeedChange::Read( char *buf, int iFrames )
// m_iDataBufferAvailFrames-m_iCorrelatedPos < GetWindowSizeFrames when flushing // m_iDataBufferAvailFrames-m_iCorrelatedPos < GetWindowSizeFrames when flushing
int iCursorAvail = GetCursorAvail(); int iCursorAvail = GetCursorAvail();
if( iCursorAvail == 0 && m_iTrailingDeltaFrames == m_iDeltaFrames && GetWindowSizeFrames() == m_iDeltaFrames ) if( iCursorAvail == 0 && m_fTrailingSpeedRatio == m_fSpeedRatio && GetWindowSizeFrames() == m_iDeltaFrames )
{ {
/* Fast path: the buffer is empty, and we're not scaling the audio. Read directly /* 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. */ * into the output buffer, to eliminate memory and copying overhead. */
@@ -291,8 +297,8 @@ int RageSoundReader_SpeedChange::SetPosition( int iFrame )
{ {
Reset(); Reset();
int64_t iScaled = (int64_t(iFrame) * GetWindowSizeFrames()) / m_iDeltaFrames; // int64_t iScaled = int64_t(iFrame) / m_fSpeedRatio;
iFrame = (int) iScaled; // iFrame = (int) iScaled;
return RageSoundReader_Filter::SetPosition( iFrame ); return RageSoundReader_Filter::SetPosition( iFrame );
} }
@@ -310,7 +316,7 @@ bool RageSoundReader_SpeedChange::SetProperty( const RString &sProperty, float f
int RageSoundReader_SpeedChange::GetNextSourceFrame() const int RageSoundReader_SpeedChange::GetNextSourceFrame() const
{ {
float fRatio = GetTrailingRatio(); float fRatio = m_fTrailingSpeedRatio; //GetTrailingRatio();
int iSourceFrame = RageSoundReader_Filter::GetNextSourceFrame(); int iSourceFrame = RageSoundReader_Filter::GetNextSourceFrame();
int iPos = lrintf(m_iPos * fRatio); int iPos = lrintf(m_iPos * fRatio);
@@ -326,9 +332,9 @@ float RageSoundReader_SpeedChange::GetStreamToSourceRatio() const
* become the real ratio on the next read. Otherwise, we'll continue using * become the real ratio on the next read. Otherwise, we'll continue using
* our old ratio for a bit longer. */ * our old ratio for a bit longer. */
if( GetCursorAvail() == 0 ) if( GetCursorAvail() == 0 )
return GetRatio() * RageSoundReader_Filter::GetStreamToSourceRatio(); return m_fSpeedRatio * RageSoundReader_Filter::GetStreamToSourceRatio();
else else
return GetTrailingRatio() * RageSoundReader_Filter::GetStreamToSourceRatio(); return m_fTrailingSpeedRatio * RageSoundReader_Filter::GetStreamToSourceRatio();
} }
/* /*
+3 -5
View File
@@ -32,9 +32,6 @@ protected:
int Step(); int Step();
void Reset(); void Reset();
/* Get the ratio currently being used. */
float GetTrailingRatio() const;
int GetCursorAvail() const; int GetCursorAvail() const;
int GetWindowSizeFrames() const; int GetWindowSizeFrames() const;
@@ -52,9 +49,10 @@ protected:
int m_iUncorrelatedPos; int m_iUncorrelatedPos;
int m_iPos; int m_iPos;
float fSpeed; float m_fSpeedRatio;
float m_fTrailingSpeedRatio;
int m_iDeltaFrames; int m_iDeltaFrames;
int m_iTrailingDeltaFrames; float m_fErrorFrames;
}; };
#endif #endif