Skip to content

Commit 920dc98

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

2 files changed

Lines changed: 437 additions & 0 deletions

File tree

src/audio/fir_hifi2ep.c

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
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_HIFIEP
40+
41+
#include <xtensa/config/defs.h>
42+
#include <xtensa/tie/xt_hifi2.h>
43+
#include "fir_hifi2ep.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_p16x2s *)&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_p24f *) *data;
95+
fir->delay_end = fir->delay + fir->length;
96+
fir->rwp = (ae_p24x2f *)(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_hifiep(struct fir_state_32x16 fir[],
116+
struct comp_buffer *source,
117+
struct comp_buffer *sink,
118+
int frames, int nch)
119+
{
120+
struct fir_state_32x16 *f;
121+
int32_t *src = (int32_t *)source->r_ptr;
122+
int32_t *snk = (int32_t *)sink->w_ptr;
123+
int32_t *x0;
124+
int32_t *y0;
125+
int32_t *x1;
126+
int32_t *y1;
127+
int ch;
128+
int i;
129+
int rshift;
130+
int lshift;
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+
140+
/* Setup circular buffer for FIR input data delay */
141+
fir_hifiep_setup_circular(f);
142+
143+
x0 = src++;
144+
y0 = snk++;
145+
for (i = 0; i < (frames >> 1); i++) {
146+
x1 = x0 + nch;
147+
y1 = y0 + nch;
148+
fir_32x16_2x_hifiep(f, x0, x1, y0, y1, lshift, rshift);
149+
x0 += inc;
150+
y0 += inc;
151+
}
152+
}
153+
}
154+
155+
/* FIR for any number of frames */
156+
void eq_fir_s32_hifiep(struct fir_state_32x16 fir[], struct comp_buffer *source,
157+
struct comp_buffer *sink, int frames, int nch)
158+
{
159+
struct fir_state_32x16 *f;
160+
int32_t *src = (int32_t *)source->r_ptr;
161+
int32_t *snk = (int32_t *)sink->w_ptr;
162+
int32_t *x;
163+
int32_t *y;
164+
int ch;
165+
int i;
166+
int rshift;
167+
int lshift;
168+
169+
for (ch = 0; ch < nch; ch++) {
170+
/* Get FIR instance and get shifts to e.g. apply mute
171+
* without overhead.
172+
*/
173+
f = &fir[ch];
174+
fir_get_lrshifts(f, &lshift, &rshift);
175+
176+
/* Setup circular buffer for FIR input data delay */
177+
fir_hifiep_setup_circular(f);
178+
179+
x = src++;
180+
y = snk++;
181+
for (i = 0; i < frames; i++) {
182+
fir_32x16_hifiep(f, x, y, lshift, rshift);
183+
x += nch;
184+
y += nch;
185+
}
186+
}
187+
}
188+
189+
#endif

0 commit comments

Comments
 (0)