include/cinder/audio/CircularBuffer.h
Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2009, The Barbarian Group
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00006  the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00009     the following disclaimer.
00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
00012 
00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00020  POSSIBILITY OF SUCH DAMAGE.
00021 */
00022 
00023 #pragma once
00024 
00025 namespace cinder { namespace audio {
00026 
00027 template<typename T>
00028 class CircularBuffer {
00029  public:
00030     typedef std::pair<T*,uint32_t> ArrayRange;
00031  
00032     CircularBuffer( uint32_t size );
00033     ~CircularBuffer();
00034     
00035     void insert( const T* src, uint32_t size );
00036     
00037     ArrayRange arrayOne() const {
00038         return ArrayRange( mBufferStart, ( mBufferStart >= mBufferLast && mSize == mMaxSize ) ? ( mBufferEnd - mBufferStart ) : mSize );
00039     }
00040     ArrayRange arrayTwo() const {
00041         uint32_t size = ( mBufferStart >= mBufferLast && mSize == mMaxSize ) ? ( mBufferLast - mBuffer ) : 0;
00042         return ArrayRange( mBufferLast - size, size );
00043     }
00044     
00045     uint32_t size() const { return mSize; }
00046     uint32_t maxSize() const { return mMaxSize; }
00047     
00048  private:
00049     T * mBuffer;
00050     T * mBufferLast;
00051     T * mBufferStart;
00052     T * mBufferEnd;
00053     
00054     uint32_t mMaxSize;
00055     uint32_t mSize;
00056     
00057 };
00058 
00059 template<typename T>
00060 CircularBuffer<T>::CircularBuffer( uint32_t size ) 
00061     : mMaxSize( size ), mSize( 0 )
00062 {
00063     mBuffer = new T[mMaxSize];
00064     mBufferEnd = mBuffer + mMaxSize;
00065     mBufferStart = mBuffer;
00066     mBufferLast = mBuffer;
00067     
00068 }
00069 
00070 template<typename T>
00071 CircularBuffer<T>::~CircularBuffer()
00072 {
00073     delete [] mBuffer;
00074 }
00075 
00076 template<typename T>
00077 void CircularBuffer<T>::insert( const T* src, uint32_t size )
00078 {
00079     if( size > mMaxSize ) {
00080         throw; //TODO
00081     }
00082     
00083     //TODO: size adjustments can probably be better handled with a modulous
00084     if( ( mBufferLast + size ) > mBufferEnd ) {
00085         uint32_t copySize = mBufferEnd - mBufferLast;
00086         memcpy( mBufferLast, src, sizeof(T) * copySize );
00087         mBufferLast = mBuffer;
00088         if( mSize < mMaxSize ) {
00089             mSize = mMaxSize;
00090         }
00091         src = src + copySize;
00092         copySize = size - copySize;
00093         memcpy( mBufferLast, src, sizeof(T) * copySize );
00094         mBufferLast += copySize;
00095         mBufferStart = mBufferLast;
00096     } else {
00097         memcpy( mBufferLast, src, sizeof(T) * size );
00098         mBufferLast += size;
00099         if( mSize < mMaxSize ) {
00100             mSize += size;
00101         } else {
00102             mBufferStart = mBufferLast;
00103             if( mBufferStart == mBufferEnd ) {
00104                 mBufferStart = mBuffer;
00105             }
00106         }
00107     }
00108 }
00109 
00110 
00111 }} //namespace