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,724 @@
|
|
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 <stdio.h>
|
21
|
+
#include <string.h>
|
22
|
+
#include <math.h>
|
23
|
+
#include "libpaddlec.h"
|
24
|
+
|
25
|
+
|
26
|
+
pdlc_fir_filter_t* pdlc_fir_filter_new(int order)
|
27
|
+
{
|
28
|
+
pdlc_fir_filter_t *fir;
|
29
|
+
|
30
|
+
fir = malloc(sizeof(pdlc_fir_filter_t));
|
31
|
+
|
32
|
+
fir->coefs = NULL;
|
33
|
+
fir->stater = NULL;
|
34
|
+
fir->statei = NULL;
|
35
|
+
fir->nb_coefs = 0;
|
36
|
+
fir->state_len = 0;
|
37
|
+
fir->coef_len = 0;
|
38
|
+
fir->index = 0;
|
39
|
+
fir->index_mask = 0;
|
40
|
+
fir->counter = 0;
|
41
|
+
fir->max_counter = 1;
|
42
|
+
|
43
|
+
if (order >= 0)
|
44
|
+
pdlc_fir_filter_initialize(fir, order);
|
45
|
+
|
46
|
+
return fir;
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
int pdlc_fir_filter_get_coef_at(const pdlc_fir_filter_t* fir, int index, float *value)
|
51
|
+
{
|
52
|
+
if (index < 0 || index >= (int)fir->nb_coefs)
|
53
|
+
return -1;
|
54
|
+
|
55
|
+
if (value)
|
56
|
+
*value = fir->coefs[0][fir->nb_coefs - 1 - index];
|
57
|
+
|
58
|
+
return 0;
|
59
|
+
}
|
60
|
+
|
61
|
+
|
62
|
+
void pdlc_fir_filter_reset(pdlc_fir_filter_t* fir)
|
63
|
+
{
|
64
|
+
memset(fir->stater, 0, fir->coef_len * sizeof(float));
|
65
|
+
memset(fir->statei, 0, fir->coef_len * sizeof(float));
|
66
|
+
fir->index = 0;
|
67
|
+
fir->counter = 0;
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
int pdlc_fir_filter_get_factor(const pdlc_fir_filter_t* fir)
|
72
|
+
{
|
73
|
+
return fir->max_counter;
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
void pdlc_fir_filter_interpolator_initialize(pdlc_fir_filter_t* fir, int order, int factor)
|
78
|
+
{
|
79
|
+
pdlc_fir_filter_initialize(fir, order);
|
80
|
+
|
81
|
+
if (factor < 1)
|
82
|
+
factor = 1;
|
83
|
+
if (factor > 32)
|
84
|
+
factor = 32;
|
85
|
+
|
86
|
+
fir->max_counter = factor;
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
void pdlc_fir_filter_decimator_initialize(pdlc_fir_filter_t* fir, int order, int factor)
|
91
|
+
{
|
92
|
+
pdlc_fir_filter_initialize(fir, order);
|
93
|
+
|
94
|
+
if (factor < 1)
|
95
|
+
factor = 1;
|
96
|
+
if (factor > 32)
|
97
|
+
factor = 32;
|
98
|
+
|
99
|
+
fir->max_counter = factor;
|
100
|
+
}
|
101
|
+
|
102
|
+
|
103
|
+
#if defined __AVX__
|
104
|
+
#include "fir_filter_avx.c"
|
105
|
+
#elif defined __SSE__
|
106
|
+
#include "fir_filter_sse.c"
|
107
|
+
#elif (defined __ARM_NEON) && ((__ARM_NEON_FP & 4) == 4)
|
108
|
+
#include "fir_filter_neon.c"
|
109
|
+
#else
|
110
|
+
|
111
|
+
|
112
|
+
void pdlc_fir_filter_inspect(pdlc_fir_filter_t* fir)
|
113
|
+
{
|
114
|
+
size_t i;
|
115
|
+
printf("nb_coefs: %u, state_len: %u, coef_len: %u, index_mask: %x, index: %u\n",
|
116
|
+
fir->nb_coefs, fir->state_len, fir->coef_len, fir->index_mask, fir->index);
|
117
|
+
printf("state: [%.7g", fir->stater[0]);
|
118
|
+
for (i = 1; i < fir->state_len; i++)
|
119
|
+
printf(", %.7g", fir->stater[i]);
|
120
|
+
printf("]\ncoefs: [%.7g", fir->coefs[0][0]);
|
121
|
+
for (i = 1; i < fir->coef_len; i++)
|
122
|
+
printf(", %.7g", fir->coefs[0][i]);
|
123
|
+
printf("]\n");
|
124
|
+
}
|
125
|
+
|
126
|
+
|
127
|
+
void pdlc_fir_filter_initialize(pdlc_fir_filter_t* fir, int order)
|
128
|
+
{
|
129
|
+
if (fir->coefs) {
|
130
|
+
if (fir->coefs[0])
|
131
|
+
free(fir->coefs[0]);
|
132
|
+
free(fir->coefs);
|
133
|
+
fir->coefs = NULL;
|
134
|
+
}
|
135
|
+
|
136
|
+
if (fir->stater)
|
137
|
+
free(fir->stater);
|
138
|
+
fir->stater = NULL;
|
139
|
+
|
140
|
+
if (fir->statei)
|
141
|
+
free(fir->statei);
|
142
|
+
fir->statei = NULL;
|
143
|
+
|
144
|
+
fir->nb_coefs = 0;
|
145
|
+
fir->state_len = 0;
|
146
|
+
fir->coef_len = 0;
|
147
|
+
fir->index = 0;
|
148
|
+
fir->index_mask = 0;
|
149
|
+
fir->counter = 0;
|
150
|
+
fir->max_counter = 1;
|
151
|
+
|
152
|
+
if (order < 0)
|
153
|
+
return;
|
154
|
+
|
155
|
+
if (order > 67108863) {
|
156
|
+
fprintf(stderr, "ERROR: libpaddlec: Filter order cannot be greater than 67108864\n");
|
157
|
+
exit(EXIT_FAILURE);
|
158
|
+
}
|
159
|
+
|
160
|
+
fir->nb_coefs = (unsigned int)(order + 1);
|
161
|
+
fir->state_len = (unsigned int)(pow(2.0, ceil(log2(fir->nb_coefs))));
|
162
|
+
fir->coef_len = fir->nb_coefs;
|
163
|
+
fir->index = 0;
|
164
|
+
fir->index_mask = fir->state_len - 1;
|
165
|
+
|
166
|
+
fir->coefs = malloc(1*sizeof(float*));
|
167
|
+
if (fir->coefs == NULL) {
|
168
|
+
fprintf(stderr, "ERROR: libpaddlec: Cannot allocate %lu bytes for FIR!\n", 1 * sizeof(float*));
|
169
|
+
exit(EXIT_FAILURE);
|
170
|
+
}
|
171
|
+
|
172
|
+
fir->coefs[0] = malloc(fir->coef_len * sizeof(float));
|
173
|
+
if (fir->coefs[0] == NULL) {
|
174
|
+
fprintf(stderr, "ERROR: libpaddlec: Cannot allocate %lu bytes for FIR!\n", fir->coef_len * sizeof(float));
|
175
|
+
exit(EXIT_FAILURE);
|
176
|
+
}
|
177
|
+
|
178
|
+
fir->stater = malloc(fir->state_len * sizeof(float));
|
179
|
+
if (fir->stater == NULL) {
|
180
|
+
fprintf(stderr, "ERROR: libpaddlec: Cannot allocate %lu bytes for FIR!\n", fir->state_len * sizeof(float));
|
181
|
+
exit(EXIT_FAILURE);
|
182
|
+
}
|
183
|
+
|
184
|
+
fir->statei = malloc(fir->state_len * sizeof(float));
|
185
|
+
if (fir->statei == NULL) {
|
186
|
+
fprintf(stderr, "ERROR: libpaddlec: Cannot allocate %lu bytes for FIR!\n", fir->state_len * sizeof(float));
|
187
|
+
exit(EXIT_FAILURE);
|
188
|
+
}
|
189
|
+
|
190
|
+
memset(fir->stater, 0, fir->state_len * sizeof(float));
|
191
|
+
memset(fir->statei, 0, fir->state_len * sizeof(float));
|
192
|
+
memset(fir->coefs[0], 0, fir->coef_len * sizeof(float));
|
193
|
+
}
|
194
|
+
|
195
|
+
|
196
|
+
void pdlc_fir_filter_free(pdlc_fir_filter_t* fir)
|
197
|
+
{
|
198
|
+
if (!fir)
|
199
|
+
return;
|
200
|
+
|
201
|
+
if (fir->coefs) {
|
202
|
+
if (fir->coefs[0])
|
203
|
+
free(fir->coefs[0]);
|
204
|
+
free(fir->coefs);
|
205
|
+
}
|
206
|
+
|
207
|
+
if (fir->stater)
|
208
|
+
free(fir->stater);
|
209
|
+
|
210
|
+
if (fir->statei)
|
211
|
+
free(fir->statei);
|
212
|
+
|
213
|
+
free(fir);
|
214
|
+
}
|
215
|
+
|
216
|
+
|
217
|
+
size_t pdlc_fir_filter_size(pdlc_fir_filter_t* fir)
|
218
|
+
{
|
219
|
+
size_t res;
|
220
|
+
|
221
|
+
res = sizeof(pdlc_fir_filter_t);
|
222
|
+
res += sizeof(float*);
|
223
|
+
res += sizeof(float) * fir->state_len * 2;
|
224
|
+
res += sizeof(float) * fir->coef_len * 1;
|
225
|
+
|
226
|
+
return res;
|
227
|
+
}
|
228
|
+
|
229
|
+
|
230
|
+
int pdlc_fir_filter_set_coef_at(pdlc_fir_filter_t* fir, int index, float value)
|
231
|
+
{
|
232
|
+
if (index < 0 || index >= (int)fir->nb_coefs)
|
233
|
+
return -1;
|
234
|
+
|
235
|
+
fir->coefs[0][fir->nb_coefs - 1 - index] = value;
|
236
|
+
|
237
|
+
return 0;
|
238
|
+
}
|
239
|
+
|
240
|
+
|
241
|
+
float pdlc_fir_filter_filter_float(pdlc_fir_filter_t* fir, float sample, float *delayed)
|
242
|
+
{
|
243
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
244
|
+
const unsigned int flt_len = fir->state_len;
|
245
|
+
const unsigned int mask = fir->index_mask;
|
246
|
+
const unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
247
|
+
const unsigned int middle_index = (start_index + nb_coefs / 2) & mask;
|
248
|
+
const float *coefs = fir->coefs[0];
|
249
|
+
float acc = 0.0f;
|
250
|
+
unsigned int i, j;
|
251
|
+
|
252
|
+
fir->stater[fir->index] = sample;
|
253
|
+
//pdlc_fir_filter_inspect(fir);
|
254
|
+
fir->index = (fir->index + 1) & mask;
|
255
|
+
|
256
|
+
if (delayed) {
|
257
|
+
if (nb_coefs & 1)
|
258
|
+
*delayed = fir->stater[middle_index];
|
259
|
+
else
|
260
|
+
*delayed = (fir->stater[middle_index] + fir->stater[(middle_index - 1) & mask]) / 2.0f;
|
261
|
+
}
|
262
|
+
|
263
|
+
j = start_index;
|
264
|
+
for (i = 0; i < nb_coefs; i++) {
|
265
|
+
acc += coefs[i] * fir->stater[j];
|
266
|
+
j = (j+1) & mask;
|
267
|
+
}
|
268
|
+
|
269
|
+
return acc;
|
270
|
+
}
|
271
|
+
|
272
|
+
|
273
|
+
pdlc_complex_t pdlc_fir_filter_filter_complex(pdlc_fir_filter_t* fir, pdlc_complex_t sample, pdlc_complex_t *delayed)
|
274
|
+
{
|
275
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
276
|
+
const unsigned int flt_len = fir->state_len;
|
277
|
+
const unsigned int mask = fir->index_mask;
|
278
|
+
const unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
279
|
+
const unsigned int middle_index = (start_index + nb_coefs / 2) & mask;
|
280
|
+
const float *coefs = fir->coefs[0];
|
281
|
+
pdlc_complex_t acc = {0.0f, 0.0f};
|
282
|
+
unsigned int i, j;
|
283
|
+
|
284
|
+
fir->stater[fir->index] = sample.real;
|
285
|
+
fir->statei[fir->index] = sample.imag;
|
286
|
+
fir->index = (fir->index + 1) & mask;
|
287
|
+
|
288
|
+
j = start_index;
|
289
|
+
for (i = 0; i < nb_coefs; i++) {
|
290
|
+
acc.real += coefs[i] * fir->stater[j];
|
291
|
+
acc.imag += coefs[i] * fir->statei[j];
|
292
|
+
j = (j+1) & mask;
|
293
|
+
}
|
294
|
+
|
295
|
+
if (delayed) {
|
296
|
+
if (nb_coefs & 1) {
|
297
|
+
delayed->real = fir->stater[middle_index];
|
298
|
+
delayed->imag = fir->statei[middle_index];
|
299
|
+
}
|
300
|
+
else {
|
301
|
+
delayed->real = (fir->stater[middle_index] + fir->stater[(middle_index - 1) & mask]) / 2.0f;
|
302
|
+
delayed->imag = (fir->statei[middle_index] + fir->statei[(middle_index - 1) & mask]) / 2.0f;
|
303
|
+
}
|
304
|
+
}
|
305
|
+
|
306
|
+
return acc;
|
307
|
+
}
|
308
|
+
|
309
|
+
|
310
|
+
pdlc_buffer_t* pdlc_fir_filter_filter_float_buffer(pdlc_fir_filter_t* fir, const pdlc_buffer_t *ifbuf, pdlc_buffer_t *ofbuf, pdlc_buffer_t *delayed)
|
311
|
+
{
|
312
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
313
|
+
const unsigned int flt_len = fir->state_len;
|
314
|
+
const unsigned int mask = fir->index_mask;
|
315
|
+
const float *coefs = fir->coefs[0];
|
316
|
+
unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
317
|
+
unsigned int middle_index;
|
318
|
+
float acc;
|
319
|
+
unsigned int i, j;
|
320
|
+
size_t k;
|
321
|
+
|
322
|
+
if (!ofbuf)
|
323
|
+
ofbuf = pdlc_buffer_new(ifbuf->length);
|
324
|
+
else if (ofbuf->length != ifbuf->length)
|
325
|
+
pdlc_buffer_resize(ofbuf, ifbuf->length, 0);
|
326
|
+
|
327
|
+
if (delayed) {
|
328
|
+
if (delayed->length != ifbuf->length)
|
329
|
+
pdlc_buffer_resize(delayed, ifbuf->length, 0);
|
330
|
+
middle_index = (start_index + nb_coefs / 2) & mask;
|
331
|
+
if (nb_coefs & 1) {
|
332
|
+
for (k = 0; k < ifbuf->length; k++) {
|
333
|
+
fir->stater[fir->index] = ifbuf->data[k];
|
334
|
+
fir->index = (fir->index + 1) & mask;
|
335
|
+
acc = 0.0f;
|
336
|
+
j = start_index;
|
337
|
+
for (i = 0; i < nb_coefs; i++) {
|
338
|
+
acc += coefs[i] * fir->stater[j];
|
339
|
+
j = (j+1) & mask;
|
340
|
+
}
|
341
|
+
ofbuf->data[k] = acc;
|
342
|
+
start_index = (start_index + 1) & mask;
|
343
|
+
delayed->data[k] = fir->stater[middle_index];
|
344
|
+
middle_index = (middle_index + 1) & mask;
|
345
|
+
}
|
346
|
+
}
|
347
|
+
else {
|
348
|
+
for (k = 0; k < ifbuf->length; k++) {
|
349
|
+
fir->stater[fir->index] = ifbuf->data[k];
|
350
|
+
fir->index = (fir->index + 1) & mask;
|
351
|
+
acc = 0.0f;
|
352
|
+
j = start_index;
|
353
|
+
for (i = 0; i < nb_coefs; i++) {
|
354
|
+
acc += coefs[i] * fir->stater[j];
|
355
|
+
j = (j+1) & mask;
|
356
|
+
}
|
357
|
+
ofbuf->data[k] = acc;
|
358
|
+
start_index = (start_index + 1) & mask;
|
359
|
+
delayed->data[k] = (fir->stater[middle_index] + fir->stater[(middle_index - 1) & mask]) / 2.0f;
|
360
|
+
middle_index = (middle_index + 1) & mask;
|
361
|
+
}
|
362
|
+
}
|
363
|
+
}
|
364
|
+
else {
|
365
|
+
for (k = 0; k < ifbuf->length; k++) {
|
366
|
+
fir->stater[fir->index] = ifbuf->data[k];
|
367
|
+
fir->index = (fir->index + 1) & mask;
|
368
|
+
acc = 0.0f;
|
369
|
+
j = start_index;
|
370
|
+
for (i = 0; i < nb_coefs; i++) {
|
371
|
+
acc += coefs[i] * fir->stater[j];
|
372
|
+
j = (j+1) & mask;
|
373
|
+
}
|
374
|
+
ofbuf->data[k] = acc;
|
375
|
+
start_index = (start_index + 1) & mask;
|
376
|
+
}
|
377
|
+
}
|
378
|
+
|
379
|
+
return ofbuf;
|
380
|
+
}
|
381
|
+
|
382
|
+
|
383
|
+
pdlc_complex_buffer_t* pdlc_fir_filter_filter_complex_buffer(pdlc_fir_filter_t* fir, const pdlc_complex_buffer_t *icbuf, pdlc_complex_buffer_t *ocbuf, pdlc_complex_buffer_t *delayed)
|
384
|
+
{
|
385
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
386
|
+
const unsigned int flt_len = fir->state_len;
|
387
|
+
const unsigned int mask = fir->index_mask;
|
388
|
+
const float *coefs = fir->coefs[0];
|
389
|
+
unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
390
|
+
unsigned int middle_index;
|
391
|
+
pdlc_complex_t acc;
|
392
|
+
unsigned int i, j;
|
393
|
+
size_t k;
|
394
|
+
|
395
|
+
if (!ocbuf)
|
396
|
+
ocbuf = pdlc_complex_buffer_new(icbuf->length);
|
397
|
+
else if (ocbuf->length != icbuf->length)
|
398
|
+
pdlc_complex_buffer_resize(ocbuf, icbuf->length, 0);
|
399
|
+
|
400
|
+
if (delayed) {
|
401
|
+
if (delayed->length != icbuf->length)
|
402
|
+
pdlc_complex_buffer_resize(delayed, icbuf->length, 0);
|
403
|
+
middle_index = (start_index + nb_coefs / 2) & mask;
|
404
|
+
if (nb_coefs & 1) {
|
405
|
+
for (k = 0; k < icbuf->length; k++) {
|
406
|
+
fir->stater[fir->index] = icbuf->data[k].real;
|
407
|
+
fir->statei[fir->index] = icbuf->data[k].imag;
|
408
|
+
fir->index = (fir->index + 1) & mask;
|
409
|
+
acc.real = 0.0f;
|
410
|
+
acc.imag = 0.0f;
|
411
|
+
j = start_index;
|
412
|
+
for (i = 0; i < nb_coefs; i++) {
|
413
|
+
acc.real += coefs[i] * fir->stater[j];
|
414
|
+
acc.imag += coefs[i] * fir->statei[j];
|
415
|
+
j = (j+1) & mask;
|
416
|
+
}
|
417
|
+
ocbuf->data[k] = acc;
|
418
|
+
start_index = (start_index + 1) & mask;
|
419
|
+
delayed->data[k].real = fir->stater[middle_index];
|
420
|
+
delayed->data[k].imag = fir->statei[middle_index];
|
421
|
+
middle_index = (middle_index + 1) & mask;
|
422
|
+
}
|
423
|
+
}
|
424
|
+
else {
|
425
|
+
for (k = 0; k < icbuf->length; k++) {
|
426
|
+
fir->stater[fir->index] = icbuf->data[k].real;
|
427
|
+
fir->statei[fir->index] = icbuf->data[k].imag;
|
428
|
+
fir->index = (fir->index + 1) & mask;
|
429
|
+
acc.real = 0.0f;
|
430
|
+
acc.imag = 0.0f;
|
431
|
+
j = start_index;
|
432
|
+
for (i = 0; i < nb_coefs; i++) {
|
433
|
+
acc.real += coefs[i] * fir->stater[j];
|
434
|
+
acc.imag += coefs[i] * fir->statei[j];
|
435
|
+
j = (j+1) & mask;
|
436
|
+
}
|
437
|
+
ocbuf->data[k] = acc;
|
438
|
+
start_index = (start_index + 1) & mask;
|
439
|
+
delayed->data[k].real = (fir->stater[middle_index] + fir->stater[(middle_index - 1) & mask]) / 2.0f;
|
440
|
+
delayed->data[k].imag = (fir->statei[middle_index] + fir->statei[(middle_index - 1) & mask]) / 2.0f;
|
441
|
+
middle_index = (middle_index + 1) & mask;
|
442
|
+
}
|
443
|
+
}
|
444
|
+
}
|
445
|
+
else {
|
446
|
+
for (k = 0; k < icbuf->length; k++) {
|
447
|
+
fir->stater[fir->index] = icbuf->data[k].real;
|
448
|
+
fir->statei[fir->index] = icbuf->data[k].imag;
|
449
|
+
fir->index = (fir->index + 1) & mask;
|
450
|
+
acc.real = 0.0f;
|
451
|
+
acc.imag = 0.0f;
|
452
|
+
j = start_index;
|
453
|
+
for (i = 0; i < nb_coefs; i++) {
|
454
|
+
acc.real += coefs[i] * fir->stater[j];
|
455
|
+
acc.imag += coefs[i] * fir->statei[j];
|
456
|
+
j = (j+1) & mask;
|
457
|
+
}
|
458
|
+
ocbuf->data[k] = acc;
|
459
|
+
start_index = (start_index + 1) & mask;
|
460
|
+
}
|
461
|
+
}
|
462
|
+
|
463
|
+
return ocbuf;
|
464
|
+
}
|
465
|
+
|
466
|
+
|
467
|
+
pdlc_buffer_t* pdlc_fir_filter_interpolate_float_buffer(pdlc_fir_filter_t* fir, const pdlc_buffer_t *ifbuf, pdlc_buffer_t *ofbuf)
|
468
|
+
{
|
469
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
470
|
+
const unsigned int flt_len = fir->state_len;
|
471
|
+
const unsigned int mask = fir->index_mask;
|
472
|
+
const float *coefs = fir->coefs[0];
|
473
|
+
const float ffactor = (float)(fir->max_counter);
|
474
|
+
const size_t ibuflen = ifbuf->length;
|
475
|
+
const size_t obuflen = ibuflen*fir->max_counter;
|
476
|
+
float *stater = fir->stater;
|
477
|
+
unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
478
|
+
float acc;
|
479
|
+
unsigned int i, j;
|
480
|
+
size_t k, l;
|
481
|
+
int m;
|
482
|
+
|
483
|
+
if (!ofbuf)
|
484
|
+
ofbuf = pdlc_buffer_new(obuflen);
|
485
|
+
else if (ofbuf->length != obuflen)
|
486
|
+
pdlc_buffer_resize(ofbuf, obuflen, 0);
|
487
|
+
|
488
|
+
for (k = 0, l = 0; k < ibuflen; k++) {
|
489
|
+
stater[fir->index] = ifbuf->data[k];
|
490
|
+
fir->index = (fir->index + 1) & mask;
|
491
|
+
acc = 0.0f;
|
492
|
+
j = start_index;
|
493
|
+
for (i = 0; i < nb_coefs; i++) {
|
494
|
+
acc += coefs[i] * stater[j];
|
495
|
+
j = (j+1) & mask;
|
496
|
+
}
|
497
|
+
ofbuf->data[l++] = acc * ffactor;
|
498
|
+
start_index = (start_index + 1) & mask;
|
499
|
+
|
500
|
+
for (m = 1; m < fir->max_counter; m++) {
|
501
|
+
stater[fir->index] = 0.0f;
|
502
|
+
fir->index = (fir->index + 1) & mask;
|
503
|
+
acc = 0.0f;
|
504
|
+
j = start_index;
|
505
|
+
for (i = 0; i < nb_coefs; i++) {
|
506
|
+
acc += coefs[i] * stater[j];
|
507
|
+
j = (j+1) & mask;
|
508
|
+
}
|
509
|
+
ofbuf->data[l++] = acc * ffactor;
|
510
|
+
start_index = (start_index + 1) & mask;
|
511
|
+
}
|
512
|
+
}
|
513
|
+
|
514
|
+
return ofbuf;
|
515
|
+
}
|
516
|
+
|
517
|
+
|
518
|
+
pdlc_complex_buffer_t* pdlc_fir_filter_interpolate_complex_buffer(pdlc_fir_filter_t* fir, const pdlc_complex_buffer_t *icbuf, pdlc_complex_buffer_t *ocbuf)
|
519
|
+
{
|
520
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
521
|
+
const unsigned int flt_len = fir->state_len;
|
522
|
+
const unsigned int mask = fir->index_mask;
|
523
|
+
const float *coefs = fir->coefs[0];
|
524
|
+
const float ffactor = (float)(fir->max_counter);
|
525
|
+
const size_t ibuflen = icbuf->length;
|
526
|
+
const size_t obuflen = ibuflen*fir->max_counter;
|
527
|
+
float *stater = fir->stater;
|
528
|
+
float *statei = fir->statei;
|
529
|
+
unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
530
|
+
float accr, acci;
|
531
|
+
unsigned int i, j;
|
532
|
+
size_t k, l;
|
533
|
+
int m;
|
534
|
+
|
535
|
+
if (!ocbuf)
|
536
|
+
ocbuf = pdlc_complex_buffer_new(obuflen);
|
537
|
+
else if (ocbuf->length != obuflen)
|
538
|
+
pdlc_complex_buffer_resize(ocbuf, obuflen, 0);
|
539
|
+
|
540
|
+
for (k = 0, l = 0; k < ibuflen; k++) {
|
541
|
+
stater[fir->index] = icbuf->data[k].real;
|
542
|
+
statei[fir->index] = icbuf->data[k].imag;
|
543
|
+
fir->index = (fir->index + 1) & mask;
|
544
|
+
accr = 0.0f;
|
545
|
+
acci = 0.0f;
|
546
|
+
j = start_index;
|
547
|
+
for (i = 0; i < nb_coefs; i++) {
|
548
|
+
accr += coefs[i] * stater[j];
|
549
|
+
acci += coefs[i] * statei[j];
|
550
|
+
j = (j+1) & mask;
|
551
|
+
}
|
552
|
+
ocbuf->data[l].real = accr * ffactor;
|
553
|
+
ocbuf->data[l++].imag = acci * ffactor;
|
554
|
+
start_index = (start_index + 1) & mask;
|
555
|
+
|
556
|
+
for (m = 1; m < fir->max_counter; m++) {
|
557
|
+
stater[fir->index] = 0.0f;
|
558
|
+
statei[fir->index] = 0.0f;
|
559
|
+
fir->index = (fir->index + 1) & mask;
|
560
|
+
accr = 0.0f;
|
561
|
+
acci = 0.0f;
|
562
|
+
j = start_index;
|
563
|
+
for (i = 0; i < nb_coefs; i++) {
|
564
|
+
accr += coefs[i] * stater[j];
|
565
|
+
acci += coefs[i] * statei[j];
|
566
|
+
j = (j+1) & mask;
|
567
|
+
}
|
568
|
+
ocbuf->data[l].real = accr * ffactor;
|
569
|
+
ocbuf->data[l++].imag = acci * ffactor;
|
570
|
+
start_index = (start_index + 1) & mask;
|
571
|
+
}
|
572
|
+
}
|
573
|
+
|
574
|
+
return ocbuf;
|
575
|
+
}
|
576
|
+
|
577
|
+
|
578
|
+
pdlc_buffer_t* pdlc_fir_filter_decimate_float_buffer(pdlc_fir_filter_t* fir, const pdlc_buffer_t *ifbuf, pdlc_buffer_t *ofbuf)
|
579
|
+
{
|
580
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
581
|
+
const unsigned int flt_len = fir->state_len;
|
582
|
+
const unsigned int mask = fir->index_mask;
|
583
|
+
const float *coefs = fir->coefs[0];
|
584
|
+
const size_t ibuflen = ifbuf->length;
|
585
|
+
const int mcounter = fir->max_counter;
|
586
|
+
const size_t obuflen = (size_t)ceil(((double)ibuflen - (double)((mcounter - fir->counter) % mcounter)) / (double)mcounter);
|
587
|
+
unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
588
|
+
float *stater = fir->stater;
|
589
|
+
float acc;
|
590
|
+
unsigned int i, j;
|
591
|
+
size_t k, l;
|
592
|
+
|
593
|
+
|
594
|
+
if (!ofbuf)
|
595
|
+
ofbuf = pdlc_buffer_new(obuflen);
|
596
|
+
else if (ofbuf->length != obuflen)
|
597
|
+
pdlc_buffer_resize(ofbuf, obuflen, 0);
|
598
|
+
|
599
|
+
|
600
|
+
for (k = 0, l = 0; k < ibuflen; k++) {
|
601
|
+
stater[fir->index] = ifbuf->data[k];
|
602
|
+
fir->index = (fir->index + 1) & mask;
|
603
|
+
if (fir->counter == 0) {
|
604
|
+
acc = 0.0f;
|
605
|
+
j = start_index;
|
606
|
+
for (i = 0; i < nb_coefs; i++) {
|
607
|
+
acc += coefs[i] * stater[j];
|
608
|
+
j = (j+1) & mask;
|
609
|
+
}
|
610
|
+
ofbuf->data[l++] = acc;
|
611
|
+
}
|
612
|
+
start_index = (start_index + 1) & mask;
|
613
|
+
fir->counter = (fir->counter + 1) % mcounter;
|
614
|
+
}
|
615
|
+
|
616
|
+
return ofbuf;
|
617
|
+
}
|
618
|
+
|
619
|
+
|
620
|
+
pdlc_complex_buffer_t* pdlc_fir_filter_decimate_complex_buffer(pdlc_fir_filter_t* fir, const pdlc_complex_buffer_t *icbuf, pdlc_complex_buffer_t *ocbuf)
|
621
|
+
{
|
622
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
623
|
+
const unsigned int flt_len = fir->state_len;
|
624
|
+
const unsigned int mask = fir->index_mask;
|
625
|
+
const float *coefs = fir->coefs[0];
|
626
|
+
const size_t ibuflen = icbuf->length;
|
627
|
+
const int mcounter = fir->max_counter;
|
628
|
+
const size_t obuflen = (size_t)ceil(((double)ibuflen - (double)((mcounter - fir->counter) % mcounter)) / (double)mcounter);
|
629
|
+
unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
630
|
+
float *stater = fir->stater;
|
631
|
+
float *statei = fir->statei;
|
632
|
+
float accr, acci;
|
633
|
+
unsigned int i, j;
|
634
|
+
size_t k, l;
|
635
|
+
|
636
|
+
|
637
|
+
if (!ocbuf)
|
638
|
+
ocbuf = pdlc_complex_buffer_new(obuflen);
|
639
|
+
else if (ocbuf->length != obuflen)
|
640
|
+
pdlc_complex_buffer_resize(ocbuf, obuflen, 0);
|
641
|
+
|
642
|
+
|
643
|
+
for (k = 0, l = 0; k < ibuflen; k++) {
|
644
|
+
stater[fir->index] = icbuf->data[k].real;
|
645
|
+
statei[fir->index] = icbuf->data[k].imag;
|
646
|
+
fir->index = (fir->index + 1) & mask;
|
647
|
+
if (fir->counter == 0) {
|
648
|
+
accr = 0.0f;
|
649
|
+
acci = 0.0f;
|
650
|
+
j = start_index;
|
651
|
+
for (i = 0; i < nb_coefs; i++) {
|
652
|
+
accr += coefs[i] * stater[j];
|
653
|
+
acci += coefs[i] * statei[j];
|
654
|
+
j = (j+1) & mask;
|
655
|
+
}
|
656
|
+
ocbuf->data[l].real = accr;
|
657
|
+
ocbuf->data[l].imag = acci;
|
658
|
+
l++;
|
659
|
+
}
|
660
|
+
start_index = (start_index + 1) & mask;
|
661
|
+
fir->counter = (fir->counter + 1) % mcounter;
|
662
|
+
}
|
663
|
+
|
664
|
+
return ocbuf;
|
665
|
+
}
|
666
|
+
|
667
|
+
|
668
|
+
pdlc_complex_buffer_t* pdlc_fir_filter_transform(pdlc_fir_filter_t* fir, const pdlc_buffer_t *ifbuf, pdlc_complex_buffer_t *ocbuf)
|
669
|
+
{
|
670
|
+
const unsigned int nb_coefs = fir->nb_coefs;
|
671
|
+
const unsigned int flt_len = fir->state_len;
|
672
|
+
const unsigned int mask = fir->index_mask;
|
673
|
+
const float *coefs = fir->coefs[0];
|
674
|
+
unsigned int start_index = (flt_len + fir->index + 1 - nb_coefs) & mask;
|
675
|
+
unsigned int middle_index = (start_index + nb_coefs / 2) & mask;
|
676
|
+
float acc;
|
677
|
+
unsigned int i, j;
|
678
|
+
size_t k;
|
679
|
+
|
680
|
+
if (!ocbuf)
|
681
|
+
ocbuf = pdlc_complex_buffer_new(ifbuf->length);
|
682
|
+
else if (ocbuf->length != ifbuf->length)
|
683
|
+
pdlc_complex_buffer_resize(ocbuf, ifbuf->length, 0);
|
684
|
+
|
685
|
+
|
686
|
+
if (nb_coefs & 1) {
|
687
|
+
for (k = 0; k < ifbuf->length; k++) {
|
688
|
+
fir->stater[fir->index] = ifbuf->data[k];
|
689
|
+
fir->index = (fir->index + 1) & mask;
|
690
|
+
acc = 0.0f;
|
691
|
+
j = start_index;
|
692
|
+
for (i = 0; i < nb_coefs; i++) {
|
693
|
+
acc += coefs[i] * fir->stater[j];
|
694
|
+
j = (j+1) & mask;
|
695
|
+
}
|
696
|
+
ocbuf->data[k].imag = acc;
|
697
|
+
ocbuf->data[k].real = fir->stater[middle_index];
|
698
|
+
start_index = (start_index + 1) & mask;
|
699
|
+
middle_index = (middle_index + 1) & mask;
|
700
|
+
}
|
701
|
+
}
|
702
|
+
else {
|
703
|
+
for (k = 0; k < ifbuf->length; k++) {
|
704
|
+
fir->stater[fir->index] = ifbuf->data[k];
|
705
|
+
fir->index = (fir->index + 1) & mask;
|
706
|
+
acc = 0.0f;
|
707
|
+
j = start_index;
|
708
|
+
for (i = 0; i < nb_coefs; i++) {
|
709
|
+
acc += coefs[i] * fir->stater[j];
|
710
|
+
j = (j+1) & mask;
|
711
|
+
}
|
712
|
+
ocbuf->data[k].imag = acc;
|
713
|
+
ocbuf->data[k].real = (fir->stater[middle_index] + fir->stater[(middle_index - 1) & mask]) / 2.0f;
|
714
|
+
start_index = (start_index + 1) & mask;
|
715
|
+
middle_index = (middle_index + 1) & mask;
|
716
|
+
}
|
717
|
+
}
|
718
|
+
|
719
|
+
return ocbuf;
|
720
|
+
}
|
721
|
+
|
722
|
+
|
723
|
+
#endif
|
724
|
+
|