CLAM-Development
1.4.0
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
src
Standard
CircularBuffer.hxx
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3
* UNIVERSITAT POMPEU FABRA
4
*
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*
20
*/
21
22
#ifndef _CircularBuffer_
23
#define _CircularBuffer_
24
25
#include "
Array.hxx
"
26
#include "
DataTypes.hxx
"
27
#include "
Err.hxx
"
28
29
namespace
CLAM
30
{
31
32
46
template
<
class
T>
class
CircularBuffer
47
{
48
protected
:
49
Array<T>
mBuffer
;
50
TSize
mLogicalSize
;
51
TSize
mReadSize
;
52
TSize
mWriteSize
;
53
TSize
mWriteIndex
;
// XXX: might want these mutable and read-like methods declared const
54
TSize
mReadIndex
;
// XXX: might want these mutable and read-like methods declared const
55
TSize
mInitialReadOffset
;
56
TSize
mInitialWriteOffset
;
57
58
public
:
59
66
CircularBuffer
() :
mBuffer
()
67
{
68
mWriteIndex
= 0;
69
mReadIndex
= 0;
70
mReadSize
=
mWriteSize
= 1;
71
mInitialReadOffset
= 0;
72
mInitialWriteOffset
= 0;
73
SetBufferSize
(0);
74
mLogicalSize
= 0;
75
}
76
82
CircularBuffer
(
TSize
bufferSize) :
mBuffer
(bufferSize)
83
{
84
CLAM_ASSERT
(bufferSize > 0,
"CircularBuffer:CircularBuffer: BufferSize has to be larger than zero"
);
85
SetBufferSize
(bufferSize);
86
mWriteIndex
= 0;
87
mReadIndex
= 0;
88
mReadSize
=
mWriteSize
= 1;
89
mInitialReadOffset
= 0;
90
mInitialWriteOffset
= 0;
91
mLogicalSize
= 0;
92
}
93
94
// Methods for setting up the buffer: -------------------------------------------
95
99
TSize
GetBufferSize
()
const
100
{
101
return
mBuffer
.Size()-
GetReadSize
();
102
}
103
109
void
SetBufferSize
(
TSize
size)
110
{
111
mBuffer
.Resize(size+
GetReadSize
());
112
mBuffer
.SetSize(size+
GetReadSize
());
113
InitPointers
();
114
}
115
120
TSize
GetWriteIndex
()
const
121
{
122
return
mWriteIndex
;
123
}
124
129
TSize
GetReadIndex
()
const
130
{
131
return
mReadIndex
;
132
}
133
139
TSize
GetInitialReadOffset
()
const
140
{
141
return
mInitialReadOffset
;
142
}
143
150
void
SetInitialReadOffset
(
TSize
size)
151
{
152
CLAM_ASSERT
((size >= 0)&&(size <
GetBufferSize
()-1),
153
"CircularBuffer:SetInitialReadOffset: InitialReadOffset has to be larger than zero"
);
154
mInitialReadOffset
= size;
155
}
156
162
TSize
GetInitialWriteOffset
()
const
163
{
164
return
mInitialWriteOffset
;
165
}
166
173
void
SetInitialWriteOffset
(
TSize
size)
174
{
175
CLAM_ASSERT
((size >= 0)&&(size <
GetBufferSize
()-1),
176
"CircularBuffer:SetInitialWriteOffset: InitialWriteOffset has to be larger than zero"
);
177
mInitialWriteOffset
= size;
178
}
179
180
// Methods for data acces: ------------------------------------------------------
181
187
void
Init
()
188
{
189
SetBufferToZero
();
190
InitPointers
();
191
}
192
196
void
SetBufferToZero
()
197
{
198
T *pBuffer;
199
pBuffer =
mBuffer
.GetPtr();
200
memset(pBuffer, 0,
GetBufferSize
()*
sizeof
(T));
201
}
202
207
void
InitPointers
()
208
{
209
if
(
mInitialReadOffset
< 0)
210
mReadIndex
=
GetBufferSize
() +
mInitialReadOffset
;
211
else
212
mReadIndex
=
mInitialReadOffset
;
213
if
(
mInitialWriteOffset
< 0)
214
mWriteIndex
=
GetBufferSize
() +
mInitialWriteOffset
;
215
else
216
mWriteIndex
=
mInitialWriteOffset
;
217
mLogicalSize
=0;
218
}
219
220
// Methods for reading and writing: ---------------------------------------------
221
226
void
Read
(T& element)
227
{
228
element =
mBuffer
[
mReadIndex
];
229
IncreaseReadIndex
();
230
}
231
232
233
void
NonCopyRead
(
Array<T>
& buffer)
234
{
235
TSize
limit;
236
if
((limit=
mReadIndex
+
mReadSize
)>
GetBufferSize
())
237
{
238
//will have to use phantom zone
239
memcpy(
mBuffer
.GetPtr()+
GetBufferSize
(),
mBuffer
.GetPtr(),
mReadSize
*
sizeof
(T));
240
}
241
buffer.
SetPtr
(
mBuffer
.GetPtr()+
mReadIndex
,
mReadSize
);
242
IncreaseReadIndex
(
mReadSize
);
243
244
245
}
246
253
void
Read
(T* buffer)
254
{
255
TSize
limit;
256
if
((limit=
mReadIndex
+
mReadSize
)>
GetBufferSize
())
257
{
258
TSize
secondHalf=limit%
GetBufferSize
();
259
TSize
firstHalf=
mReadSize
-secondHalf;
260
memcpy(buffer,
mBuffer
.GetPtr()+
mReadIndex
,firstHalf*
sizeof
(T));
261
memcpy(buffer+firstHalf,
mBuffer
.GetPtr(),secondHalf*
sizeof
(T));
262
}
263
else
264
{
265
memcpy(buffer,
mBuffer
.GetPtr()+
mReadIndex
,
mReadSize
*
sizeof
(T));
266
}
267
268
IncreaseReadIndex
(
mReadSize
);
269
}
270
280
void
Read
(
Array<T>
& in,
TSize
offset = 0)
// XXX: maybe call in, out instead?
281
{
282
CLAM_ASSERT
(
GetReadSize
() <= in.
Size
()+offset,
"Error, input buffer is not large enough"
);
// XXX: maybe call the input buffer the output buffer?
283
284
#ifdef CLAM_HIGH_OPTIMIZATIONS
285
Read
(in.
GetPtr
()+offset);
286
#else
287
for
(
int
i=0;i<
mReadSize
;i++)
288
Read
(in[i+offset]);
289
#endif
290
}
291
295
void
Write
(
const
T& element)
296
{
297
mBuffer
[
mWriteIndex
] = element;
298
IncreaseWriteIndex
();
299
}
300
306
void
Write
(
const
T* buffer)
307
{
308
TSize
limit;
309
if
((limit=
mWriteIndex
+
mWriteSize
)>
GetBufferSize
())
310
{
311
TSize
secondHalf=limit%
GetBufferSize
();
312
TSize
firstHalf=
mWriteSize
-secondHalf;
313
memcpy(
mBuffer
.GetPtr()+
mWriteIndex
,buffer,firstHalf*
sizeof
(T));
314
memcpy(
mBuffer
.GetPtr(),buffer+firstHalf,secondHalf*
sizeof
(T));
315
}
316
else
317
{
318
memcpy(
mBuffer
.GetPtr()+
mWriteIndex
,buffer,
mWriteSize
*
sizeof
(T));
319
}
320
321
IncreaseWriteIndex
(
mWriteSize
);
322
}
323
331
void
Write
(
const
Array<T>
& in,
TSize
offset = 0)
332
{
333
CLAM_ASSERT
(
GetWriteSize
()<=in.
Size
()+offset,
"Error, input buffer is not large enough"
);
334
#ifdef CLAM_HIGH_OPTIMIZATIONS
335
Write
(in.
GetPtr
()+offset);
336
#else
337
for
(
int
i=0;i<
mWriteSize
;i++)
338
Write
(in[i+offset]);
339
#endif
340
}
341
347
void
Add
(
const
T& elem)
348
{
349
mBuffer
[
mWriteIndex
] += elem;
350
IncreaseWriteIndex
();
351
}
352
360
void
Add
(
const
Array<T>
& in,
TSize
offset = 0)
361
{
362
CLAM_ASSERT
(
GetWriteSize
()<=in.
Size
()+offset,
"Error, input buffer is not large enough"
);
363
for
(
int
i=0;i<
mWriteSize
;i++)
364
Add
(in[i+offset]);
365
// XXX: might also want a CLAM_HIGH_OPTIMIZATIONS version of this method...
366
}
367
372
void
IncreaseReadIndex
(
TSize
step = 1)
373
{
374
mReadIndex
+= step;
375
mReadIndex
=
mReadIndex
%
GetBufferSize
();
376
mLogicalSize
-=step;
377
CLAM_ASSERT
(
mLogicalSize
>=0,
"Error:Read Index surpassed Write Index"
);
378
}
379
384
void
IncreaseWriteIndex
(
TSize
step = 1)
385
{
386
// XXX: might want to assert that step > 0
387
mWriteIndex
+= step;
388
mWriteIndex
=
mWriteIndex
%
GetBufferSize
();
389
mLogicalSize
+=step;
390
CLAM_ASSERT
(
mLogicalSize
<=
GetBufferSize
(),
"Error:Write Index surpassed Read Index"
);
391
}
392
397
void
DecreaseReadIndex
(
TSize
step = 1)
398
{
399
// XXX: might want to assert that step > 0
400
mReadIndex
-= step;
401
mReadIndex
=
mReadIndex
%
GetBufferSize
();
402
if
(
mReadIndex
<0)
mReadIndex
=
GetBufferSize
()+
mReadIndex
;
403
mLogicalSize
+=step;
404
CLAM_ASSERT
(
mLogicalSize
<=
GetBufferSize
(),
"Error:Write Index surpassed Read Index"
);
405
}
406
411
void
DecreaseWriteIndex
(
TSize
step = 1)
412
{
413
// XXX: might want to assert that step > 0
414
mWriteIndex
-= step;
415
mWriteIndex
=
mWriteIndex
%
GetBufferSize
();
416
if
(
mWriteIndex
<0)
mWriteIndex
=
GetBufferSize
()+
mWriteIndex
;
417
mLogicalSize
-=step;
418
CLAM_ASSERT
(
mLogicalSize
>=0,
"Error:Read Index surpassed Write Index"
);
419
}
420
426
T&
GetPtrToElement
(
int
absPos)
427
{
428
int
index = absPos%
GetBufferSize
();
// XXX: unnecessary copy.
429
430
return
mBuffer
[index];
431
}
432
433
// Getters and setters: ---------------------------------------------------------
434
440
TSize
GetReadSize
()
const
441
{
442
return
mReadSize
;
443
}
444
450
TSize
GetWriteSize
()
const
451
{
452
return
mWriteSize
;
453
}
454
459
void
SetReadSize
(
TSize
size)
460
{
461
CLAM_ASSERT
(size>=0&&size<=
GetBufferSize
(),
"AudioCircularBuffer:SetReadSize: ReadSize has to be larger than zero"
);
462
TSize
previousBufferSize=
GetBufferSize
();
463
mReadSize
= size;
464
SetBufferSize
(previousBufferSize);
465
}
466
471
void
SetWriteSize
(
TSize
size)
472
{
473
CLAM_ASSERT
(size>=0&&size<=
GetBufferSize
(),
"AudioCircularBuffer:SetWriteSize: WriteSize has to be larger than zero"
);
474
mWriteSize
= size;
475
}
476
};
477
478
479
480
};
//end of namespace
481
482
#endif //_CircularBuffer_
483
Generated by
1.8.1