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:
sukibaby
2025-01-27 04:22:36 -08:00
committed by teejusb
parent 4f4167e3c7
commit 2feb9e784c
+23 -21
View File
@@ -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;
}
}
}