From 65e6922acab10bccc6f1d670f33370a150be59d5 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Wed, 27 Dec 2006 05:40:00 +0000 Subject: [PATCH] better rounding error fix. The ratio goes through a relatively low-resolution fixed-point representation within SpeedChange (m_iDeltaFrames). --- stepmania/src/RageSoundReader_PitchChange.cpp | 36 ++++++++++++------- stepmania/src/RageSoundReader_PitchChange.h | 1 - 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/stepmania/src/RageSoundReader_PitchChange.cpp b/stepmania/src/RageSoundReader_PitchChange.cpp index 5348cacef1..ca03824faa 100644 --- a/stepmania/src/RageSoundReader_PitchChange.cpp +++ b/stepmania/src/RageSoundReader_PitchChange.cpp @@ -45,8 +45,31 @@ int RageSoundReader_PitchChange::Read( char *pBuf, int iFrames ) float fRate = GetStreamToSourceRatio(); if( m_pSpeedChange->NextReadWillStep() ) { + /* This is the simple way: */ + // float fRequestedSpeedRatio = m_fSpeedRatio / m_fPitchRatio; + // m_pSpeedChange->SetSpeedRatio( fRequestedSpeedRatio ); + // m_pResample->SetRate( m_fPitchRatio ); + + /* + * However, the speed changer has a granularity due to internal fixed- + * point math, and the actual ratio will be slightly different than what + * we tell it to use. The actual ratio used is fActualSpeedChangeRatio. + * Given + * + * fRequestedSpeedRatio = m_fSpeedRatio / m_fPitchRatio + * + * solve for m_fPitchRatio: + * + * fRequestedPitchRatio = m_fSpeedRatio / fRequestedSpeedRatio + * + * and compute the pitch ratio based on the actual speed ratio, rather than + * the requested speed ratio. This avoids excessive rounding error between + * the ratios of m_pSpeedChange and m_pResample. + */ m_pSpeedChange->SetSpeedRatio( m_fSpeedRatio / m_fPitchRatio ); - m_pResample->SetRate( m_fPitchRatio ); + float fActualSpeedRatio = m_pSpeedChange->GetRatio(); + float fRequestedPitchRatio = m_fSpeedRatio / fActualSpeedRatio; + m_pResample->SetRate( fRequestedPitchRatio ); } /* If we just applied a new speed and it caused the ratio to change, return @@ -57,17 +80,6 @@ int RageSoundReader_PitchChange::Read( char *pBuf, int iFrames ) return RageSoundReader_Filter::Read( pBuf, iFrames ); } -float RageSoundReader_PitchChange::GetStreamToSourceRatio() const -{ - /* If m_fSpeedRatio is 1.0f and the underlying ratio is exactly 1.0, - * the ratio should be exactly 1. Rounding error prevents n * (1/n) - * from being exact. */ - float fRatio = m_pSource->GetStreamToSourceRatio(); - if( m_fSpeedRatio == 1.0f && fabsf(1.0f - fRatio) < 0.001f ) - fRatio = 1.0f; - return fRatio; -} - bool RageSoundReader_PitchChange::SetProperty( const RString &sProperty, float fValue ) { if( sProperty == "Rate" ) diff --git a/stepmania/src/RageSoundReader_PitchChange.h b/stepmania/src/RageSoundReader_PitchChange.h index 0a91a85c94..4c0673671a 100644 --- a/stepmania/src/RageSoundReader_PitchChange.h +++ b/stepmania/src/RageSoundReader_PitchChange.h @@ -15,7 +15,6 @@ public: virtual int Read( char *pBuf, int iFrames ); virtual bool SetProperty( const RString &sProperty, float fValue ); - virtual float GetStreamToSourceRatio() const; void SetSpeedRatio( float fRatio ) { m_fSpeedRatio = fRatio; } void SetPitchRatio( float fRatio ) { m_fPitchRatio = fRatio; }