CircularBuffer.hxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef _CircularBuffer_
00023 #define _CircularBuffer_
00024 
00025 #include "Array.hxx"
00026 #include "DataTypes.hxx"
00027 #include "Err.hxx"
00028 
00029 namespace CLAM
00030 {
00031 
00032 
00046         template <class T> class CircularBuffer
00047         {
00048         protected: 
00049                 Array<T> mBuffer;
00050                 TSize mLogicalSize;
00051                 TSize mReadSize;
00052                 TSize mWriteSize;
00053                 TSize mWriteIndex; // XXX: might want these mutable and read-like methods declared const
00054                 TSize mReadIndex; // XXX: might want these mutable and read-like methods declared const
00055                 TSize mInitialReadOffset;
00056                 TSize mInitialWriteOffset;
00057         
00058         public:
00059          
00066                 CircularBuffer() : mBuffer()
00067                 {
00068                         mWriteIndex = 0;                                
00069                         mReadIndex = 0;
00070                         mReadSize = mWriteSize = 1;
00071                         mInitialReadOffset = 0;
00072                         mInitialWriteOffset = 0;
00073                         SetBufferSize(0);
00074                         mLogicalSize = 0;
00075                 }
00076                 
00082                 CircularBuffer(TSize bufferSize) : mBuffer(bufferSize)
00083                 {
00084                         CLAM_ASSERT(bufferSize > 0, "CircularBuffer:CircularBuffer: BufferSize has to be larger than zero");
00085                         SetBufferSize(bufferSize);
00086                         mWriteIndex = 0;                                
00087                         mReadIndex = 0;
00088                         mReadSize = mWriteSize = 1;
00089                         mInitialReadOffset = 0;
00090                         mInitialWriteOffset = 0;
00091                         mLogicalSize = 0;
00092                 }
00093 
00094                 // Methods for setting up the buffer: -------------------------------------------
00095 
00099                 TSize GetBufferSize() const
00100                 {
00101                         return mBuffer.Size()-GetReadSize();
00102                 }
00103 
00109                 void SetBufferSize(TSize size)
00110                 {
00111                         mBuffer.Resize(size+GetReadSize());
00112                         mBuffer.SetSize(size+GetReadSize());
00113                         InitPointers();
00114                 }
00115 
00120                 TSize GetWriteIndex() const
00121                 {
00122                         return mWriteIndex;
00123                 }
00124 
00129                 TSize GetReadIndex() const
00130                 {
00131                         return mReadIndex;
00132                 }
00133 
00139                 TSize GetInitialReadOffset() const
00140                 {
00141                         return mInitialReadOffset;
00142                 }
00143 
00150                 void SetInitialReadOffset(TSize size)
00151                 {
00152                         CLAM_ASSERT((size >= 0)&&(size < GetBufferSize()-1),
00153                                 "CircularBuffer:SetInitialReadOffset: InitialReadOffset has to be larger than zero");
00154                         mInitialReadOffset = size;
00155                 }
00156 
00162                 TSize GetInitialWriteOffset() const
00163                 {
00164                         return mInitialWriteOffset;
00165                 }
00166 
00173                 void SetInitialWriteOffset(TSize size)
00174                 {
00175                         CLAM_ASSERT((size >= 0)&&(size < GetBufferSize()-1),
00176                                 "CircularBuffer:SetInitialWriteOffset: InitialWriteOffset has to be larger than zero");
00177                         mInitialWriteOffset = size;
00178                 }
00179 
00180                 // Methods for data acces: ------------------------------------------------------
00181         
00187                 void Init()
00188                 {
00189                         SetBufferToZero();
00190                         InitPointers();
00191                 }
00192 
00196                 void SetBufferToZero()
00197                 {
00198                         T *pBuffer;
00199                         pBuffer = mBuffer.GetPtr();
00200                         memset(pBuffer, 0, GetBufferSize()*sizeof(T));
00201                 }
00202 
00207                 void InitPointers()
00208                 {
00209                         if(mInitialReadOffset < 0)
00210                                 mReadIndex = GetBufferSize() + mInitialReadOffset;
00211                         else
00212                                 mReadIndex = mInitialReadOffset;
00213                         if(mInitialWriteOffset < 0)
00214                                 mWriteIndex = GetBufferSize() + mInitialWriteOffset;
00215                         else
00216                                 mWriteIndex = mInitialWriteOffset;
00217                         mLogicalSize=0;
00218                 }
00219 
00220                 // Methods for reading and writing: ---------------------------------------------
00221 
00226                 void Read(T& element)
00227                 {
00228                         element = mBuffer[mReadIndex];
00229                         IncreaseReadIndex();
00230                 }
00231 
00232                 
00233                 void NonCopyRead(Array<T>& buffer)
00234                 {
00235                         TSize limit;
00236                         if((limit=mReadIndex+mReadSize)>GetBufferSize())
00237                         {
00238                                 //will have to use phantom zone 
00239                                 memcpy(mBuffer.GetPtr()+GetBufferSize(),mBuffer.GetPtr(),mReadSize*sizeof(T));
00240                         }
00241                         buffer.SetPtr(mBuffer.GetPtr()+mReadIndex,mReadSize);
00242                         IncreaseReadIndex(mReadSize);
00243 
00244 
00245                 }
00246                 
00253                 void Read(T* buffer)
00254                 {
00255                         TSize limit;
00256                         if((limit=mReadIndex+mReadSize)>GetBufferSize())
00257                         {
00258                                 TSize secondHalf=limit%GetBufferSize();
00259                                 TSize firstHalf=mReadSize-secondHalf;
00260                                 memcpy(buffer,mBuffer.GetPtr()+mReadIndex,firstHalf*sizeof(T));
00261                                 memcpy(buffer+firstHalf,mBuffer.GetPtr(),secondHalf*sizeof(T));
00262                         }
00263                         else
00264                         {
00265                                 memcpy(buffer,mBuffer.GetPtr()+mReadIndex,mReadSize*sizeof(T));
00266                         }
00267                         
00268                         IncreaseReadIndex(mReadSize);
00269                 }
00270 
00280                 void Read(Array<T>& in, TSize offset = 0) // XXX: maybe call in, out instead?
00281                 {
00282                         CLAM_ASSERT(GetReadSize() <= in.Size()+offset, "Error, input buffer is not large enough"); // XXX: maybe call the input buffer the output buffer?
00283 
00284 #ifdef CLAM_HIGH_OPTIMIZATIONS
00285                         Read(in.GetPtr()+offset);
00286 #else
00287                         for(int i=0;i<mReadSize;i++)
00288                                 Read(in[i+offset]);
00289 #endif
00290                 }
00291 
00295                 void Write(const T& element)
00296                 {
00297                         mBuffer[mWriteIndex] = element;
00298                         IncreaseWriteIndex();
00299                 }
00300 
00306                 void Write(const T* buffer)
00307                 {
00308                         TSize limit;
00309                         if((limit=mWriteIndex+mWriteSize)>GetBufferSize())
00310                         {
00311                                 TSize secondHalf=limit%GetBufferSize();
00312                                 TSize firstHalf=mWriteSize-secondHalf;
00313                                 memcpy(mBuffer.GetPtr()+mWriteIndex,buffer,firstHalf*sizeof(T));
00314                                 memcpy(mBuffer.GetPtr(),buffer+firstHalf,secondHalf*sizeof(T));
00315                         }
00316                         else
00317                         {
00318                                 memcpy(mBuffer.GetPtr()+mWriteIndex,buffer,mWriteSize*sizeof(T));
00319                         }
00320                         
00321                         IncreaseWriteIndex(mWriteSize);
00322                 }
00323 
00331                 void Write(const Array<T>& in, TSize offset = 0) 
00332                 {
00333                         CLAM_ASSERT(GetWriteSize()<=in.Size()+offset,"Error, input buffer is not large enough");
00334 #ifdef CLAM_HIGH_OPTIMIZATIONS
00335                         Write(in.GetPtr()+offset);
00336 #else
00337                         for(int i=0;i<mWriteSize;i++)
00338                                 Write(in[i+offset]);
00339 #endif
00340                 }
00341 
00347                 void Add(const T& elem)
00348                 {
00349                         mBuffer[mWriteIndex] += elem;
00350                         IncreaseWriteIndex();
00351                 }
00352 
00360                 void Add(const Array<T>& in, TSize offset = 0)
00361                 {
00362                         CLAM_ASSERT(GetWriteSize()<=in.Size()+offset,"Error, input buffer is not large enough");
00363                         for(int i=0;i<mWriteSize;i++)
00364                                 Add(in[i+offset]);
00365                         // XXX: might also want a CLAM_HIGH_OPTIMIZATIONS version of this method...
00366                 }
00367 
00372                 void IncreaseReadIndex(TSize step = 1)
00373                 {
00374                         mReadIndex += step;
00375                         mReadIndex=mReadIndex%GetBufferSize();
00376                         mLogicalSize-=step;
00377                         CLAM_ASSERT(mLogicalSize>=0,"Error:Read Index surpassed Write Index");
00378                 }
00379 
00384                 void IncreaseWriteIndex(TSize step = 1)
00385                 {
00386                         // XXX: might want to assert that step > 0
00387                         mWriteIndex += step;
00388                         mWriteIndex =mWriteIndex%GetBufferSize();
00389                         mLogicalSize+=step;
00390                         CLAM_ASSERT(mLogicalSize<=GetBufferSize(),"Error:Write Index surpassed Read Index");
00391                 }
00392 
00397                 void DecreaseReadIndex(TSize step = 1)
00398                 {
00399                         // XXX: might want to assert that step > 0
00400                         mReadIndex -= step;
00401                         mReadIndex =mReadIndex%GetBufferSize();
00402                         if(mReadIndex<0) mReadIndex=GetBufferSize()+mReadIndex;
00403                         mLogicalSize+=step;
00404                         CLAM_ASSERT(mLogicalSize<=GetBufferSize(),"Error:Write Index surpassed Read Index");
00405                 }
00406 
00411                 void DecreaseWriteIndex(TSize step = 1)
00412                 {
00413                         // XXX: might want to assert that step > 0
00414                         mWriteIndex -= step;
00415                         mWriteIndex =mWriteIndex%GetBufferSize();
00416                         if(mWriteIndex<0) mWriteIndex =GetBufferSize()+mWriteIndex ;
00417                         mLogicalSize-=step;
00418                         CLAM_ASSERT(mLogicalSize>=0,"Error:Read Index surpassed Write Index");
00419                 }
00420 
00426                 T& GetPtrToElement(int absPos)
00427                 {
00428                         int index = absPos%GetBufferSize(); // XXX: unnecessary copy.
00429                         
00430                         return mBuffer[index];
00431                 }
00432                 
00433                 // Getters and setters: ---------------------------------------------------------
00434 
00440                 TSize GetReadSize() const
00441                 {
00442                         return mReadSize;
00443                 }
00444 
00450                 TSize GetWriteSize() const
00451                 {
00452                         return mWriteSize;
00453                 }
00454 
00459                 void SetReadSize(TSize size)
00460                 {
00461                         CLAM_ASSERT(size>=0&&size<=GetBufferSize(),"AudioCircularBuffer:SetReadSize: ReadSize has to be larger than zero");
00462                         TSize previousBufferSize=GetBufferSize();
00463                         mReadSize = size;
00464                         SetBufferSize(previousBufferSize);
00465                 }
00466 
00471                 void SetWriteSize(TSize size)
00472                 {
00473                         CLAM_ASSERT(size>=0&&size<=GetBufferSize(),"AudioCircularBuffer:SetWriteSize: WriteSize has to be larger than zero");
00474                         mWriteSize = size;
00475                 }
00476         };
00477 
00478 
00479 
00480 }; //end of namespace
00481 
00482 #endif //_CircularBuffer_
00483 
Generated by  doxygen 1.6.3