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 
7 #include <sof/math/fir_config.h>
8 
9 #if FIR_HIFIEP
10 
11 #include <sof/audio/eq_fir/eq_fir.h>
12 #include <sof/audio/buffer.h>
13 #include <sof/audio/format.h>
14 #include <sof/math/fir_hifi2ep.h>
15 #include <xtensa/config/defs.h>
16 #include <xtensa/tie/xt_hifi2.h>
17 #include <errno.h>
18 #include <stddef.h>
19 #include <stdint.h>
20 
21 #if CONFIG_FORMAT_S32LE
22 /* For even frame lengths use FIR filter that processes two sequential
23  * sample per call.
24  */
eq_fir_2x_s32(struct fir_state_32x16 fir[],const struct audio_stream * source,struct audio_stream * sink,int frames,int nch)25 void eq_fir_2x_s32(struct fir_state_32x16 fir[], const struct audio_stream *source,
26 		   struct audio_stream *sink, int frames, int nch)
27 {
28 	struct fir_state_32x16 *f;
29 	int32_t *src = (int32_t *)source->r_ptr;
30 	int32_t *snk = (int32_t *)sink->w_ptr;
31 	int32_t *x0;
32 	int32_t *y0;
33 	int32_t *x1;
34 	int32_t *y1;
35 	int ch;
36 	int i;
37 	int rshift;
38 	int lshift;
39 	int inc = nch << 1;
40 
41 	for (ch = 0; ch < nch; ch++) {
42 		/* Get FIR instance and get shifts to e.g. apply mute
43 		 * without overhead.
44 		 */
45 		f = &fir[ch];
46 		fir_get_lrshifts(f, &lshift, &rshift);
47 
48 		/* Setup circular buffer for FIR input data delay */
49 		fir_hifiep_setup_circular(f);
50 
51 		x0 = src++;
52 		y0 = snk++;
53 		for (i = 0; i < (frames >> 1); i++) {
54 			x1 = x0 + nch;
55 			y1 = y0 + nch;
56 			fir_32x16_2x_hifiep(f, *x0, *x1, y0, y1,
57 					    lshift, rshift);
58 			x0 += inc;
59 			y0 += inc;
60 		}
61 	}
62 }
63 
64 /* FIR for any number of frames */
eq_fir_s32(struct fir_state_32x16 fir[],const struct audio_stream * source,struct audio_stream * sink,int frames,int nch)65 void eq_fir_s32(struct fir_state_32x16 fir[], const struct audio_stream *source,
66 		struct audio_stream *sink, int frames, int nch)
67 {
68 	struct fir_state_32x16 *f;
69 	int32_t *src = (int32_t *)source->r_ptr;
70 	int32_t *snk = (int32_t *)sink->w_ptr;
71 	int32_t *x;
72 	int32_t *y;
73 	int ch;
74 	int i;
75 	int rshift;
76 	int lshift;
77 
78 	for (ch = 0; ch < nch; ch++) {
79 		/* Get FIR instance and get shifts to e.g. apply mute
80 		 * without overhead.
81 		 */
82 		f = &fir[ch];
83 		fir_get_lrshifts(f, &lshift, &rshift);
84 
85 		/* Setup circular buffer for FIR input data delay */
86 		fir_hifiep_setup_circular(f);
87 
88 		x = src++;
89 		y = snk++;
90 		for (i = 0; i < frames; i++) {
91 			fir_32x16_hifiep(f, *x, y, lshift, rshift);
92 			x += nch;
93 			y += nch;
94 		}
95 	}
96 }
97 #endif /* CONFIG_FORMAT_S32LE */
98 
99 #if CONFIG_FORMAT_S24LE
eq_fir_2x_s24(struct fir_state_32x16 fir[],const struct audio_stream * source,struct audio_stream * sink,int frames,int nch)100 void eq_fir_2x_s24(struct fir_state_32x16 fir[], const struct audio_stream *source,
101 		   struct audio_stream *sink, int frames, int nch)
102 {
103 	struct fir_state_32x16 *f;
104 	int32_t *src = (int32_t *)source->r_ptr;
105 	int32_t *snk = (int32_t *)sink->w_ptr;
106 	int32_t *x0;
107 	int32_t *y0;
108 	int32_t *x1;
109 	int32_t *y1;
110 	int32_t z0;
111 	int32_t z1;
112 	int ch;
113 	int i;
114 	int rshift;
115 	int lshift;
116 	int inc = nch << 1;
117 
118 	for (ch = 0; ch < nch; ch++) {
119 		/* Get FIR instance and get shifts to e.g. apply mute
120 		 * without overhead.
121 		 */
122 		f = &fir[ch];
123 		fir_get_lrshifts(f, &lshift, &rshift);
124 
125 		/* Setup circular buffer for FIR input data delay */
126 		fir_hifiep_setup_circular(f);
127 
128 		x0 = src++;
129 		y0 = snk++;
130 		for (i = 0; i < (frames >> 1); i++) {
131 			x1 = x0 + nch;
132 			y1 = y0 + nch;
133 			fir_32x16_2x_hifiep(f, *x0 << 8, *x1 << 8, &z0, &z1,
134 					    lshift, rshift);
135 			*y0 = sat_int24(Q_SHIFT_RND(z0, 31, 23));
136 			*y1 = sat_int24(Q_SHIFT_RND(z1, 31, 23));
137 			x0 += inc;
138 			y0 += inc;
139 		}
140 	}
141 }
142 
143 /* FIR for any number of frames */
eq_fir_s24(struct fir_state_32x16 fir[],const struct audio_stream * source,struct audio_stream * sink,int frames,int nch)144 void eq_fir_s24(struct fir_state_32x16 fir[], const struct audio_stream *source,
145 		struct audio_stream *sink, int frames, int nch)
146 {
147 	struct fir_state_32x16 *f;
148 	int32_t *src = (int32_t *)source->r_ptr;
149 	int32_t *snk = (int32_t *)sink->w_ptr;
150 	int32_t *x;
151 	int32_t *y;
152 	int32_t z;
153 	int ch;
154 	int i;
155 	int rshift;
156 	int lshift;
157 
158 	for (ch = 0; ch < nch; ch++) {
159 		/* Get FIR instance and get shifts to e.g. apply mute
160 		 * without overhead.
161 		 */
162 		f = &fir[ch];
163 		fir_get_lrshifts(f, &lshift, &rshift);
164 
165 		/* Setup circular buffer for FIR input data delay */
166 		fir_hifiep_setup_circular(f);
167 
168 		x = src++;
169 		y = snk++;
170 		for (i = 0; i < frames; i++) {
171 			fir_32x16_hifiep(f, *x << 8, &z, lshift, rshift);
172 			*y = sat_int24(Q_SHIFT_RND(z, 31, 23));
173 			x += nch;
174 			y += nch;
175 		}
176 	}
177 }
178 #endif /* CONFIG_FORMAT_S24LE */
179 
180 #if CONFIG_FORMAT_S16LE
eq_fir_2x_s16(struct fir_state_32x16 fir[],const struct audio_stream * source,struct audio_stream * sink,int frames,int nch)181 void eq_fir_2x_s16(struct fir_state_32x16 fir[], const struct audio_stream *source,
182 		   struct audio_stream *sink, int frames, int nch)
183 {
184 	struct fir_state_32x16 *f;
185 	int16_t *src = (int16_t *)source->r_ptr;
186 	int16_t *snk = (int16_t *)sink->w_ptr;
187 	int16_t *x0;
188 	int16_t *y0;
189 	int16_t *x1;
190 	int16_t *y1;
191 	int32_t z0;
192 	int32_t z1;
193 	int ch;
194 	int i;
195 	int rshift;
196 	int lshift;
197 	int inc = nch << 1;
198 
199 	for (ch = 0; ch < nch; ch++) {
200 		/* Get FIR instance and get shifts to e.g. apply mute
201 		 * without overhead.
202 		 */
203 		f = &fir[ch];
204 		fir_get_lrshifts(f, &lshift, &rshift);
205 
206 		/* Setup circular buffer for FIR input data delay */
207 		fir_hifiep_setup_circular(f);
208 
209 		x0 = src++;
210 		y0 = snk++;
211 		for (i = 0; i < (frames >> 1); i++) {
212 			x1 = x0 + nch;
213 			y1 = y0 + nch;
214 			fir_32x16_2x_hifiep(f, *x0 << 16, *x1 << 16, &z0, &z1,
215 					    lshift, rshift);
216 			*y0 = sat_int16(Q_SHIFT_RND(z0, 31, 15));
217 			*y1 = sat_int16(Q_SHIFT_RND(z1, 31, 15));
218 			x0 += inc;
219 			y0 += inc;
220 		}
221 	}
222 }
223 
224 /* FIR for any number of frames */
eq_fir_s16(struct fir_state_32x16 fir[],const struct audio_stream * source,struct audio_stream * sink,int frames,int nch)225 void eq_fir_s16(struct fir_state_32x16 fir[], const struct audio_stream *source,
226 		struct audio_stream *sink, int frames, int nch)
227 {
228 	struct fir_state_32x16 *f;
229 	int16_t *src = (int16_t *)source->r_ptr;
230 	int16_t *snk = (int16_t *)sink->w_ptr;
231 	int16_t *x;
232 	int16_t *y;
233 	int32_t z;
234 	int ch;
235 	int i;
236 	int rshift;
237 	int lshift;
238 
239 	for (ch = 0; ch < nch; ch++) {
240 		/* Get FIR instance and get shifts to e.g. apply mute
241 		 * without overhead.
242 		 */
243 		f = &fir[ch];
244 		fir_get_lrshifts(f, &lshift, &rshift);
245 
246 		/* Setup circular buffer for FIR input data delay */
247 		fir_hifiep_setup_circular(f);
248 
249 		x = src++;
250 		y = snk++;
251 		for (i = 0; i < frames; i++) {
252 			fir_32x16_hifiep(f, *x << 16, &z, lshift, rshift);
253 			*y = sat_int16(Q_SHIFT_RND(z, 31, 15));
254 			x += nch;
255 			y += nch;
256 		}
257 	}
258 }
259 #endif /* CONFIG_FORMAT_S16LE */
260 
261 #endif /* FIR_HIFIEP */
262