CARingBufferError CARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead) { SampleTime endRead = startRead + nFrames; SampleTime startRead0 = startRead; SampleTime endRead0 = endRead; CARingBufferError err = ClipTimeBounds(startRead, endRead); SampleTime readSizeFrames = endRead - startRead; if (err) { if ( readSizeFrames <= 0 ) { CARB_DEBUG( "POS1 read size frames too little. (%ld)\n", err ); return err; } } SInt32 destStartFrameOffset = startRead - startRead0; if ( destStartFrameOffset > 0 ) { CARB_DEBUG( "Fetch - Zeroing start bound\n" ); ZeroABL(abl, 0, destStartFrameOffset * mBytesPerFrame); } SInt32 destEndSize = endRead0 - endRead; if ( destEndSize > 0 ) { CARB_DEBUG( "Fetch - Zeroing end bound (%ld frames off)\n", destEndSize ); ZeroABL(abl, ( destStartFrameOffset + readSizeFrames ) * mBytesPerFrame, destEndSize * mBytesPerFrame); } Byte **buffers = mBuffers; int offset0 = FrameOffset(startRead); int offset1 = FrameOffset(endRead); int destStartByteOffset = destStartFrameOffset * mBytesPerFrame; int nbytes; if ( offset0 < offset1 ) { nbytes = offset1 - offset0; FetchABL( abl, destStartByteOffset , buffers, offset0, nbytes ); } else { nbytes = mCapacityBytes - offset0; FetchABL( abl, destStartByteOffset , buffers, offset0, nbytes ); FetchABL( abl, destStartByteOffset + nbytes, buffers, 0 , offset1 ); nbytes += offset1; } int nchannels = abl->mNumberBuffers; AudioBuffer *dest = abl->mBuffers; while (--nchannels >= 0) { dest->mDataByteSize = nbytes; dest++; } OSStatus err2 = ClipTimeBounds( startRead, endRead ); err2 = worse( err, err2 ); readSizeFrames = endRead - startRead; if ( err2 ) { if ( readSizeFrames <= 0 ) { CARB_DEBUG( "POS2 read size frames too little. (%ld)\n", err2 ); return err2; } } if ( err2 ) { CARB_DEBUG( "Returning error %ld.\n", err2 ); } return err2; }
bool AudioRingBuffer::Store(const Byte *data, UInt32 nFrames, SInt64 startFrame) { if (nFrames > mCapacityFrames) return false; // $$$ we have an unaddressed critical region here // reading and writing could well be in separate threads SInt64 endFrame = startFrame + nFrames; if (startFrame >= mEndFrame + mCapacityFrames) // writing more than one buffer ahead -- fine but that means that everything we have is now too far in the past Clear(); if (mStartFrame == 0) { // empty buffer mStartOffset = 0; mStartFrame = startFrame; mEndFrame = endFrame; memcpy(mBuffer, data, nFrames * mBytesPerFrame); } else { UInt32 offset0, offset1, nBytes; if (endFrame > mEndFrame) { // advancing (as will be usual with sequential stores) if (startFrame > mEndFrame) { // we are skipping some samples, so zero the range we are skipping offset0 = FrameOffset(mEndFrame); offset1 = FrameOffset(startFrame); if (offset0 < offset1) memset(mBuffer + offset0, 0, offset1 - offset0); else { nBytes = mCapacityBytes - offset0; memset(mBuffer + offset0, 0, nBytes); memset(mBuffer, 0, offset1); } } mEndFrame = endFrame; // except for the case of not having wrapped yet, we will normally // have to advance the start SInt64 newStart = mEndFrame - mCapacityFrames; if (newStart > mStartFrame) { mStartOffset = (mStartOffset + (newStart - mStartFrame) * mBytesPerFrame) % mCapacityBytes; mStartFrame = newStart; } } // now everything is lined up and we can just write the new data offset0 = FrameOffset(startFrame); offset1 = FrameOffset(endFrame); if (offset0 < offset1) memcpy(mBuffer + offset0, data, offset1 - offset0); else { nBytes = mCapacityBytes - offset0; memcpy(mBuffer + offset0, data, nBytes); memcpy(mBuffer, data + nBytes, offset1); } } //printf("Store - buffer times: %.0f - %.0f, writing %.0f - %.0f\n", double(mStartFrame), double(mEndFrame), double(startFrame), double(endFrame)); return true; }
double AudioRingBuffer::Fetch(Byte *data, UInt32 nFrames, SInt64 startFrame) { //printf("read()\n"); SInt64 endFrame = startFrame + nFrames; if (startFrame < mStartFrame || endFrame > mEndFrame) { //printf("error - buffer times: %.0f - %.0f, reading for %.0f - %.0f\n", double(mStartFrame), double(mEndFrame), double(startFrame), double(endFrame)); if (startFrame < mStartFrame) return double(startFrame - mStartFrame); else return double(endFrame - mEndFrame); } UInt32 offset0 = FrameOffset(startFrame); UInt32 offset1 = FrameOffset(endFrame); if (offset0 < offset1) { //printf("r-memcpy C\n"); memcpy(data, mBuffer + offset0, offset1 - offset0); } else { //printf("r-memcpy D\n"); UInt32 nBytes = mCapacityBytes - offset0; memcpy(data, mBuffer + offset0, nBytes); memcpy(data + nBytes, mBuffer, offset1); } return double((mEndFrame - nFrames) - startFrame); }
CARingBufferError CARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead, bool outOfBoundsOK) { SampleTime endRead = startRead + nFrames; SampleTime startRead0 = startRead; SampleTime endRead0 = endRead; SampleTime size; CARingBufferError err = CheckTimeBounds(startRead, endRead); size = endRead - startRead; if (err) { if (!outOfBoundsOK) return err; if (size <= 0) return err; // there is nothing to read } SInt32 destStartOffset = startRead - startRead0; if (destStartOffset > 0) { ZeroABL(abl, 0, destStartOffset * mBytesPerFrame); } SInt32 destEndSize = endRead0 - endRead; if (destEndSize > 0) { ZeroABL(abl, destStartOffset + size, destEndSize * mBytesPerFrame); } Byte **buffers = mBuffers; int offset0 = FrameOffset(startRead); int offset1 = FrameOffset(endRead); int nbytes; if (offset0 < offset1) { FetchABL(abl, destStartOffset, buffers, offset0, nbytes = offset1 - offset0); } else { nbytes = mCapacityBytes - offset0; FetchABL(abl, destStartOffset, buffers, offset0, nbytes); FetchABL(abl, destStartOffset + nbytes, buffers, 0, offset1); nbytes += offset1; } int nchannels = abl->mNumberBuffers; AudioBuffer *dest = abl->mBuffers; while (--nchannels >= 0) { dest->mDataByteSize = nbytes; dest++; } // have to check bounds again because the data may have been overwritten before we could finish reading it. OSStatus err2 = CheckTimeBounds(startRead, endRead); err2 = worse(err, err2); size = endRead - startRead; if (err2) { if (!outOfBoundsOK) return err2; if (size <= 0) return err2; // there is nothing to read } return err2; }
CARingBufferError CARingBuffer::Store(const AudioBufferList *abl, UInt32 framesToWrite, SampleTime startWrite) { if (framesToWrite > mCapacityFrames) return kCARingBufferError_TooMuch; // too big! SampleTime endWrite = startWrite + framesToWrite; if (startWrite < EndTime()) { // going backwards, throw everything out SetTimeBounds(startWrite, startWrite); } else if (endWrite - StartTime() <= mCapacityFrames) { // the buffer has not yet wrapped and will not need to } else { // advance the start time past the region we are about to overwrite SampleTime newStart = endWrite - mCapacityFrames; // one buffer of time behind where we're writing SampleTime newEnd = std::max(newStart, EndTime()); SetTimeBounds(newStart, newEnd); } // write the new frames Byte **buffers = mBuffers; int nchannels = mNumberChannels; int offset0, offset1, nbytes; SampleTime curEnd = EndTime(); if (startWrite > curEnd) { // we are skipping some samples, so zero the range we are skipping offset0 = FrameOffset(curEnd); offset1 = FrameOffset(startWrite); if (offset0 < offset1) ZeroRange(buffers, nchannels, offset0, offset1 - offset0); else { ZeroRange(buffers, nchannels, offset0, mCapacityBytes - offset0); ZeroRange(buffers, nchannels, 0, offset1); } offset0 = offset1; } else { offset0 = FrameOffset(startWrite); } offset1 = FrameOffset(endWrite); if (offset0 < offset1) StoreABL(buffers, offset0, abl, 0, offset1 - offset0); else { nbytes = mCapacityBytes - offset0; StoreABL(buffers, offset0, abl, 0, nbytes); StoreABL(buffers, 0, abl, nbytes, offset1); } // now update the end time SetTimeBounds(StartTime(), endWrite); return kCARingBufferError_OK; // success }
CARingBufferError CARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead) { SampleTime endRead = startRead + nFrames; SampleTime startRead0 = startRead; SampleTime endRead0 = endRead; SampleTime size; CARingBufferError err = ClipTimeBounds(startRead, endRead); if (err) return err; size = endRead - startRead; SInt32 destStartOffset = startRead - startRead0; if(destStartOffset > nFrames) return kCARingBufferError_CPUOverload; if (destStartOffset > 0) { ZeroABL(abl, 0, destStartOffset * mBytesPerFrame); } SInt32 destEndSize = endRead0 - endRead; if (destEndSize > 0) { ZeroABL(abl, destStartOffset + size, destEndSize * mBytesPerFrame); } Byte **buffers = mBuffers; int offset0 = FrameOffset(startRead); int offset1 = FrameOffset(endRead); int nbytes; if (offset0 < offset1) { FetchABL(abl, destStartOffset, buffers, offset0, nbytes = offset1 - offset0); } else { nbytes = mCapacityBytes - offset0; FetchABL(abl, destStartOffset, buffers, offset0, nbytes); FetchABL(abl, destStartOffset + nbytes, buffers, 0, offset1); nbytes += offset1; } int nchannels = abl->mNumberBuffers; AudioBuffer *dest = abl->mBuffers; while (--nchannels >= 0) { dest->mDataByteSize = nbytes; dest++; } return noErr; }
FSTCARingBufferError FSTCARingBuffer::Fetch(AudioBufferList *abl, UInt32 nFrames, SampleTime startRead) { SampleTime endRead = startRead + nFrames; SampleTime startRead0 = startRead; SampleTime endRead0 = endRead; SampleTime size; FSTCARingBufferError err = ClipTimeBounds(startRead, endRead); if (err) return err; size = endRead - startRead; SInt32 idx, destStartOffset = startRead - startRead0; if(mBufferList) { for(idx=0; idx<mBufferList->mNumberBuffers; idx++) { AudioBuffer * storeBuf = &mBufferList->mBuffers[idx], * fetchBuf = &abl->mBuffers[idx]; mCapacityBytes = sizeof(float)*storeBuf->mNumberChannels * mCapacityFrames; if (destStartOffset > 0) { ZeroAB(fetchBuf, 0, destStartOffset * sizeof(float)*fetchBuf->mNumberChannels); } SInt32 destEndSize = endRead0 - endRead; if (destEndSize > 0) { ZeroAB(fetchBuf, (destStartOffset + size) * sizeof(float)*fetchBuf->mNumberChannels, destEndSize * sizeof(float)*fetchBuf->mNumberChannels); } int offset0 = startRead * sizeof(float) * storeBuf->mNumberChannels; int offset1 = endRead * sizeof(float) * storeBuf->mNumberChannels; int nbytes; if(offset0 == offset1 == 0) { nbytes = 0; } if (offset0 < offset1) { FetchAB(fetchBuf, destStartOffset, storeBuf, offset0, nbytes = offset1 - offset0); } else { nbytes = mCapacityBytes - offset0; FetchAB(fetchBuf, destStartOffset, storeBuf, offset0, nbytes); FetchAB(fetchBuf, destStartOffset + nbytes, storeBuf, 0, offset1); nbytes += offset1; } fetchBuf->mDataByteSize = nbytes; } } else { if (destStartOffset > 0) { ZeroABL(abl, 0, destStartOffset * mBytesPerFrame); } SInt32 destEndSize = endRead0 - endRead; if (destEndSize > 0) { ZeroABL(abl, destStartOffset + size, destEndSize * mBytesPerFrame); } Byte **buffers = mBuffers; int offset0 = FrameOffset(startRead); int offset1 = FrameOffset(endRead); int nbytes; if (offset0 < offset1) { FetchBufs(abl, destStartOffset, buffers, offset0, nbytes = offset1 - offset0); } else { nbytes = mCapacityBytes - offset0; FetchBufs(abl, destStartOffset, buffers, offset0, nbytes); FetchBufs(abl, destStartOffset + nbytes, buffers, 0, offset1); nbytes += offset1; } int nchannels = abl->mNumberBuffers; AudioBuffer *dest = abl->mBuffers; while (--nchannels >= 0) { dest->mDataByteSize = nbytes; dest++; } } return noErr; }
FSTCARingBufferError FSTCARingBuffer::Store(const AudioBufferList *abl, UInt32 framesToWrite, SampleTime startWrite) { if (framesToWrite > mCapacityFrames) return kFSTCARingBufferError_TooMuch; // too big! if(startWrite > mCapacityFrames) return kFSTCARingBufferError_CPUOverload; SampleTime endWrite = startWrite + framesToWrite; if (startWrite < EndTime()) { // going backwards, throw everything out SetTimeBounds(startWrite, startWrite); } else if (endWrite - StartTime() <= mCapacityFrames) { // the buffer has not yet wrapped and will not need to } else { // advance the start time past the region we are about to overwrite SampleTime newStart = endWrite - mCapacityFrames; // one buffer of time behind where we're writing SampleTime newEnd = std::max(newStart, EndTime()); SetTimeBounds(newStart, newEnd); } int idx, offset0, offset1, nbytes; SampleTime curEnd = EndTime(); if(mBufferList) { int numBuffs = abl->mNumberBuffers; if(numBuffs > mBufferList->mNumberBuffers) numBuffs = mBufferList->mNumberBuffers; for(idx=0; idx<numBuffs; idx++) { AudioBuffer * buffer = &mBufferList->mBuffers[idx]; mCapacityBytes = sizeof(float)*buffer->mNumberChannels * mCapacityFrames; if (startWrite > curEnd) { // we are skipping some samples, so zero the range we are skipping offset0 = curEnd * sizeof(float) * buffer->mNumberChannels; offset1 = startWrite * sizeof(float) * buffer->mNumberChannels; if (offset0 < offset1) { ZeroRangeAB(buffer, offset0, offset1 - offset0); } else { ZeroRangeAB(buffer, offset0, mCapacityBytes - offset0); ZeroRangeAB(buffer, 0, offset1); } offset0 = offset1; } else { offset0 = startWrite * sizeof(float) * buffer->mNumberChannels; } offset1 = endWrite * sizeof(float) * buffer->mNumberChannels; if (offset0 < offset1) StoreAB(buffer, offset0, &abl->mBuffers[idx], 0, offset1 - offset0); else { nbytes = mCapacityBytes - offset0; StoreAB(buffer, offset0, &abl->mBuffers[idx], 0, nbytes); StoreAB(buffer, 0, &abl->mBuffers[idx], nbytes, offset1); } } } else { // write the new frames Byte **buffers = mBuffers; int nchannels = mNumberChannels; if (startWrite > curEnd) { // we are skipping some samples, so zero the range we are skipping offset0 = FrameOffset(curEnd); offset1 = FrameOffset(startWrite); if (offset0 < offset1) ZeroRange(buffers, nchannels, offset0, offset1 - offset0); else { ZeroRange(buffers, nchannels, offset0, mCapacityBytes - offset0); ZeroRange(buffers, nchannels, 0, offset1); } offset0 = offset1; } else { offset0 = FrameOffset(startWrite); } offset1 = FrameOffset(endWrite); if (offset0 < offset1) StoreBufs(buffers, offset0, abl, 0, offset1 - offset0); else { nbytes = mCapacityBytes - offset0; StoreBufs(buffers, offset0, abl, 0, nbytes); StoreBufs(buffers, 0, abl, nbytes, offset1); } } // now update the end time SetTimeBounds(StartTime(), endWrite); return kFSTCARingBufferError_OK; // success }