diff --git a/stepmania/src/RageSound.cpp b/stepmania/src/RageSound.cpp index b1e4bba23a..0b8264d3f3 100644 --- a/stepmania/src/RageSound.cpp +++ b/stepmania/src/RageSound.cpp @@ -288,18 +288,29 @@ int RageSound::GetData( char *pBuffer, int iFrames ) fRate = m_pSource->GetStreamToSourceRatio(); int iNewSourceFrame = m_pSource->GetNextSourceFrame(); - iGotFrames = m_pSource->Read( pBuffer, iFrames ); - if( iGotFrames == -1 ) + while( iGotFrames == 0 ) { - Fail( m_pSource->GetError() ); + iGotFrames = m_pSource->Read( pBuffer, iFrames ); + if( iGotFrames == RageSoundReader::ERROR ) + { + Fail( m_pSource->GetError() ); - /* Pretend we got EOF. */ - return 0; + /* Pretend we got EOF. */ + return 0; + } + + if( iGotFrames == RageSoundReader::END_OF_FILE ) + { + iGotFrames = 0; + break; + } + + ASSERT_M( iGotFrames >= 0, ssprintf("%i", iGotFrames) ); // unhandled error condition } /* If we didn't get any data, don't update iSourceFrame, so we just keep * extrapolating if we're in M_CONTINUE. */ - if( iGotFrames != 0 ) + if( iGotFrames == 0 ) iSourceFrame = iNewSourceFrame; if( m_pSource->GetNumChannels() == 1 ) diff --git a/stepmania/src/RageSoundReader.h b/stepmania/src/RageSoundReader.h index 8b6812eb88..d917eee213 100644 --- a/stepmania/src/RageSoundReader.h +++ b/stepmania/src/RageSoundReader.h @@ -18,6 +18,12 @@ public: virtual bool IsStreamingFromDisk() const = 0; virtual bool SetProperty( const RString &sProperty, float fValue ) { return false; } + /* Return values for Read(). */ + enum { + ERROR = -1, + END_OF_FILE = -2 + }; + /* GetNextSourceFrame() provides the source frame associated with the next frame * that will be read via Read(). GetStreamToSourceRatio() returns the ratio * for extrapolating the source frames of the remainder of the block. These diff --git a/stepmania/src/RageSoundReader_ChannelSplit.cpp b/stepmania/src/RageSoundReader_ChannelSplit.cpp index 09006732d5..900da120d1 100644 --- a/stepmania/src/RageSoundReader_ChannelSplit.cpp +++ b/stepmania/src/RageSoundReader_ChannelSplit.cpp @@ -48,7 +48,7 @@ public: } /* Request that m_sBuffer contain frames [iStartFrame,iStartFrame+iFrames). */ - bool ReadBuffer(); + int ReadBuffer(); int m_iRefCount; RageSoundReader *m_pSource; @@ -111,10 +111,11 @@ bool RageSoundReader_Split::SetProperty( const RString &sProperty, float fValue int RageSoundReader_Split::Read( char *pBuf, int iFrames ) { m_iRequestFrames = iFrames; - if( !m_pImpl->ReadBuffer() ) + int iRet = m_pImpl->ReadBuffer(); + if( iRet < 0 ) { this->SetError( m_pImpl->m_pSource->GetError() ); - return -1; + return iRet; } int iBytesAvailable = m_pImpl->m_sBuffer.size(); @@ -153,7 +154,7 @@ int RageSoundReader_Split::Read( char *pBuf, int iFrames ) return iFramesAvailable; } -bool RageSoundSplitterImpl::ReadBuffer() +int RageSoundSplitterImpl::ReadBuffer() { /* Discard any bytes that are no longer requested by any sound. */ int iMinFrameRequested = INT_MAX; @@ -182,21 +183,21 @@ bool RageSoundSplitterImpl::ReadBuffer() int iFramesToRead = iMaxFrameRequested - (m_iBufferPositionFrames + iFramesBuffered); if( iFramesToRead <= 0 ) - return true; // requested data already buffered + return 1; // requested data already buffered int iBytesToRead = iFramesToRead * sizeof(int16_t) * m_pSource->GetNumChannels(); int iOldSizeBytes = m_sBuffer.size(); m_sBuffer.resize( iOldSizeBytes + iBytesToRead ); int iGotFrames = m_pSource->Read( &m_sBuffer[0] + iOldSizeBytes, iFramesToRead ); - if( iGotFrames == -1 ) + if( iGotFrames < 0 ) { m_sBuffer.resize( iOldSizeBytes ); - return false; + return iGotFrames; } int iGotBytes = iGotFrames * sizeof(int16_t) * m_pSource->GetNumChannels(); m_sBuffer.resize( iOldSizeBytes + iGotBytes ); - return true; + return 1; } void RageSoundReader_Split::AddSourceChannelToSound( int iFromChannel, int iToChannel ) diff --git a/stepmania/src/RageSoundReader_MP3.cpp b/stepmania/src/RageSoundReader_MP3.cpp index c321fbd398..166bb9aba2 100644 --- a/stepmania/src/RageSoundReader_MP3.cpp +++ b/stepmania/src/RageSoundReader_MP3.cpp @@ -765,9 +765,9 @@ int RageSoundReader_MP3::Read( char *buf, int iFrames ) /* Decode more from the MP3 stream. */ int ret = do_mad_frame_decode(); if( ret == 0 ) - return iFramesWritten; + return END_OF_FILE; if( ret == -1 ) - return -1; + return ERROR; synth_output(); } diff --git a/stepmania/src/RageSoundReader_Pan.cpp b/stepmania/src/RageSoundReader_Pan.cpp index e37a204317..fb3ea50604 100644 --- a/stepmania/src/RageSoundReader_Pan.cpp +++ b/stepmania/src/RageSoundReader_Pan.cpp @@ -17,6 +17,12 @@ int RageSoundReader_Pan::Read( char *pBuf, int iFrames ) iFrames /= 2; iFrames = m_pSource->Read( pBuf, iFrames ); + if( iFrames < 0 ) + { + this->SetError( m_pSource->GetError() ); + return iFrames; + } + int iSamples = iFrames * m_pSource->GetNumChannels(); int16_t *pSampleBuf = (int16_t *) pBuf; diff --git a/stepmania/src/RageSoundReader_Preload.cpp b/stepmania/src/RageSoundReader_Preload.cpp index 17abd46c83..b70f93a511 100644 --- a/stepmania/src/RageSoundReader_Preload.cpp +++ b/stepmania/src/RageSoundReader_Preload.cpp @@ -126,6 +126,8 @@ int RageSoundReader_Preload::Read( char *pBuffer, int iFrames ) const int iFramesAvail = iSizeFrames - m_iPosition; iFrames = min( iFrames, iFramesAvail ); + if( iFrames == 0 ) + return END_OF_FILE; memcpy( pBuffer, m_Buffer->data() + (m_iPosition * samplesize), iFrames * samplesize ); m_iPosition += iFrames; diff --git a/stepmania/src/RageSoundReader_Resample_Good.cpp b/stepmania/src/RageSoundReader_Resample_Good.cpp index dab5e13bce..1a30d5b675 100644 --- a/stepmania/src/RageSoundReader_Resample_Good.cpp +++ b/stepmania/src/RageSoundReader_Resample_Good.cpp @@ -726,6 +726,7 @@ int RageSoundReader_Resample_Good::Read( char *pBuf_, int iFrames ) return iFramesRead; } + // XXX: errors return m_pSource->Read( pBuf_, iFrames ); } @@ -735,10 +736,10 @@ int RageSoundReader_Resample_Good::Read( char *pBuf_, int iFrames ) ASSERT( pTmpBuf ); int iFramesIn = m_pSource->Read( (char *) pTmpBuf, iFramesNeeded ); - if( iFramesIn == -1 ) + if( iFramesIn < 0 ) { SetError( m_pSource->GetError() ); - return -1; + return iFramesIn; } const int iSamplesIn = iFramesIn * iChannels; diff --git a/stepmania/src/RageSoundReader_SpeedChange.cpp b/stepmania/src/RageSoundReader_SpeedChange.cpp index 3b99855810..6397ddf24d 100644 --- a/stepmania/src/RageSoundReader_SpeedChange.cpp +++ b/stepmania/src/RageSoundReader_SpeedChange.cpp @@ -85,7 +85,7 @@ static int FindClosestMatch( const int16_t *pBuffer, int iBufferSize, const int1 return iBestOffset; } -void RageSoundReader_SpeedChange::FillData( int iMaxFrames ) +int RageSoundReader_SpeedChange::FillData( int iMaxFrames ) { /* XXX: If the rate or source frame offset changes in the source, we should stop * at that point, so the changes propagate upward. That's tricky, since we want @@ -97,13 +97,16 @@ void RageSoundReader_SpeedChange::FillData( int iMaxFrames ) int iFramesToRead = iMaxFrames - m_iDataBufferAvailFrames; int iBytesToRead = iFramesToRead * m_Channels.size() * sizeof(int16_t); if( iBytesToRead <= 0 ) - return; + return m_iDataBufferAvailFrames; int16_t *pTempBuffer = (int16_t *) alloca( iBytesToRead ); int iGotFrames = m_pSource->Read( (char *) pTempBuffer, iFramesToRead ); - // if( iGotFrames == -1 ) XXX - if( !iGotFrames ) - return; + if( iGotFrames < 0 ) + { + if( iGotFrames == END_OF_FILE && m_iDataBufferAvailFrames ) + return m_iDataBufferAvailFrames; + return iGotFrames; + } for( size_t i = 0; i < m_Channels.size(); ++i ) { @@ -124,6 +127,7 @@ void RageSoundReader_SpeedChange::FillData( int iMaxFrames ) m_iDataBufferAvailFrames += iGotFrames; } + return m_iDataBufferAvailFrames; } void RageSoundReader_SpeedChange::EraseData( int iFramesToDelete ) @@ -145,15 +149,10 @@ void RageSoundReader_SpeedChange::EraseData( int iFramesToDelete ) } } -bool RageSoundReader_SpeedChange::Step() +int RageSoundReader_SpeedChange::Step() { if( m_iDataBufferAvailFrames == 0 ) - { - FillData( GetWindowSizeFrames() ); - if( m_iDataBufferAvailFrames == 0 ) - return false; - return true; - } + return FillData( GetWindowSizeFrames() ); /* If m_iPos is non-zero, we just finished playing a previous block, so advance forward. */ if( m_iPos ) @@ -186,15 +185,21 @@ bool RageSoundReader_SpeedChange::Step() EraseData( iToDelete ); /* Fill as much data as we might need to do the search and use the result. */ - int iMaxPositionNeeded = m_iUncorrelatedPos + GetToleranceFrames() + GetWindowSizeFrames(); - for( size_t i = 0; i < m_Channels.size(); ++i ) - iMaxPositionNeeded = max( iMaxPositionNeeded, m_Channels[i].m_iCorrelatedPos + GetWindowSizeFrames() ); - FillData( iMaxPositionNeeded ); - if( iMaxPositionNeeded > m_iDataBufferAvailFrames ) { - /* We're at EOF. Flush the remaining data, if any. */ - m_iUncorrelatedPos = m_Channels[0].m_iCorrelatedPos; - return true; + int iMaxPositionNeeded = m_iUncorrelatedPos + GetToleranceFrames() + GetWindowSizeFrames(); + for( size_t i = 0; i < m_Channels.size(); ++i ) + iMaxPositionNeeded = max( iMaxPositionNeeded, m_Channels[i].m_iCorrelatedPos + GetWindowSizeFrames() ); + + int iGot = FillData( iMaxPositionNeeded ); + if( iGot < 0 ) + return iGot; + + if( iMaxPositionNeeded > m_iDataBufferAvailFrames ) + { + /* We're at EOF. Flush the remaining data, if any. */ + m_iUncorrelatedPos = m_Channels[0].m_iCorrelatedPos; + return m_iDataBufferAvailFrames; + } } /* Starting at our preferred position (m_iUncorrelatedPos), within GetToleranceFrames(), @@ -214,7 +219,7 @@ bool RageSoundReader_SpeedChange::Step() c.m_iCorrelatedPos = iBest + m_iUncorrelatedPos; ASSERT( m_Channels[i].m_iCorrelatedPos + GetWindowSizeFrames() <= m_iDataBufferAvailFrames ); } - return true; + return m_iDataBufferAvailFrames; } int RageSoundReader_SpeedChange::GetCursorAvail() const @@ -247,9 +252,11 @@ int RageSoundReader_SpeedChange::Read( char *buf, int iFrames ) if( iCursorAvail == 0 ) { - Step(); + int iRet = Step(); + if( iRet < 0 ) + return iRet; if( !GetCursorAvail() ) - return 0; // EOF + return END_OF_FILE; continue; } diff --git a/stepmania/src/RageSoundReader_SpeedChange.h b/stepmania/src/RageSoundReader_SpeedChange.h index 4ca9f39848..68d8e14600 100644 --- a/stepmania/src/RageSoundReader_SpeedChange.h +++ b/stepmania/src/RageSoundReader_SpeedChange.h @@ -25,9 +25,9 @@ public: bool NextReadWillStep() const { return GetCursorAvail() == 0; } protected: - void FillData( int iMax ); + int FillData( int iMax ); void EraseData( int iToDelete ); - bool Step(); + int Step(); void Reset(); /* Get the ratio last set by SetSpeedRatio. */ diff --git a/stepmania/src/RageSoundReader_Vorbisfile.cpp b/stepmania/src/RageSoundReader_Vorbisfile.cpp index 240a072be2..cf61411f21 100644 --- a/stepmania/src/RageSoundReader_Vorbisfile.cpp +++ b/stepmania/src/RageSoundReader_Vorbisfile.cpp @@ -225,7 +225,7 @@ int RageSoundReader_Vorbisfile::Read( char *buf, int iFrames ) if( ret == OV_EBADLINK ) { SetError( ssprintf("Read: OV_EBADLINK") ); - return -1; + return ERROR; } if( ret == 0 ) @@ -243,6 +243,9 @@ int RageSoundReader_Vorbisfile::Read( char *buf, int iFrames ) iFrames -= iFramesRead; } + if( !frames_read ) + return END_OF_FILE; + return frames_read; } diff --git a/stepmania/src/RageSoundReader_WAV.cpp b/stepmania/src/RageSoundReader_WAV.cpp index 7b90406a6a..a47d728727 100644 --- a/stepmania/src/RageSoundReader_WAV.cpp +++ b/stepmania/src/RageSoundReader_WAV.cpp @@ -79,6 +79,9 @@ struct WavReaderPCM: public WavReader len /= 2; const int iBytesLeftInDataChunk = m_WavData.m_iDataChunkSize - (m_File.Tell() - m_WavData.m_iDataChunkPos); + if( !iBytesLeftInDataChunk ) + return RageSoundReader::END_OF_FILE; + len = min( len, iBytesLeftInDataChunk ); int iGot = m_File.Read( buf, len ); int iGotSamples = 0; @@ -296,10 +299,15 @@ public: if( m_iBufferUsed == m_iBufferAvail ) { if( !DecodeADPCMBlock() ) - return -1; + return RageSoundReader::ERROR; } if( m_iBufferAvail == 0 ) - break; /* EOF */ + { + if( !iGotFrames ) + return RageSoundReader::END_OF_FILE; + else + return iGotFrames; + } int iFramesToCopy = (m_iBufferAvail-m_iBufferUsed) / iBytesPerFrame; iFramesToCopy = min( iFramesToCopy, (int) (iFrames-iGotFrames) );