88#define FLOW_ASSERT (x, y )
99#endif
1010
11- template <typename T >
11+ template <typename DataType, typename IndexType = size_t >
1212class CircularBuffer {
1313protected:
14- T* data;
15- size_t size;
16- size_t writepos = 0 ;
17- size_t readpos = 0 ;
14+ DataType* data;
15+ IndexType size;
16+ IndexType writepos = 0 ;
17+ IndexType readpos = 0 ;
18+ bool empty = true ;
1819public:
1920 CircularBuffer (): data(NULL ), size(0 ){}
20- CircularBuffer (T * data, size_t size): data(data), size(size){}
21+ CircularBuffer (DataType * data, IndexType size): data(data), size(size){}
2122
22- void setData (T * data, size_t len) {
23+ void setData (DataType * data, IndexType len) {
2324 this ->data = data;
2425 size = len;
2526 }
2627
27- size_t getSize () const {
28+ IndexType getSize () const {
2829 return size;
2930 }
3031
31- T * getData () {
32+ DataType * getData () {
3233 return data;
3334 }
3435
3536 bool isEmpty () const {
36- return writepos == readpos;
37+ return empty;
38+ }
39+
40+ bool isFull () const {
41+ return (writepos == readpos) && !empty;
3742 }
3843
39- void write (T c){
44+ void write (DataType c){
45+ FLOW_ASSERT (getWriteCapacity () > 0 , " overflow" );
4046 data[writepos++] = c;
4147 if (writepos >= size)
4248 writepos = 0 ;
49+ empty = false ;
4350 }
4451
45- void write (T * source, size_t len){
52+ void write (DataType * source, IndexType len){
4653 FLOW_ASSERT (getWriteCapacity () >= len, " overflow" );
47- T * dest = getWriteHead ();
48- size_t rem = size-writepos;
49- if (len > rem){
50- memcpy (dest, source, rem*sizeof (T ));
54+ DataType * dest = getWriteHead ();
55+ IndexType rem = size-writepos;
56+ if (len >= rem){
57+ memcpy (dest, source, rem*sizeof (DataType ));
5158 writepos = len-rem;
52- memcpy (data, source+rem, writepos*sizeof (T ));
59+ memcpy (data, source+rem, writepos*sizeof (DataType ));
5360 }else {
54- memcpy (dest, source, len*sizeof (T ));
61+ memcpy (dest, source, len*sizeof (DataType ));
5562 writepos += len;
5663 }
64+ empty = false ;
5765 }
5866
59- void writeAt (size_t index, T value){
67+ void writeAt (IndexType index, DataType value){
6068 data[index % size] = value;
6169 }
6270
63- void overdub (T c){
71+ void overdub (DataType c){
6472 data[writepos++] += c;
6573 if (writepos >= size)
6674 writepos = 0 ;
75+ empty = false ;
6776 }
6877
69- void overdubAt (size_t index, T value){
78+ void overdubAt (IndexType index, DataType value){
7079 data[index % size] += value;
7180 }
7281
73- T read (){
74- T c = data[readpos++];
82+ DataType read (){
83+ FLOW_ASSERT (getReadCapacity () > 0 , " underflow" );
84+ DataType c = data[readpos++];
7585 if (readpos >= size)
7686 readpos = 0 ;
87+ empty = readpos == writepos;
7788 return c;
7889 }
7990
80- void read (T * dst, size_t len){
91+ void read (DataType * dst, IndexType len){
8192 FLOW_ASSERT (getReadCapacity () >= len, " underflow" );
82- T * src = getReadHead ();
83- size_t rem = size-readpos;
93+ DataType * src = getReadHead ();
94+ IndexType rem = size-readpos;
8495 if (len > rem){
85- memcpy (dst, src, rem*sizeof (T ));
96+ memcpy (dst, src, rem*sizeof (DataType ));
8697 readpos = len-rem;
87- memcpy (dst+rem, data, readpos*sizeof (T ));
98+ memcpy (dst+rem, data, readpos*sizeof (DataType ));
8899 }else {
89- memcpy (dst, src, len*sizeof (T ));
100+ memcpy (dst, src, len*sizeof (DataType ));
90101 readpos += len;
91102 }
103+ empty = readpos == writepos;
92104 }
93105
94- T readAt (size_t index){
106+ DataType readAt (IndexType index){
95107 return data[index % size];
96108 }
97109
98110 void skipUntilLast (char c){
99- T * src = getReadHead ();
100- size_t rem = size-readpos;
111+ DataType * src = getReadHead ();
112+ IndexType rem = size-readpos;
101113 for (int i=0 ; i<rem; ++i){
102114 if (src[i] != c){
103115 readpos += i;
@@ -111,40 +123,43 @@ class CircularBuffer {
111123 return ;
112124 }
113125 }
126+ empty = readpos == writepos;
114127 }
115128
116- size_t getWriteIndex (){
129+ IndexType getWriteIndex (){
117130 return writepos;
118131 }
119132
120- void setWriteIndex (size_t pos){
133+ void setWriteIndex (IndexType pos){
121134 writepos = pos % size;
122135 }
123136
124- T * getWriteHead (){
137+ DataType * getWriteHead (){
125138 return data+writepos;
126139 }
127140
128141 void moveWriteHead (int32_t samples){
129142 FLOW_ASSERT (getWriteCapacity () >= samples, " overflow" );
130143 writepos = (writepos + samples) % size;
144+ empty = false ;
131145 }
132146
133- size_t getReadIndex (){
147+ IndexType getReadIndex (){
134148 return readpos;
135149 }
136150
137- void setReadIndex (size_t pos){
151+ void setReadIndex (IndexType pos){
138152 readpos = pos % size;
139153 }
140154
141- T * getReadHead (){
155+ DataType * getReadHead (){
142156 return data+readpos;
143157 }
144158
145159 void moveReadHead (int32_t samples){
146160 FLOW_ASSERT (getReadCapacity () < samples, " underflow" );
147161 readpos = (readpos + samples) % size;
162+ empty = readpos == writepos;
148163 }
149164
150165 /* *
@@ -157,61 +172,62 @@ class CircularBuffer {
157172 /* *
158173 * Get the read index expressed as delay behind the write index.
159174 */
160- int getDelay (){
175+ IndexType getDelay () const {
161176 return (writepos-readpos+size) % size;
162177 }
163178
164179 /* *
165180 * Write to buffer and read with a delay
166181 */
167- void delay (T * in, T * out, size_t len, int delay_samples){
182+ void delay (DataType * in, DataType * out, IndexType len, int delay_samples){
168183 setDelay (delay_samples); // set delay relative to where we start writing
169184 write (in, len);
170185 read (out, len);
171186 }
172187
173- size_t getReadCapacity (){
174- return (writepos + size - readpos) % size ;
188+ IndexType getReadCapacity () const {
189+ return size - getWriteCapacity () ;
175190 }
176191
177- size_t getWriteCapacity (){
178- return size - getReadCapacity () ;
192+ IndexType getWriteCapacity () const {
193+ return size*empty + (readpos + size - writepos) % size ;
179194 }
180195
181- size_t getContiguousWriteCapacity (){
196+ IndexType getContiguousWriteCapacity () const {
182197 if (writepos < readpos)
183198 return readpos - writepos;
184199 else
185200 return size - writepos;
186201 }
187202
188- size_t getContiguousReadCapacity (){
203+ IndexType getContiguousReadCapacity () const {
189204 if (writepos < readpos)
190205 return size - readpos;
191206 else
192207 return writepos - readpos;
193208 }
194209
195- void setAll (const T value){
196- for (size_t i=0 ; i<size; ++i)
210+ void setAll (const DataType value){
211+ for (IndexType i=0 ; i<size; ++i)
197212 data[i] = value;
198213 }
199214
200215 void reset (){
201216 readpos = writepos = 0 ;
217+ empty = true ;
202218 }
203219
204220 void clear (){
205221 setAll (0 );
206222 }
207223
208- static CircularBuffer<T >* create (size_t len){
209- CircularBuffer<T >* obj = new CircularBuffer<T >(new T [len], len);
224+ static CircularBuffer<DataType >* create (IndexType len){
225+ CircularBuffer<DataType >* obj = new CircularBuffer<DataType >(new DataType [len], len);
210226 obj->clear ();
211227 return obj;
212228 }
213229
214- static void destroy (CircularBuffer<T >* obj){
230+ static void destroy (CircularBuffer<DataType >* obj){
215231 delete[] obj->data ;
216232 delete obj;
217233 }
0 commit comments