HAAS Stereo Enhancer
[calf.git] / src / calf / buffer.h
blob373fbd1cd546273b23fb211fa6c8f343727975d0
1 /* Calf DSP Library
2 * Buffer abstractions.
4 * Copyright (C) 2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 #ifndef __BUFFER_H
22 #define __BUFFER_H
24 namespace dsp {
26 /// decrease by N if >= N (useful for circular buffers)
27 template<int N> inline int wrap_around(int a) {
28 return (a >= N) ? a - N : a;
31 // provide fast specializations for powers of 2
32 template<> inline int wrap_around<2>(int a) { return a & 1; }
33 template<> inline int wrap_around<4>(int a) { return a & 3; }
34 template<> inline int wrap_around<8>(int a) { return a & 7; }
35 template<> inline int wrap_around<16>(int a) { return a & 15; }
36 template<> inline int wrap_around<32>(int a) { return a & 31; }
37 template<> inline int wrap_around<64>(int a) { return a & 63; }
38 template<> inline int wrap_around<128>(int a) { return a & 127; }
39 template<> inline int wrap_around<256>(int a) { return a & 255; }
40 template<> inline int wrap_around<512>(int a) { return a & 511; }
41 template<> inline int wrap_around<1024>(int a) { return a & 1023; }
42 template<> inline int wrap_around<2048>(int a) { return a & 2047; }
43 template<> inline int wrap_around<4096>(int a) { return a & 4095; }
44 template<> inline int wrap_around<8192>(int a) { return a & 8191; }
45 template<> inline int wrap_around<16384>(int a) { return a & 16383; }
46 template<> inline int wrap_around<32768>(int a) { return a & 32767; }
47 template<> inline int wrap_around<65536>(int a) { return a & 65535; }
49 template<class Buf, class T>
50 void fill(Buf &buf, T value) {
51 T* data = buf.data();
52 int size = buf.size();
53 for (int i=0; i<size; i++)
54 *data++ = value;
57 template<class T>
58 void fill(T *data, int size, T value) {
59 for (int i=0; i<size; i++)
60 *data++ = value;
63 template<class T, class U>
64 void copy(T *dest, U *src, int size, T scale = 1, T add = 0) {
65 for (int i=0; i<size; i++)
66 *dest++ = (*src++) * scale + add;
69 template<class T>
70 struct sample_traits {
71 enum {
72 channels = 1,
73 bps = sizeof(T)*8
77 template<class T>
78 struct sample_traits<stereo_sample<T> > {
79 enum {
80 channels = 2,
81 bps = sizeof(T)*8
85 template<int N, class T = float>
86 class fixed_size_buffer {
87 public:
88 typedef T data_type;
89 enum { buffer_size = N };
90 inline int size() { return N; }
93 template<int N, class T = float>
94 class mem_fixed_size_buffer: public fixed_size_buffer<N, T> {
95 T *buf;
96 public:
97 mem_fixed_size_buffer(T ubuf[N]) { buf = ubuf; }
98 void set_data(T buf[N]) { this->buf = buf; }
99 inline T* data() { return buf; }
100 inline const T* data() const { return buf; }
101 inline T& operator[](int pos) { return buf[pos]; }
102 inline const T& operator[](int pos) const { return buf[pos]; }
105 template<int N, class T = float>
106 class auto_buffer: public fixed_size_buffer<N, T> {
107 T buf[N];
108 public:
109 T* data() const { return buf; }
110 inline T& operator[](int pos) { return buf[pos]; }
111 inline const T& operator[](int pos) const { return buf[pos]; }
114 template<class T = float>
115 class dynamic_buffer {
116 T *buf;
117 int buf_size;
118 bool owns;
119 public:
120 dynamic_buffer() { owns = false; }
121 dynamic_buffer(T *_buf, int _buf_size, bool _own)
122 : buf(_buf), buf_size(_buf_size), owns(_own) {
124 dynamic_buffer(int _size) {
125 buf = new T[_size];
126 buf_size = _size;
127 owns = true;
129 inline T* data() { return buf; }
130 inline const T* data() const { return buf; }
131 inline int size() { return buf_size; }
132 void resize(int new_size, bool fill_with_zeros = false) {
133 T *new_buf = new T[new_size];
134 memcpy(new_buf, buf, std::min(buf_size, new_size));
135 if (fill_with_zeros && buf_size < new_size)
136 dsp::zero(new_buf + buf_size, new_size - buf_size);
137 if (owns)
138 delete []buf;
139 buf = new_buf;
140 buf_size = new_size;
141 owns = true;
143 inline T& operator[](int pos) { return buf[pos]; }
144 inline const T& operator[](int pos) const { return buf[pos]; }
145 ~dynamic_buffer() {
146 if (owns)
147 delete []buf;
151 template<class T, class U>
152 void copy_buf(T &dest_buf, const U &src_buf, T scale = 1, T add = 0) {
153 typedef typename T::data_type data_type;
154 data_type *dest = dest_buf.data();
155 const data_type *src = src_buf.data();
156 int size = src.size();
157 for (int i=0; i<size; i++)
158 *dest++ = (*src++) * scale + add;
161 template<class T>
162 struct buffer_traits {
165 /// this class template defines some basic position operations for fixed_size_buffers
166 template<int N, class T>
167 struct buffer_traits<fixed_size_buffer<N, T> > {
168 int inc_wrap(int pos) const {
169 return wrap_around<T::size>(pos+1);
172 int pos_diff(int pos1, int pos2) const {
173 int pos = pos1 - pos2;
174 if (pos < 0) pos += T::size;
175 return pos;
179 /// this is useless for now (and untested too)
180 template<class B>
181 class circular_buffer: public B {
182 typedef typename B::data_type data_type;
183 typedef class buffer_traits<B> traits;
184 B buffer;
185 int rpos, wpos;
186 circular_buffer() {
187 clear();
189 void clear() {
190 rpos = 0;
191 wpos = 0;
193 inline void put(data_type data) {
194 buffer[wpos] = data;
195 wpos = traits::inc_wrap(wpos);
197 inline bool empty() {
198 return rpos == wpos;
200 inline bool full() {
201 return rpos == traits::inc_wrap(wpos);
203 inline const data_type& get() {
204 int oldrpos = rpos;
205 rpos = traits::inc_wrap(rpos);
206 return buffer[oldrpos];
208 inline int get_rbytes() {
209 return traits::pos_diff(wpos, rpos);
211 inline int get_wbytes() {
212 if (full()) return 0;
213 return traits::pos_diff(rpos, wpos);
217 /// this is useless for now
218 template<int N, class T = float>
219 class mono_auto_buffer: public auto_buffer<N, T> {
222 /// this is useless for now
223 template<int N, class T = float>
224 class stereo_auto_buffer: public auto_buffer<N, stereo_sample<T> > {
229 #endif