void BufferedAudioSourceThread::run() { std::vector<float> tempBuffer; while(1) { mReadMore.wait(); if(shouldThreadExit()) break; { // create a local scope for our locking object RScopedLock l(&mLock); for(UInt32 i = 0; i < mSources.size(); ++i) { BufferedAudioSource *pSource = mSources[i]; pSource->mLock.lock(); Int64 totalFrames = pSource->getSampleRate() * SECONDS_TO_BUFFER; Int64 framesThreshold = totalFrames / 2; // Int64 availableFrames = pSource->mBuffer.size() / pSource->getNumChannels(); pSource->mLock.unlock(); if(availableFrames <= framesThreshold) { Int64 numFrames = totalFrames - availableFrames; Int64 framesToRead = numFrames; Int64 frames = 0; tempBuffer.resize(numFrames * pSource->getNumChannels()); float *pBuffer = &tempBuffer[0]; // keep track of last known version when starting to buffer // to discard any previously buffered data in case source // changed position. This avoids having to keep a lock // while buffering data. int lastVersion = pSource->getPositionVersion(); while(framesToRead > 0 && !pSource->isEOF()) { int currentVersion = 0; frames = pSource->decodeData(pBuffer, framesToRead, currentVersion); // check if version changed since we started buffering // and discard everything we've buffered before if so if (currentVersion != lastVersion) { tempBuffer.erase(tempBuffer.begin(), tempBuffer.begin() + ((numFrames - framesToRead) * pSource->getNumChannels())); tempBuffer.resize(numFrames * pSource->getNumChannels()); pBuffer = &tempBuffer[0]; framesToRead = numFrames; } framesToRead -= frames; pBuffer += frames * pSource->getNumChannels(); lastVersion = currentVersion; } // Now write the data back to the buffer Int64 framesRead = numFrames - framesToRead; if(framesRead > 0) { pSource->mLock.lock(); pSource->mBuffer.putData(&tempBuffer[0], framesRead * pSource->getNumChannels()); pSource->mLock.unlock(); } } } } } }
void BufferedAudioSourceThread::run() { std::vector<float> tempBuffer; while(1) { mReadMore.wait(); if(shouldThreadExit()) break; mLock.lock(); for(UInt32 i = 0; i < mSources.size(); ++i) { BufferedAudioSource *pSource = mSources[i]; pSource->mLock.lock(); Int64 totalFrames = pSource->getSampleRate() * SECONDS_TO_BUFFER; Int64 availableFrames = pSource->mBuffer.size() / pSource->getNumChannels(); pSource->mLock.unlock(); if(availableFrames < totalFrames) { Int64 numFrames = totalFrames - availableFrames; Int64 framesToRead = numFrames; Int64 frames = 0; tempBuffer.resize(numFrames * pSource->getNumChannels()); float *pBuffer = &tempBuffer[0]; do { frames = pSource->decodeData(pBuffer, framesToRead); framesToRead -= frames; pBuffer += frames * pSource->getNumChannels(); } while(framesToRead > 0 && !pSource->isEOF()); // Now write the data back to the buffer Int64 framesRead = numFrames - framesToRead; if(framesRead > 0) { pSource->mLock.lock(); int fillPosition = pSource->mBuffer.size(); Int64 totalSamples = pSource->mBuffer.size() + framesRead * pSource->getNumChannels(); pSource->mBuffer.resize(totalSamples); memcpy(&pSource->mBuffer[fillPosition], &tempBuffer[0], sizeof(float) * framesRead * pSource->getNumChannels()); pSource->mLock.unlock(); } // Check if we've reached the end /* double loopStart; double loopEnd; pSource->getLoopPoints(loopStart, loopEnd); Int64 loopEndFrame = pSource->convertSecondsToSamples(pSource->mLoopEnd); if(pSource->isLooping() && pSource->mCurrentFrame >= loopEndFrame && loopEndFrame > 0) pSource->setPosition(loopStart); if(pSource->isEOF() || (pSource->mCurrentFrame >= loopEndFrame && loopEndFrame > 0)) { if(pSource->isLooping()) // Reset the buffering position and keep on going... pSource->setPosition(loopStart); // else // // We didn't fill the whole buffer, so resize appropriately // pSource->mBuffer.resize(availableFrames + numFrames - framesToRead); } */ } } mLock.unlock(); } }