1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2017 Intel Corporation. All rights reserved.
4 //
5 // Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
6 // Liam Girdwood <liam.r.girdwood@linux.intel.com>
7 // Keyon Jie <yang.jie@linux.intel.com>
8
9 #include <sof/math/fir_config.h>
10
11 #if FIR_GENERIC
12
13 #include <sof/common.h>
14 #include <sof/audio/buffer.h>
15 #include <sof/audio/format.h>
16 #include <sof/math/fir_generic.h>
17 #include <user/fir.h>
18 #include <errno.h>
19 #include <stddef.h>
20 #include <stdint.h>
21
22 /*
23 * EQ FIR algorithm code
24 */
25
fir_reset(struct fir_state_32x16 * fir)26 void fir_reset(struct fir_state_32x16 *fir)
27 {
28 fir->rwi = 0;
29 fir->length = 0;
30 fir->out_shift = 0;
31 fir->coef = NULL;
32 /* There may need to know the beginning of dynamic allocation after
33 * reset so omitting setting also fir->delay to NULL.
34 */
35 }
36
fir_delay_size(struct sof_fir_coef_data * config)37 int fir_delay_size(struct sof_fir_coef_data *config)
38 {
39 /* Check for sane FIR length. The generic version does not
40 * have other constraints.
41 */
42 if (config->length > SOF_FIR_MAX_LENGTH || config->length < 1)
43 return -EINVAL;
44
45 return config->length * sizeof(int32_t);
46 }
47
fir_init_coef(struct fir_state_32x16 * fir,struct sof_fir_coef_data * config)48 int fir_init_coef(struct fir_state_32x16 *fir,
49 struct sof_fir_coef_data *config)
50 {
51 fir->rwi = 0;
52 fir->length = (int)config->length;
53 fir->taps = fir->length; /* The same for generic C version */
54 fir->out_shift = (int)config->out_shift;
55 fir->coef = ASSUME_ALIGNED(&config->coef[0], 4);
56 return 0;
57 }
58
fir_init_delay(struct fir_state_32x16 * fir,int32_t ** data)59 void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data)
60 {
61 fir->delay = *data;
62 *data += fir->length; /* Point to next delay line start */
63 }
64
fir_32x16(struct fir_state_32x16 * fir,int32_t x)65 int32_t fir_32x16(struct fir_state_32x16 *fir, int32_t x)
66 {
67 int64_t y = 0;
68 int32_t *data = &fir->delay[fir->rwi];
69 int16_t *coef = &fir->coef[0];
70 int n1;
71 int n2;
72 int n;
73
74 /* Bypass is set with length set to zero. */
75 if (!fir->length)
76 return x;
77
78 /* Write sample to delay */
79 *data = x;
80
81 /* Advance write pointer and calculate into n1 max. number of taps
82 * to process before circular wrap.
83 */
84 n1 = ++fir->rwi;
85 if (fir->rwi == fir->length)
86 fir->rwi = 0;
87
88 /* Check if no need to un-wrap FIR data. */
89 if (n1 > fir->length) {
90 /* Data is Q1.31, coef is Q1.15, product is Q2.46 */
91 for (n = 0; n < fir->length; n++) {
92 y += (int64_t)(*coef) * (*data);
93 coef++;
94 data--;
95 }
96
97 /* Q2.46 -> Q2.31, saturate to Q1.31 */
98 return sat_int32(y >> (15 + fir->out_shift));
99 }
100
101 /* Part 1, loop n1 times */
102 for (n = 0; n < n1; n++) {
103 y += (int64_t)(*coef) * (*data);
104 coef++;
105 data--;
106 }
107
108 /* Part 2, un-wrap data, continue n2 times */
109 n2 = fir->length - n1;
110 data = &fir->delay[fir->length - 1];
111 for (n = 0; n < n2; n++) {
112 y += (int64_t)(*coef) * (*data);
113 coef++;
114 data--;
115 }
116
117 /* Q2.46 -> Q2.31, saturate to Q1.31 */
118 return sat_int32(y >> (15 + fir->out_shift));
119 }
120
121 #endif
122