Skip to content

Commit f92af28

Browse files
committed
Audio: MFCC: Fix FFT buffer fill for 32-bit mode
When MFCC_FFT_BITS is 32, the HiFi3/4 mfcc_fill_fft_buffer() used AE_S16_0_XP to write 16-bit samples into 32-bit icomplex32 containers. This left the upper 16 bits of .real with stale data and .imag unzeroed, causing corrupted FFT input after the first frame when scratch buffers are reused for power_spectra and mel_log_32. Replace all platform-specific implementations with a single generic C version in mfcc_common.c. The function performs only data copying with no arithmetic, so HiFi intrinsics provide very little benefit. The new implementation uses int32_t pointer type with matching element stride, and relies on the caller's bzero of fft_buf to keep imaginary parts zero. Fix mel_log_32 scratch space check to use fft_buffer_size instead of assuming sizeof(icomplex32) per element, which overestimated available space by 2x. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent f12dce1 commit f92af28

5 files changed

Lines changed: 48 additions & 130 deletions

File tree

src/audio/mfcc/mfcc_common.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,53 @@ static int mfcc_stft_process(const struct comp_dev *dev, struct mfcc_comp_data *
178178
return cc_count;
179179
}
180180

181+
void mfcc_fill_fft_buffer(struct mfcc_state *state)
182+
{
183+
struct mfcc_buffer *buf = &state->buf;
184+
struct mfcc_fft *fft = &state->fft;
185+
int32_t *d = &fft->fft_buf[fft->fft_fill_start_idx].real;
186+
const int fft_elem_inc = sizeof(fft->fft_buf[0]) / sizeof(int32_t);
187+
int16_t *prev = state->prev_data;
188+
int16_t *prev_end = prev + state->prev_data_size;
189+
int16_t *r = buf->r_ptr;
190+
int copied;
191+
int nmax;
192+
int n;
193+
int j;
194+
195+
/* Copy overlapped samples from state buffer. The fft_buf has been
196+
* cleared by caller so imaginary part remains zero.
197+
*/
198+
while (prev < prev_end) {
199+
*d = *prev++;
200+
d += fft_elem_inc;
201+
}
202+
203+
/* Copy hop size of new data from circular buffer */
204+
for (copied = 0; copied < fft->fft_hop_size; copied += n) {
205+
nmax = fft->fft_hop_size - copied;
206+
n = mfcc_buffer_samples_without_wrap(buf, r);
207+
n = MIN(n, nmax);
208+
for (j = 0; j < n; j++) {
209+
*d = *r++;
210+
d += fft_elem_inc;
211+
}
212+
r = mfcc_buffer_wrap(buf, r);
213+
}
214+
215+
buf->s_avail -= copied;
216+
buf->s_free += copied;
217+
buf->r_ptr = r;
218+
219+
/* Copy for next time data back to overlap buffer */
220+
d = (int32_t *)&fft->fft_buf[fft->fft_fill_start_idx + fft->fft_hop_size].real;
221+
prev = state->prev_data;
222+
while (prev < prev_end) {
223+
*prev++ = *d;
224+
d += fft_elem_inc;
225+
}
226+
}
227+
181228
#if CONFIG_FORMAT_S16LE
182229
static int16_t *mfcc_sink_copy_zero_s16(const struct audio_stream *sink, int16_t *w_ptr,
183230
int samples)

src/audio/mfcc/mfcc_generic.c

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -51,47 +51,6 @@ void mfcc_fill_prev_samples(struct mfcc_buffer *buf, int16_t *prev_data,
5151
buf->r_ptr = r;
5252
}
5353

54-
void mfcc_fill_fft_buffer(struct mfcc_state *state)
55-
{
56-
struct mfcc_buffer *buf = &state->buf;
57-
struct mfcc_fft *fft = &state->fft;
58-
int16_t *r = buf->r_ptr;
59-
int copied;
60-
int nmax;
61-
int idx = fft->fft_fill_start_idx;
62-
int j;
63-
int n;
64-
65-
/* Copy overlapped samples from state buffer. Imaginary part of input
66-
* remains zero.
67-
*/
68-
for (j = 0; j < state->prev_data_size; j++)
69-
fft->fft_buf[idx + j].real = state->prev_data[j];
70-
71-
/* Copy hop size of new data from circular buffer */
72-
idx += state->prev_data_size;
73-
for (copied = 0; copied < fft->fft_hop_size; copied += n) {
74-
nmax = fft->fft_hop_size - copied;
75-
n = mfcc_buffer_samples_without_wrap(buf, r);
76-
n = MIN(n, nmax);
77-
for (j = 0; j < n; j++) {
78-
fft->fft_buf[idx].real = *r;
79-
r++;
80-
idx++;
81-
}
82-
r = mfcc_buffer_wrap(buf, r);
83-
}
84-
85-
buf->s_avail -= copied;
86-
buf->s_free += copied;
87-
buf->r_ptr = r;
88-
89-
/* Copy for next time data back to overlap buffer */
90-
idx = fft->fft_fill_start_idx + fft->fft_hop_size;
91-
for (j = 0; j < state->prev_data_size; j++)
92-
state->prev_data[j] = fft->fft_buf[idx + j].real;
93-
}
94-
9554
void mfcc_apply_window(struct mfcc_state *state, int input_shift)
9655
{
9756
struct mfcc_fft *fft = &state->fft;

src/audio/mfcc/mfcc_hifi3.c

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -128,50 +128,6 @@ void mfcc_fill_prev_samples(struct mfcc_buffer *buf, int16_t *prev_data,
128128
buf->r_ptr = (void *)in; /* int16_t pointer but direct cast is not possible */
129129
}
130130

131-
void mfcc_fill_fft_buffer(struct mfcc_state *state)
132-
{
133-
struct mfcc_buffer *buf = &state->buf;
134-
struct mfcc_fft *fft = &state->fft;
135-
int idx = fft->fft_fill_start_idx;
136-
ae_int16 *out = (ae_int16 *)&fft->fft_buf[idx].real;
137-
ae_int16 *in = (ae_int16 *)state->prev_data;
138-
ae_int16x4 sample;
139-
const int buf_inc = sizeof(ae_int16);
140-
const int fft_inc = sizeof(fft->fft_buf[0]);
141-
int j;
142-
143-
/* Copy overlapped samples from state buffer. Imaginary part of input
144-
* remains zero.
145-
*/
146-
for (j = 0; j < state->prev_data_size; j++) {
147-
AE_L16_XP(sample, in, buf_inc);
148-
AE_S16_0_XP(sample, out, fft_inc);
149-
}
150-
151-
/* Copy hop size of new data from circular buffer */
152-
idx += state->prev_data_size;
153-
in = (ae_int16 *)buf->r_ptr;
154-
out = (ae_int16 *)&fft->fft_buf[idx].real;
155-
set_circular_buf0(buf->addr, buf->end_addr);
156-
for (j = 0; j < fft->fft_hop_size; j++) {
157-
AE_L16_XC(sample, in, buf_inc);
158-
AE_S16_0_XP(sample, out, fft_inc);
159-
}
160-
161-
buf->s_avail -= fft->fft_hop_size;
162-
buf->s_free += fft->fft_hop_size;
163-
buf->r_ptr = (int16_t *)in;
164-
165-
/* Copy for next time data back to overlap buffer */
166-
idx = fft->fft_fill_start_idx + fft->fft_hop_size;
167-
in = (ae_int16 *)&fft->fft_buf[idx].real;
168-
out = (ae_int16 *)state->prev_data;
169-
for (j = 0; j < state->prev_data_size; j++) {
170-
AE_L16_XP(sample, in, fft_inc);
171-
AE_S16_0_XP(sample, out, buf_inc);
172-
}
173-
}
174-
175131
void mfcc_apply_window(struct mfcc_state *state, int input_shift)
176132
{
177133
struct mfcc_fft *fft = &state->fft;

src/audio/mfcc/mfcc_hifi4.c

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -124,50 +124,6 @@ void mfcc_fill_prev_samples(struct mfcc_buffer *buf, int16_t *prev_data,
124124
buf->r_ptr = (int16_t *)in;
125125
}
126126

127-
void mfcc_fill_fft_buffer(struct mfcc_state *state)
128-
{
129-
struct mfcc_buffer *buf = &state->buf;
130-
struct mfcc_fft *fft = &state->fft;
131-
int idx = fft->fft_fill_start_idx;
132-
ae_int16 *out = (ae_int16 *)&fft->fft_buf[idx].real;
133-
ae_int16 *in = (ae_int16 *)state->prev_data;
134-
ae_int16x4 sample;
135-
const int buf_inc = sizeof(ae_int16);
136-
const int fft_inc = sizeof(fft->fft_buf[0]);
137-
int j;
138-
139-
/* Copy overlapped samples from state buffer. Imaginary part of input
140-
* remains zero.
141-
*/
142-
for (j = 0; j < state->prev_data_size; j++) {
143-
AE_L16_XP(sample, in, buf_inc);
144-
AE_S16_0_XP(sample, out, fft_inc);
145-
}
146-
147-
/* Copy hop size of new data from circular buffer */
148-
idx += state->prev_data_size;
149-
in = (ae_int16 *)buf->r_ptr;
150-
out = (ae_int16 *)&fft->fft_buf[idx].real;
151-
set_circular_buf0(buf->addr, buf->end_addr);
152-
for (j = 0; j < fft->fft_hop_size; j++) {
153-
AE_L16_XC(sample, in, buf_inc);
154-
AE_S16_0_XP(sample, out, fft_inc);
155-
}
156-
157-
buf->s_avail -= fft->fft_hop_size;
158-
buf->s_free += fft->fft_hop_size;
159-
buf->r_ptr = (int16_t *)in;
160-
161-
/* Copy for next time data back to overlap buffer */
162-
idx = fft->fft_fill_start_idx + fft->fft_hop_size;
163-
in = (ae_int16 *)&fft->fft_buf[idx].real;
164-
out = (ae_int16 *)state->prev_data;
165-
for (j = 0; j < state->prev_data_size; j++) {
166-
AE_L16_XP(sample, in, fft_inc);
167-
AE_S16_0_XP(sample, out, buf_inc);
168-
}
169-
}
170-
171127
void mfcc_apply_window(struct mfcc_state *state, int input_shift)
172128
{
173129
struct mfcc_fft *fft = &state->fft;

src/audio/mfcc/mfcc_setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ int mfcc_setup(struct processing_module *mod, int max_frames, int sample_rate, i
304304
state->mel_log_32 = &state->power_spectra[fft->half_fft_size];
305305

306306
/* Check that mel_log_32 fits in the remaining fft_buf scratch space */
307-
int mel_log_32_space = fft->fft_padded_size * 2 - fft->half_fft_size;
307+
int mel_log_32_space = (int)(fft->fft_buffer_size / sizeof(int32_t)) - fft->half_fft_size;
308308

309309
if (config->num_mel_bins > mel_log_32_space) {
310310
comp_err(dev, "num_mel_bins %d exceeds mel_log_32 scratch space %d",

0 commit comments

Comments
 (0)