IFrame* AudioFrameBuffer::getFrame(const size_t size) { LOG_DEBUG("Get a " << size << " bytes frame from a " << _totalDataSize << " bytes frame buffer"); IFrame* next = _frameQueue.front(); const size_t nextFrameSize = next->getDataSize(); // If no expected size, or if the expected size equals the front frame of the queue (with no offset) if(size == 0 || (size == nextFrameSize && _positionInFrontFrame == 0)) { // Directly return the front frame of the queue _totalDataSize -= nextFrameSize; popFrame(); return next; } // Create a new frame AudioFrame* newAudioFrame = new AudioFrame(_audioFrameDesc, false); const size_t expectedNbSamples = size / (newAudioFrame->getNbChannels() * newAudioFrame->getBytesPerSample()); newAudioFrame->setNbSamplesPerChannel(expectedNbSamples); newAudioFrame->allocateData(); // Concatenate frames data size_t extractedDataSize = 0; unsigned char* outputData = new unsigned char[size]; while(extractedDataSize != size && _frameQueue.size() != 0) { // Get the front frame from queue next = _frameQueue.front(); size_t remainingDataInFrontFrame = next->getDataSize() - _positionInFrontFrame; // Compute the data size to get from the frame size_t dataToGet = size - extractedDataSize; if(dataToGet > remainingDataInFrontFrame) dataToGet = remainingDataInFrontFrame; // Copy the data from the frame to temporal buffer for(size_t i = 0; i < dataToGet; i++) outputData[extractedDataSize++] = next->getData()[0][_positionInFrontFrame + i]; if(dataToGet < remainingDataInFrontFrame) { // Set new position into front frame _positionInFrontFrame += dataToGet; } else { // The whole front frame has been read, so pop it from queue popFrame(); _positionInFrontFrame = 0; } } _totalDataSize -= extractedDataSize; newAudioFrame->assignBuffer(outputData); return newAudioFrame; }