Skip to content

Commit 57f1861

Browse files
committed
EQ FIR: HiFi3 optimized version
Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 32e4902 commit 57f1861

2 files changed

Lines changed: 440 additions & 0 deletions

File tree

src/audio/fir_hifi3.c

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
* Copyright (c) 2017, Intel Corporation
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the Intel Corporation nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*
28+
* Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
29+
*/
30+
31+
#include <stdint.h>
32+
#include <stddef.h>
33+
#include <errno.h>
34+
#include <sof/audio/component.h>
35+
#include <sof/audio/format.h>
36+
#include <uapi/eq.h>
37+
#include "fir_config.h"
38+
39+
#if FIR_HIFI3
40+
41+
#include <xtensa/config/defs.h>
42+
#include <xtensa/tie/xt_hifi3.h>
43+
#include "fir_hifi3.h"
44+
45+
/*
46+
* EQ FIR algorithm code
47+
*/
48+
49+
void fir_reset(struct fir_state_32x16 *fir)
50+
{
51+
fir->mute = 1;
52+
fir->length = 0;
53+
fir->out_shift = 0;
54+
fir->rwp = NULL;
55+
fir->delay = NULL;
56+
fir->delay_end = NULL;
57+
fir->coef = NULL;
58+
/* There may need to know the beginning of dynamic allocation after
59+
* reset so omitting setting also fir->delay to NULL.
60+
*/
61+
}
62+
63+
int fir_init_coef(struct fir_state_32x16 *fir, int16_t config[])
64+
{
65+
struct sof_eq_fir_coef_data *setup;
66+
67+
/* The length is taps plus two since the filter computes two
68+
* samples per call. Length plus one would be minimum but the add
69+
* must be even. The even length is needed for 64 bit loads from delay
70+
* lines with 32 bit samples.
71+
*/
72+
setup = (struct sof_eq_fir_coef_data *)config;
73+
fir->mute = 0;
74+
fir->rwp = NULL;
75+
fir->taps = (int)setup->length;
76+
fir->length = fir->taps + 2;
77+
fir->out_shift = (int)setup->out_shift;
78+
fir->coef = (ae_f16x4 *)&setup->coef[0];
79+
fir->delay = NULL;
80+
fir->delay_end = NULL;
81+
82+
/* Check FIR tap count for implementation specific constraints */
83+
if (fir->taps > SOF_EQ_FIR_MAX_LENGTH || fir->taps < 4)
84+
return -EINVAL;
85+
86+
if (fir->taps & 3)
87+
return -EINVAL;
88+
89+
return fir->length;
90+
}
91+
92+
void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data)
93+
{
94+
fir->delay = (ae_int32 *) *data;
95+
fir->delay_end = fir->delay + fir->length;
96+
fir->rwp = (ae_int32 *)(fir->delay + fir->length - 1);
97+
*data += fir->length; /* Point to next delay line start */
98+
}
99+
100+
void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift,
101+
int *rshift)
102+
{
103+
if (fir->mute) {
104+
*lshift = 0;
105+
*rshift = 31;
106+
} else {
107+
*lshift = (fir->out_shift < 0) ? -fir->out_shift : 0;
108+
*rshift = (fir->out_shift > 0) ? fir->out_shift : 0;
109+
}
110+
}
111+
112+
/* For even frame lengths use FIR filter that processes two sequential
113+
* sample per call.
114+
*/
115+
void eq_fir_2x_s32_hifi3(struct fir_state_32x16 fir[],
116+
struct comp_buffer *source, struct comp_buffer *sink,
117+
int frames, int nch)
118+
{
119+
struct fir_state_32x16 *f;
120+
int32_t *src = (int32_t *)source->r_ptr;
121+
int32_t *snk = (int32_t *)sink->w_ptr;
122+
int32_t *x0;
123+
int32_t *y0;
124+
int32_t *x1;
125+
int32_t *y1;
126+
int ch;
127+
int i;
128+
int rshift;
129+
int lshift;
130+
int shift;
131+
int inc = nch << 1;
132+
133+
for (ch = 0; ch < nch; ch++) {
134+
/* Get FIR instance and get shifts to e.g. apply mute
135+
* without overhead.
136+
*/
137+
f = &fir[ch];
138+
fir_get_lrshifts(f, &lshift, &rshift);
139+
shift = lshift - rshift;
140+
141+
/* Setup circular buffer for FIR input data delay */
142+
fir_hifi3_setup_circular(f);
143+
144+
x0 = src++;
145+
y0 = snk++;
146+
for (i = 0; i < (frames >> 1); i++) {
147+
x1 = x0 + nch;
148+
y1 = y0 + nch;
149+
fir_32x16_2x_hifi3(f, x0, x1, y0, y1, shift);
150+
x0 += inc;
151+
y0 += inc;
152+
}
153+
}
154+
}
155+
156+
/* FIR for any number of frames */
157+
void eq_fir_s32_hifi3(struct fir_state_32x16 fir[], struct comp_buffer *source,
158+
struct comp_buffer *sink, int frames, int nch)
159+
{
160+
struct fir_state_32x16 *f;
161+
int32_t *src = (int32_t *)source->r_ptr;
162+
int32_t *snk = (int32_t *)sink->w_ptr;
163+
int32_t *x;
164+
int32_t *y;
165+
int ch;
166+
int i;
167+
int rshift;
168+
int lshift;
169+
int shift;
170+
171+
for (ch = 0; ch < nch; ch++) {
172+
/* Get FIR instance and get shifts to e.g. apply mute
173+
* without overhead.
174+
*/
175+
f = &fir[ch];
176+
fir_get_lrshifts(f, &lshift, &rshift);
177+
shift = lshift - rshift;
178+
179+
/* Setup circular buffer for FIR input data delay */
180+
fir_hifi3_setup_circular(f);
181+
182+
x = src++;
183+
y = snk++;
184+
for (i = 0; i < frames; i++) {
185+
fir_32x16_hifi3(f, x, y, shift);
186+
x += nch;
187+
y += nch;
188+
}
189+
}
190+
}
191+
192+
#endif

0 commit comments

Comments
 (0)