RageSoundReader_Merge fixes
This is the fixed Merge from the 2025-1-26 test build. It will more strictly check the drift with each iteration of the m_aSounds loop, whereas the original implementation can allow small amounts of desync to accumulate over time if none of them exceed the threshold.
This commit is contained in:
@@ -172,29 +172,28 @@ static const int ERROR_CORRECTION_THRESHOLD = 16;
|
||||
int RageSoundReader_Merge::Read( float *pBuffer, int iFrames )
|
||||
{
|
||||
if( m_aSounds.empty() )
|
||||
{
|
||||
return END_OF_FILE;
|
||||
}
|
||||
|
||||
/*
|
||||
* All sounds which are active should stay aligned; each GetNextSourceFrame should not
|
||||
* come out of sync. Accomodate small rounding errors. A larger inconsistency
|
||||
* happens may be a bug, such as sounds at different speeds.
|
||||
*/
|
||||
std::vector<int> aNextSourceFrames(m_aSounds.size());
|
||||
std::vector<float> aRatios(m_aSounds.size());
|
||||
|
||||
std::vector<int> aNextSourceFrames;
|
||||
std::vector<float> aRatios;
|
||||
aNextSourceFrames.resize( m_aSounds.size() );
|
||||
aRatios.resize( m_aSounds.size() );
|
||||
for( unsigned i = 0; i < m_aSounds.size(); ++i )
|
||||
for (size_t i = 0; i < m_aSounds.size(); ++i)
|
||||
{
|
||||
aNextSourceFrames[i] = m_aSounds[i]->GetNextSourceFrame();
|
||||
aRatios[i] = m_aSounds[i]->GetStreamToSourceRatio();
|
||||
}
|
||||
|
||||
{
|
||||
/* GetNextSourceFrame for each active sound should be the same. If any differ,
|
||||
* delay the later sounds until the earlier ones catch back up to put them
|
||||
* back in sync. */
|
||||
int iEarliestSound = distance( aNextSourceFrames.begin(), min_element( aNextSourceFrames.begin(), aNextSourceFrames.end() ) );
|
||||
int iEarliestSound = std::distance(aNextSourceFrames.begin(), std::min_element(aNextSourceFrames.begin(), aNextSourceFrames.end()));
|
||||
|
||||
/* Normally, m_iNextSourceFrame should already be aligned with the GetNextSourceFrame of our
|
||||
* sounds. If it's not, adjust it and return. */
|
||||
@@ -207,11 +206,10 @@ int RageSoundReader_Merge::Read( float *pBuffer, int iFrames )
|
||||
}
|
||||
|
||||
int iMinPosition = aNextSourceFrames[iEarliestSound];
|
||||
for( unsigned i = 0; i < m_aSounds.size(); ++i )
|
||||
for (size_t i = 0; i < m_aSounds.size(); ++i)
|
||||
{
|
||||
if (Difference(aNextSourceFrames[i], iMinPosition) > ERROR_CORRECTION_THRESHOLD)
|
||||
{
|
||||
if( Difference(aNextSourceFrames[i], iMinPosition) <= ERROR_CORRECTION_THRESHOLD )
|
||||
continue;
|
||||
|
||||
/* A sound is being delayed to resync it; clamp the number of frames we
|
||||
* read now, so we don't advance past it. */
|
||||
int iMaxSourceFramesToRead = aNextSourceFrames[i] - iMinPosition;
|
||||
@@ -221,24 +219,24 @@ int RageSoundReader_Merge::Read( float *pBuffer, int iFrames )
|
||||
}
|
||||
}
|
||||
|
||||
// Read directly if there's only one sound
|
||||
if( m_aSounds.size() == 1 )
|
||||
{
|
||||
/* We have only one source; read directly into the buffer. */
|
||||
RageSoundReader *pSound = m_aSounds.front();
|
||||
iFrames = pSound->Read( pBuffer, iFrames );
|
||||
if( iFrames > 0 )
|
||||
{
|
||||
m_iNextSourceFrame += static_cast<int>((iFrames * m_fCurrentStreamToSourceRatio) + 0.5 );
|
||||
aNextSourceFrames.front() = pSound->GetNextSourceFrame();
|
||||
aRatios.front() = pSound->GetStreamToSourceRatio();
|
||||
}
|
||||
return iFrames;
|
||||
}
|
||||
|
||||
RageSoundMixBuffer mix;
|
||||
float Buffer[2048];
|
||||
iFrames = std::min( iFrames, (int) (ARRAYLEN(Buffer) / m_iChannels) );
|
||||
iFrames = std::min(iFrames, static_cast<int>(ARRAYLEN(Buffer) / m_iChannels));
|
||||
|
||||
/* Read iFrames from each sound. */
|
||||
for( unsigned i = 0; i < m_aSounds.size(); ++i )
|
||||
for (size_t i = 0; i < m_aSounds.size(); ++i)
|
||||
{
|
||||
RageSoundReader *pSound = m_aSounds[i];
|
||||
ASSERT( pSound->GetNumChannels() == m_iChannels );
|
||||
@@ -249,11 +247,11 @@ int RageSoundReader_Merge::Read( float *pBuffer, int iFrames )
|
||||
// if( i == 0 )
|
||||
//LOG->Trace( "*** %i", Difference(aNextSourceFrames[i], m_iNextSourceFrame + std::lrint(iFramesRead * aRatios[i])) );
|
||||
|
||||
if( Difference(aNextSourceFrames[i], m_iNextSourceFrame + static_cast<int>((iFramesRead * aRatios[i]) + 0.5)) > ERROR_CORRECTION_THRESHOLD )
|
||||
{
|
||||
LOG->Trace( "*** hurk %i", Difference(aNextSourceFrames[i], m_iNextSourceFrame + static_cast<int>((iFramesRead * aRatios[i]) + 0.5 )) );
|
||||
break;
|
||||
}
|
||||
// if( Difference(aNextSourceFrames[i], m_iNextSourceFrame + static_cast<int>((iFramesRead * aRatios[i]) + 0.5)) > ERROR_CORRECTION_THRESHOLD )
|
||||
// {
|
||||
// LOG->Trace("Sound positions moving at different rates");
|
||||
// break;
|
||||
// }
|
||||
|
||||
int iGotFrames = pSound->Read( Buffer, iFrames - iFramesRead );
|
||||
aNextSourceFrames[i] = m_aSounds[i]->GetNextSourceFrame();
|
||||
@@ -262,7 +260,9 @@ int RageSoundReader_Merge::Read( float *pBuffer, int iFrames )
|
||||
if( iGotFrames < 0 )
|
||||
{
|
||||
if( i == 0 )
|
||||
{
|
||||
return iGotFrames;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -271,7 +271,9 @@ int RageSoundReader_Merge::Read( float *pBuffer, int iFrames )
|
||||
iFramesRead += iGotFrames;
|
||||
|
||||
if( Difference(aRatios[i], m_fCurrentStreamToSourceRatio) > 0.001f )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user