paddlec 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +56 -0
- data/ext/libpaddlec/arithmetic.c +2486 -0
- data/ext/libpaddlec/comparison.c +683 -0
- data/ext/libpaddlec/complex.c +349 -0
- data/ext/libpaddlec/delay.c +240 -0
- data/ext/libpaddlec/fir_filter.c +724 -0
- data/ext/libpaddlec/fir_filter_avx.c +2645 -0
- data/ext/libpaddlec/fir_filter_neon.c +1767 -0
- data/ext/libpaddlec/fir_filter_sse.c +1677 -0
- data/ext/libpaddlec/libpaddlec.c +933 -0
- data/ext/libpaddlec/libpaddlec.h +473 -0
- data/ext/libpaddlec/math.c +563 -0
- data/ext/libpaddlec/no_fast_math.c +955 -0
- data/ext/libpaddlec/rounding.c +503 -0
- data/ext/paddlec/complex_buffer.c +3555 -0
- data/ext/paddlec/complex_buffer.h +28 -0
- data/ext/paddlec/delay.c +214 -0
- data/ext/paddlec/delay.h +29 -0
- data/ext/paddlec/extconf.rb +106 -0
- data/ext/paddlec/fir_filter.c +892 -0
- data/ext/paddlec/fir_filter.h +28 -0
- data/ext/paddlec/float_buffer.c +4770 -0
- data/ext/paddlec/float_buffer.h +28 -0
- data/ext/paddlec/paddlec.c +788 -0
- data/ext/paddlec/paddlec.h +76 -0
- data/ext/paddlec/pulseaudio.c +6767 -0
- data/ext/paddlec/pulseaudio.h +30 -0
- data/lib/paddlec.rb +26 -0
- data/lib/paddlec/version.rb +3 -0
- data/paddlec.gemspec +55 -0
- data/samples/fmdemod.rb +121 -0
- data/samples/fmdemod_chunk.rb +120 -0
- data/samples/fmdemod_chunk_buffer.rb +144 -0
- data/samples/stereo_chunk.rb +161 -0
- metadata +99 -0
@@ -0,0 +1,349 @@
|
|
1
|
+
/* Copyright (C) 2019 Théotime Bollengier <theotime.bollengier@gmail.com>
|
2
|
+
*
|
3
|
+
* This file is part of PaddleC
|
4
|
+
*
|
5
|
+
* PaddleC is free software: you can redistribute it and/or modify
|
6
|
+
* it under the terms of the GNU General Public License as published by
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or
|
8
|
+
* (at your option) any later version.
|
9
|
+
*
|
10
|
+
* PaddleC is distributed in the hope that it will be useful,
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
* GNU General Public License for more details.
|
14
|
+
*
|
15
|
+
* You should have received a copy of the GNU General Public License
|
16
|
+
* along with PaddleC. If not, see <https://www.gnu.org/licenses/>.
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include <stdlib.h>
|
20
|
+
#include <math.h>
|
21
|
+
#include "libpaddlec.h"
|
22
|
+
|
23
|
+
|
24
|
+
pdlc_buffer_t* pdlc_buffer_abs(const pdlc_buffer_t *fbuf, pdlc_buffer_t *ofbuf)
|
25
|
+
{
|
26
|
+
size_t i;
|
27
|
+
|
28
|
+
if (!ofbuf)
|
29
|
+
ofbuf = pdlc_buffer_new(fbuf->length);
|
30
|
+
else
|
31
|
+
pdlc_buffer_resize(ofbuf, fbuf->length, 0);
|
32
|
+
|
33
|
+
for (i = 0; i < fbuf->length; i++)
|
34
|
+
ofbuf->data[i] = fabsf(fbuf->data[i]);
|
35
|
+
|
36
|
+
return ofbuf;
|
37
|
+
}
|
38
|
+
|
39
|
+
|
40
|
+
pdlc_buffer_t* pdlc_buffer_abs_inplace(pdlc_buffer_t *fbuf)
|
41
|
+
{
|
42
|
+
size_t i;
|
43
|
+
|
44
|
+
for (i = 0; i < fbuf->length; i++)
|
45
|
+
fbuf->data[i] = fabsf(fbuf->data[i]);
|
46
|
+
|
47
|
+
return fbuf;
|
48
|
+
}
|
49
|
+
|
50
|
+
|
51
|
+
pdlc_buffer_t* pdlc_complex_buffer_abs(const pdlc_complex_buffer_t *cbuf, pdlc_buffer_t *ofbuf)
|
52
|
+
{
|
53
|
+
size_t i;
|
54
|
+
|
55
|
+
if (!ofbuf)
|
56
|
+
ofbuf = pdlc_buffer_new(cbuf->length);
|
57
|
+
else
|
58
|
+
pdlc_buffer_resize(ofbuf, cbuf->length, 0);
|
59
|
+
|
60
|
+
for (i = 0; i < cbuf->length; i++)
|
61
|
+
ofbuf->data[i] = hypotf(cbuf->data[i].real, cbuf->data[i].imag);
|
62
|
+
|
63
|
+
return ofbuf;
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
pdlc_buffer_t* pdlc_buffer_abs2(const pdlc_buffer_t *fbuf, pdlc_buffer_t *ofbuf)
|
68
|
+
{
|
69
|
+
size_t i;
|
70
|
+
|
71
|
+
if (!ofbuf)
|
72
|
+
ofbuf = pdlc_buffer_new(fbuf->length);
|
73
|
+
else
|
74
|
+
pdlc_buffer_resize(ofbuf, fbuf->length, 0);
|
75
|
+
|
76
|
+
for (i = 0; i < fbuf->length; i++)
|
77
|
+
ofbuf->data[i] = fbuf->data[i] * fbuf->data[i];
|
78
|
+
|
79
|
+
return ofbuf;
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
pdlc_buffer_t* pdlc_buffer_abs2_inplace(pdlc_buffer_t *fbuf)
|
84
|
+
{
|
85
|
+
size_t i;
|
86
|
+
|
87
|
+
for (i = 0; i < fbuf->length; i++)
|
88
|
+
fbuf->data[i] = fbuf->data[i] * fbuf->data[i];
|
89
|
+
|
90
|
+
return fbuf;
|
91
|
+
}
|
92
|
+
|
93
|
+
|
94
|
+
pdlc_buffer_t* pdlc_complex_buffer_abs2(const pdlc_complex_buffer_t *cbuf, pdlc_buffer_t *ofbuf)
|
95
|
+
{
|
96
|
+
size_t i;
|
97
|
+
|
98
|
+
if (!ofbuf)
|
99
|
+
ofbuf = pdlc_buffer_new(cbuf->length);
|
100
|
+
else
|
101
|
+
pdlc_buffer_resize(ofbuf, cbuf->length, 0);
|
102
|
+
|
103
|
+
for (i = 0; i < cbuf->length; i++)
|
104
|
+
ofbuf->data[i] = cbuf->data[i].real * cbuf->data[i].real + cbuf->data[i].imag * cbuf->data[i].imag;
|
105
|
+
|
106
|
+
return ofbuf;
|
107
|
+
}
|
108
|
+
|
109
|
+
|
110
|
+
pdlc_buffer_t* pdlc_buffer_arg(const pdlc_buffer_t *fbuf, pdlc_buffer_t *ofbuf)
|
111
|
+
{
|
112
|
+
size_t i;
|
113
|
+
|
114
|
+
if (!ofbuf)
|
115
|
+
ofbuf = pdlc_buffer_new(fbuf->length);
|
116
|
+
else
|
117
|
+
pdlc_buffer_resize(ofbuf, fbuf->length, 0);
|
118
|
+
|
119
|
+
for (i = 0; i < fbuf->length; i++)
|
120
|
+
ofbuf->data[i] = (fbuf->data[i] < 0.0f) ? (float)M_PI : 0.0f;
|
121
|
+
|
122
|
+
return ofbuf;
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
pdlc_buffer_t* pdlc_buffer_arg_inplace(pdlc_buffer_t *fbuf)
|
127
|
+
{
|
128
|
+
size_t i;
|
129
|
+
|
130
|
+
for (i = 0; i < fbuf->length; i++)
|
131
|
+
fbuf->data[i] = (fbuf->data[i] < 0.0f) ? (float)M_PI : 0.0f;
|
132
|
+
|
133
|
+
return fbuf;
|
134
|
+
}
|
135
|
+
|
136
|
+
|
137
|
+
pdlc_buffer_t* pdlc_complex_buffer_arg(const pdlc_complex_buffer_t *cbuf, pdlc_buffer_t *ofbuf)
|
138
|
+
{
|
139
|
+
size_t i;
|
140
|
+
|
141
|
+
if (!ofbuf)
|
142
|
+
ofbuf = pdlc_buffer_new(cbuf->length);
|
143
|
+
else
|
144
|
+
pdlc_buffer_resize(ofbuf, cbuf->length, 0);
|
145
|
+
|
146
|
+
for (i = 0; i < cbuf->length; i++)
|
147
|
+
ofbuf->data[i] = atan2f(cbuf->data[i].imag, cbuf->data[i].real);
|
148
|
+
|
149
|
+
return ofbuf;
|
150
|
+
}
|
151
|
+
|
152
|
+
|
153
|
+
pdlc_buffer_t* pdlc_buffer_conjugate(const pdlc_buffer_t *fbuf, pdlc_buffer_t *ofbuf)
|
154
|
+
{
|
155
|
+
size_t i;
|
156
|
+
|
157
|
+
if (!ofbuf)
|
158
|
+
ofbuf = pdlc_buffer_new(fbuf->length);
|
159
|
+
else
|
160
|
+
pdlc_buffer_resize(ofbuf, fbuf->length, 0);
|
161
|
+
|
162
|
+
for (i = 0; i < fbuf->length; i++)
|
163
|
+
ofbuf->data[i] = fbuf->data[i];
|
164
|
+
|
165
|
+
return ofbuf;
|
166
|
+
}
|
167
|
+
|
168
|
+
|
169
|
+
pdlc_buffer_t* pdlc_buffer_conjugate_inplace(pdlc_buffer_t *fbuf)
|
170
|
+
{
|
171
|
+
size_t i;
|
172
|
+
|
173
|
+
for (i = 0; i < fbuf->length; i++)
|
174
|
+
fbuf->data[i] = fbuf->data[i];
|
175
|
+
|
176
|
+
return fbuf;
|
177
|
+
}
|
178
|
+
|
179
|
+
|
180
|
+
pdlc_complex_buffer_t* pdlc_complex_buffer_conjugate(const pdlc_complex_buffer_t *cbuf, pdlc_complex_buffer_t *ocbuf)
|
181
|
+
{
|
182
|
+
size_t i;
|
183
|
+
|
184
|
+
if (!ocbuf)
|
185
|
+
ocbuf = pdlc_complex_buffer_new(cbuf->length);
|
186
|
+
else
|
187
|
+
pdlc_complex_buffer_resize(ocbuf, cbuf->length, 0);
|
188
|
+
|
189
|
+
for (i = 0; i < cbuf->length; i++) {
|
190
|
+
ocbuf->data[i].real = cbuf->data[i].real;
|
191
|
+
ocbuf->data[i].imag = -cbuf->data[i].imag;
|
192
|
+
}
|
193
|
+
|
194
|
+
return ocbuf;
|
195
|
+
}
|
196
|
+
|
197
|
+
|
198
|
+
pdlc_complex_buffer_t* pdlc_complex_buffer_conjugate_inplace(pdlc_complex_buffer_t *cbuf)
|
199
|
+
{
|
200
|
+
size_t i;
|
201
|
+
|
202
|
+
for (i = 0; i < cbuf->length; i++) {
|
203
|
+
cbuf->data[i].real = cbuf->data[i].real;
|
204
|
+
cbuf->data[i].imag = -cbuf->data[i].imag;
|
205
|
+
}
|
206
|
+
|
207
|
+
return cbuf;
|
208
|
+
}
|
209
|
+
|
210
|
+
|
211
|
+
pdlc_buffer_t* pdlc_buffer_imag(const pdlc_buffer_t *fbuf, pdlc_buffer_t *ofbuf)
|
212
|
+
{
|
213
|
+
size_t i;
|
214
|
+
|
215
|
+
if (!ofbuf)
|
216
|
+
ofbuf = pdlc_buffer_new(fbuf->length);
|
217
|
+
else
|
218
|
+
pdlc_buffer_resize(ofbuf, fbuf->length, 0);
|
219
|
+
|
220
|
+
for (i = 0; i < fbuf->length; i++)
|
221
|
+
ofbuf->data[i] = 0.0f;
|
222
|
+
|
223
|
+
return ofbuf;
|
224
|
+
}
|
225
|
+
|
226
|
+
|
227
|
+
pdlc_buffer_t* pdlc_buffer_imag_inplace(pdlc_buffer_t *fbuf)
|
228
|
+
{
|
229
|
+
size_t i;
|
230
|
+
|
231
|
+
for (i = 0; i < fbuf->length; i++)
|
232
|
+
fbuf->data[i] = 0.0f;
|
233
|
+
|
234
|
+
return fbuf;
|
235
|
+
}
|
236
|
+
|
237
|
+
|
238
|
+
pdlc_buffer_t* pdlc_complex_buffer_imag(const pdlc_complex_buffer_t *cbuf, pdlc_buffer_t *ofbuf)
|
239
|
+
{
|
240
|
+
size_t i;
|
241
|
+
|
242
|
+
if (!ofbuf)
|
243
|
+
ofbuf = pdlc_buffer_new(cbuf->length);
|
244
|
+
else
|
245
|
+
pdlc_buffer_resize(ofbuf, cbuf->length, 0);
|
246
|
+
|
247
|
+
for (i = 0; i < cbuf->length; i++)
|
248
|
+
ofbuf->data[i] = cbuf->data[i].imag;
|
249
|
+
|
250
|
+
return ofbuf;
|
251
|
+
}
|
252
|
+
|
253
|
+
|
254
|
+
pdlc_buffer_t* pdlc_buffer_real(const pdlc_buffer_t *fbuf, pdlc_buffer_t *ofbuf)
|
255
|
+
{
|
256
|
+
size_t i;
|
257
|
+
|
258
|
+
if (!ofbuf)
|
259
|
+
ofbuf = pdlc_buffer_new(fbuf->length);
|
260
|
+
else
|
261
|
+
pdlc_buffer_resize(ofbuf, fbuf->length, 0);
|
262
|
+
|
263
|
+
for (i = 0; i < fbuf->length; i++)
|
264
|
+
ofbuf->data[i] = fbuf->data[i];
|
265
|
+
|
266
|
+
return ofbuf;
|
267
|
+
}
|
268
|
+
|
269
|
+
|
270
|
+
pdlc_buffer_t* pdlc_buffer_real_inplace(pdlc_buffer_t *fbuf)
|
271
|
+
{
|
272
|
+
size_t i;
|
273
|
+
|
274
|
+
for (i = 0; i < fbuf->length; i++)
|
275
|
+
fbuf->data[i] = fbuf->data[i];
|
276
|
+
|
277
|
+
return fbuf;
|
278
|
+
}
|
279
|
+
|
280
|
+
|
281
|
+
pdlc_buffer_t* pdlc_complex_buffer_real(const pdlc_complex_buffer_t *cbuf, pdlc_buffer_t *ofbuf)
|
282
|
+
{
|
283
|
+
size_t i;
|
284
|
+
|
285
|
+
if (!ofbuf)
|
286
|
+
ofbuf = pdlc_buffer_new(cbuf->length);
|
287
|
+
else
|
288
|
+
pdlc_buffer_resize(ofbuf, cbuf->length, 0);
|
289
|
+
|
290
|
+
for (i = 0; i < cbuf->length; i++)
|
291
|
+
ofbuf->data[i] = cbuf->data[i].real;
|
292
|
+
|
293
|
+
return ofbuf;
|
294
|
+
}
|
295
|
+
|
296
|
+
|
297
|
+
pdlc_complex_buffer_t* pdlc_buffer_swapIQ(const pdlc_buffer_t *fbuf, pdlc_complex_buffer_t *ocbuf)
|
298
|
+
{
|
299
|
+
size_t i;
|
300
|
+
|
301
|
+
if (!ocbuf)
|
302
|
+
ocbuf = pdlc_complex_buffer_new(fbuf->length);
|
303
|
+
else
|
304
|
+
pdlc_complex_buffer_resize(ocbuf, fbuf->length, 0);
|
305
|
+
|
306
|
+
for (i = 0; i < fbuf->length; i++) {
|
307
|
+
ocbuf->data[i].real = 0.0f;
|
308
|
+
ocbuf->data[i].imag = fbuf->data[i];
|
309
|
+
}
|
310
|
+
|
311
|
+
return ocbuf;
|
312
|
+
}
|
313
|
+
|
314
|
+
|
315
|
+
pdlc_complex_buffer_t* pdlc_complex_buffer_swapIQ(const pdlc_complex_buffer_t *cbuf, pdlc_complex_buffer_t *ocbuf)
|
316
|
+
{
|
317
|
+
size_t i;
|
318
|
+
pdlc_complex_t tmp;
|
319
|
+
|
320
|
+
if (!ocbuf)
|
321
|
+
ocbuf = pdlc_complex_buffer_new(cbuf->length);
|
322
|
+
else
|
323
|
+
pdlc_complex_buffer_resize(ocbuf, cbuf->length, 0);
|
324
|
+
|
325
|
+
for (i = 0; i < cbuf->length; i++) {
|
326
|
+
tmp.real = cbuf->data[i].imag;
|
327
|
+
tmp.imag = cbuf->data[i].real;
|
328
|
+
ocbuf->data[i] = tmp;
|
329
|
+
}
|
330
|
+
|
331
|
+
return ocbuf;
|
332
|
+
}
|
333
|
+
|
334
|
+
|
335
|
+
pdlc_complex_buffer_t* pdlc_complex_buffer_swapIQ_inplace(pdlc_complex_buffer_t *cbuf)
|
336
|
+
{
|
337
|
+
size_t i;
|
338
|
+
pdlc_complex_t tmp;
|
339
|
+
|
340
|
+
for (i = 0; i < cbuf->length; i++) {
|
341
|
+
tmp.real = cbuf->data[i].imag;
|
342
|
+
tmp.imag = cbuf->data[i].real;
|
343
|
+
cbuf->data[i] = tmp;
|
344
|
+
}
|
345
|
+
|
346
|
+
return cbuf;
|
347
|
+
}
|
348
|
+
|
349
|
+
|
@@ -0,0 +1,240 @@
|
|
1
|
+
/* Copyright (C) 2020 Théotime Bollengier <theotime.bollengier@gmail.com>
|
2
|
+
*
|
3
|
+
* This file is part of PaddleC
|
4
|
+
*
|
5
|
+
* PaddleC is free software: you can redistribute it and/or modify
|
6
|
+
* it under the terms of the GNU General Public License as published by
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or
|
8
|
+
* (at your option) any later version.
|
9
|
+
*
|
10
|
+
* PaddleC is distributed in the hope that it will be useful,
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
* GNU General Public License for more details.
|
14
|
+
*
|
15
|
+
* You should have received a copy of the GNU General Public License
|
16
|
+
* along with PaddleC. If not, see <https://www.gnu.org/licenses/>.
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include <stdlib.h>
|
20
|
+
#include <stdio.h>
|
21
|
+
#include <string.h>
|
22
|
+
#include <math.h>
|
23
|
+
#include "libpaddlec.h"
|
24
|
+
|
25
|
+
|
26
|
+
pdlc_delay_t* pdlc_delay_new(int delay)
|
27
|
+
{
|
28
|
+
pdlc_delay_t *del;
|
29
|
+
|
30
|
+
del = malloc(sizeof(pdlc_delay_t));
|
31
|
+
del->delay = 0;
|
32
|
+
del->index_mask = 0;
|
33
|
+
del->index = 0;
|
34
|
+
del->data = NULL;
|
35
|
+
|
36
|
+
if (delay > 0)
|
37
|
+
pdlc_delay_initialize(del, delay);
|
38
|
+
|
39
|
+
return del;
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
void pdlc_delay_initialize(pdlc_delay_t* del, int delay)
|
44
|
+
{
|
45
|
+
unsigned int length;
|
46
|
+
|
47
|
+
if (del->data)
|
48
|
+
free(del->data);
|
49
|
+
|
50
|
+
del->delay = 0;
|
51
|
+
del->index_mask = 0;
|
52
|
+
del->index = 0;
|
53
|
+
del->data = NULL;
|
54
|
+
|
55
|
+
if (delay <= 0)
|
56
|
+
return;
|
57
|
+
|
58
|
+
if (delay > 134217728) {
|
59
|
+
fprintf(stderr, "ERROR: libpaddlec: Delay cannot be greater than 134217728\n");
|
60
|
+
exit(EXIT_FAILURE);
|
61
|
+
}
|
62
|
+
|
63
|
+
del->delay = (unsigned int)delay;
|
64
|
+
length = (unsigned int)(pow(2.0, ceil(log2(del->delay))));
|
65
|
+
del->index_mask = length - 1;
|
66
|
+
|
67
|
+
del->data = malloc(length*sizeof(pdlc_complex_t));
|
68
|
+
if (del->data == NULL) {
|
69
|
+
fprintf(stderr, "ERROR: libpaddlec: Cannot allocate %lu bytes for the delay!\n", length * sizeof(pdlc_complex_t));
|
70
|
+
exit(EXIT_FAILURE);
|
71
|
+
}
|
72
|
+
|
73
|
+
memset(del->data, 0, length*sizeof(pdlc_complex_t));
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
void pdlc_delay_free(pdlc_delay_t* del)
|
78
|
+
{
|
79
|
+
if (del->data)
|
80
|
+
free(del->data);
|
81
|
+
}
|
82
|
+
|
83
|
+
|
84
|
+
size_t pdlc_delay_size(const pdlc_delay_t* del)
|
85
|
+
{
|
86
|
+
return sizeof(pdlc_delay_t) + (del->index_mask + 1)*sizeof(pdlc_complex_t);
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
void pdlc_delay_reset(pdlc_delay_t* del)
|
91
|
+
{
|
92
|
+
memset(del->data, 0, (del->index_mask + 1)*sizeof(pdlc_complex_t));
|
93
|
+
del->index = 0;
|
94
|
+
}
|
95
|
+
|
96
|
+
|
97
|
+
float pdlc_delay_delay_float(pdlc_delay_t* del, float value)
|
98
|
+
{
|
99
|
+
const unsigned int mask = del->index_mask;
|
100
|
+
const unsigned int start_index = (mask + del->index + 1 - del->delay) & mask;
|
101
|
+
float *ptr = (float*)del->data;
|
102
|
+
float res;
|
103
|
+
|
104
|
+
res = ptr[start_index];
|
105
|
+
ptr[del->index] = value;
|
106
|
+
del->index = (del->index + 1) & mask;
|
107
|
+
|
108
|
+
return res;
|
109
|
+
}
|
110
|
+
|
111
|
+
|
112
|
+
pdlc_complex_t pdlc_delay_delay_complex(pdlc_delay_t* del, pdlc_complex_t value)
|
113
|
+
{
|
114
|
+
const unsigned int mask = del->index_mask;
|
115
|
+
const unsigned int start_index = (mask + del->index + 1 - del->delay) & mask;
|
116
|
+
pdlc_complex_t *ptr = del->data;
|
117
|
+
pdlc_complex_t res;
|
118
|
+
|
119
|
+
res = ptr[start_index];
|
120
|
+
ptr[del->index] = value;
|
121
|
+
del->index = (del->index + 1) & mask;
|
122
|
+
|
123
|
+
return res;
|
124
|
+
}
|
125
|
+
|
126
|
+
|
127
|
+
pdlc_buffer_t* pdlc_delay_delay_float_buffer(pdlc_delay_t* del, const pdlc_buffer_t *ifbuf, pdlc_buffer_t *ofbuf)
|
128
|
+
{
|
129
|
+
const unsigned int mask = del->index_mask;
|
130
|
+
const unsigned int length = mask + 1;
|
131
|
+
const unsigned int delay = del->delay;
|
132
|
+
const unsigned int start_index = (length + del->index - delay) & mask;
|
133
|
+
float *ptr = (float*)del->data;
|
134
|
+
unsigned int len, tocopy, dests = 0, srcs = 0;
|
135
|
+
|
136
|
+
if (!ofbuf)
|
137
|
+
ofbuf = pdlc_buffer_new(ifbuf->length);
|
138
|
+
else if (ofbuf->length != ifbuf->length)
|
139
|
+
pdlc_buffer_resize(ofbuf, ifbuf->length, 0);
|
140
|
+
|
141
|
+
/* Delay line to output buffer */
|
142
|
+
len = delay;
|
143
|
+
if (ifbuf->length < len)
|
144
|
+
len = ifbuf->length;
|
145
|
+
tocopy = len;
|
146
|
+
if ((start_index + tocopy) > length) {
|
147
|
+
tocopy = length - start_index;
|
148
|
+
memcpy(ofbuf->data + dests, ptr + start_index, tocopy*sizeof(float));
|
149
|
+
dests += tocopy;
|
150
|
+
tocopy = len - tocopy;
|
151
|
+
memcpy(ofbuf->data + dests, ptr, tocopy*sizeof(float));
|
152
|
+
}
|
153
|
+
else
|
154
|
+
memcpy(ofbuf->data + dests, ptr + start_index, tocopy*sizeof(float));
|
155
|
+
dests += tocopy;
|
156
|
+
|
157
|
+
if (ifbuf->length >= delay)
|
158
|
+
del->index = 0;
|
159
|
+
|
160
|
+
/* Input buffer to output buffer */
|
161
|
+
if (ifbuf->length > delay) {
|
162
|
+
tocopy = ifbuf->length - len;
|
163
|
+
memcpy(ofbuf->data + dests, ifbuf->data, tocopy*sizeof(float));
|
164
|
+
srcs = tocopy;
|
165
|
+
}
|
166
|
+
|
167
|
+
/* Input buffer to delay line */
|
168
|
+
tocopy = len;
|
169
|
+
if ((del->index + tocopy) > length) {
|
170
|
+
tocopy = length - del->index;
|
171
|
+
memcpy(ptr + del->index, ifbuf->data + srcs, tocopy*sizeof(float));
|
172
|
+
srcs += tocopy;
|
173
|
+
tocopy = len - tocopy;
|
174
|
+
memcpy(ptr, ifbuf->data + srcs, tocopy*sizeof(float));
|
175
|
+
}
|
176
|
+
else
|
177
|
+
memcpy(ptr + del->index, ifbuf->data + srcs, tocopy*sizeof(float));
|
178
|
+
del->index = (del->index + len) & mask;
|
179
|
+
|
180
|
+
return ofbuf;
|
181
|
+
}
|
182
|
+
|
183
|
+
|
184
|
+
pdlc_complex_buffer_t* pdlc_delay_delay_complex_buffer(pdlc_delay_t* del, const pdlc_complex_buffer_t *icbuf, pdlc_complex_buffer_t *ocbuf)
|
185
|
+
{
|
186
|
+
const unsigned int mask = del->index_mask;
|
187
|
+
const unsigned int length = mask + 1;
|
188
|
+
const unsigned int delay = del->delay;
|
189
|
+
const unsigned int start_index = (length + del->index - delay) & mask;
|
190
|
+
pdlc_complex_t *ptr = del->data;
|
191
|
+
unsigned int len, tocopy, dests = 0, srcs = 0;
|
192
|
+
|
193
|
+
if (!ocbuf)
|
194
|
+
ocbuf = pdlc_complex_buffer_new(icbuf->length);
|
195
|
+
else if (ocbuf->length != icbuf->length)
|
196
|
+
pdlc_complex_buffer_resize(ocbuf, icbuf->length, 0);
|
197
|
+
|
198
|
+
/* Delay line to output buffer */
|
199
|
+
len = delay;
|
200
|
+
if (icbuf->length < len)
|
201
|
+
len = icbuf->length;
|
202
|
+
tocopy = len;
|
203
|
+
if ((start_index + tocopy) > length) {
|
204
|
+
tocopy = length - start_index;
|
205
|
+
memcpy(ocbuf->data + dests, ptr + start_index, tocopy*sizeof(pdlc_complex_t));
|
206
|
+
dests += tocopy;
|
207
|
+
tocopy = len - tocopy;
|
208
|
+
memcpy(ocbuf->data + dests, ptr, tocopy*sizeof(pdlc_complex_t));
|
209
|
+
}
|
210
|
+
else
|
211
|
+
memcpy(ocbuf->data + dests, ptr + start_index, tocopy*sizeof(pdlc_complex_t));
|
212
|
+
dests += tocopy;
|
213
|
+
|
214
|
+
if (icbuf->length >= delay)
|
215
|
+
del->index = 0;
|
216
|
+
|
217
|
+
/* Input buffer to output buffer */
|
218
|
+
if (icbuf->length > delay) {
|
219
|
+
tocopy = icbuf->length - len;
|
220
|
+
memcpy(ocbuf->data + dests, icbuf->data, tocopy*sizeof(pdlc_complex_t));
|
221
|
+
srcs = tocopy;
|
222
|
+
}
|
223
|
+
|
224
|
+
/* Input buffer to delay line */
|
225
|
+
tocopy = len;
|
226
|
+
if ((del->index + tocopy) > length) {
|
227
|
+
tocopy = length - del->index;
|
228
|
+
memcpy(ptr + del->index, icbuf->data + srcs, tocopy*sizeof(pdlc_complex_t));
|
229
|
+
srcs += tocopy;
|
230
|
+
tocopy = len - tocopy;
|
231
|
+
memcpy(ptr, icbuf->data + srcs, tocopy*sizeof(pdlc_complex_t));
|
232
|
+
}
|
233
|
+
else
|
234
|
+
memcpy(ptr + del->index, icbuf->data + srcs, tocopy*sizeof(pdlc_complex_t));
|
235
|
+
del->index = (del->index + len) & mask;
|
236
|
+
|
237
|
+
return ocbuf;
|
238
|
+
}
|
239
|
+
|
240
|
+
|