-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcircular_buffer.h
More file actions
144 lines (124 loc) · 2.96 KB
/
circular_buffer.h
File metadata and controls
144 lines (124 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Circular buffer implementation adapted from https://github.com/acids-ircam/nn_tilde
#pragma once
#include <memory>
#include <algorithm>
template <class T> class circular_buffer {
public:
circular_buffer();
void initialize(size_t size);
bool empty();
bool full();
void put(const T *input_array, int N);
void put(const T& value);
void put_repeat(const T& value, int N);
void get(T *output_array, int N);
void reset();
size_t size();
void shave(const size_t new_size);
bool freezing = false;
protected:
std::unique_ptr<T[]> _buffer;
size_t _max_size;
unsigned int _head = 0;
unsigned int _tail = 0;
bool _full = false;
};
template <class T>
circular_buffer<T>::circular_buffer() {}
template <class T>
void circular_buffer<T>::initialize(size_t size) {
_buffer = std::make_unique<T[]>(size);
// last element of _buffer might be accessed if freezing is on
_buffer[size - 1] = T();
_max_size = size;
}
template <class T>
bool circular_buffer<T>::empty() {
return (!_full && _head == _tail);
}
template <class T>
bool circular_buffer<T>::full() {
return _full;
}
template <class T>
void circular_buffer<T>::put(const T *input_array, int N) {
if (!_max_size)
return;
while (N--) {
_buffer[_head] = *(input_array++);
_head = (_head + 1) % _max_size;
if (_full)
_tail = (_tail + 1) % _max_size;
_full = _head == _tail;
}
}
template <class T>
inline void circular_buffer<T>::put(const T &value)
{
if (!_max_size)
return;
_buffer[_head] = value;
_head = (_head + 1) % _max_size;
if (_full)
_tail = (_tail + 1) % _max_size;
_full = _head == _tail;
}
template <class T>
void circular_buffer<T>::put_repeat(const T& value, int N) {
if (!_max_size)
return;
while (N--) {
_buffer[_head] = value; // Assign the same value repeatedly
_head = (_head + 1) % _max_size;
if (_full)
_tail = (_tail + 1) % _max_size;
_full = _head == _tail;
}
}
template <class T>
void circular_buffer<T>::get(T *output_array, int N) {
if (!_max_size)
return;
while (N--) {
if (empty()) {
if (freezing)
{
size_t lastTail = (_tail == 0) ? _max_size - 1 : _tail - 1;
*(output_array++) = _buffer[lastTail];
}
else
{
*(output_array++) = T();
}
} else {
*(output_array++) = _buffer[_tail];
_tail = (_tail + 1) % _max_size;
_full = false;
}
}
}
template <class T>
void circular_buffer<T>::reset() {
_head = _tail;
_full = false;
}
// Number of elements the currently holds
template <class T>
size_t circular_buffer<T>::size() {
if (_full) {
return _max_size;
} else if (_head >= _tail) {
return _head - _tail;
} else {
return _max_size - _tail + _head;
}
}
// Retain new_size most recent by discarding stale elements
template <class T>
void circular_buffer<T>::shave(const size_t new_size)
{
while (size() > new_size) {
_tail = (_tail + 1) % _max_size;
_full = false;
}
}