Skip to content

Commit 2f173e0

Browse files
committed
Audio: stft_process: Add conversion to polar format and back
This patch adds to stft_process component conversion to polar (magnitude, angle) format for first FFT half from DC to Nyquist frequency. The polar format is converted back to (real, imaginary) complex and upper FFT half symmetry is applied. The magnitude domain is commonly used for signal processing in frequency domain. This change when enabled in Kconfig change increases load in MTL platform from 72 MCPS to 202 MCPS with 1024 size FFT and hop of 256. Currently the build option STFT_PROCESS_MAGNITUDE_PHASE is not set. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 4a3a3fb commit 2f173e0

File tree

4 files changed

+63
-7
lines changed

4 files changed

+63
-7
lines changed

src/audio/stft_process/Kconfig

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
# SPDX-License-Identifier: BSD-3-Clause
22

33
config COMP_STFT_PROCESS
4-
tristate "Template example component"
4+
tristate "STFT processing component"
55
default n
66
select MATH_FFT
77
select MATH_32BIT_FFT
88
select MATH_FFT_MULTI
99
help
10-
Select for stft_process component. Reason for existence
11-
is to provide a minimal component example and use as
12-
placeholder in processing pipelines. As example processing
13-
it swaps or reverses the channels when the switch control
14-
is enabled.
10+
Select for stft_process component. STFT acronym means
11+
short term Fourier transform. It converts audio
12+
to multiple FFTs with selected FFT size, hop, and
13+
window function. Possible signal processing can be
14+
done in it in frequency domain for FFTs that is
15+
efficient for more complex signal processing techniques.
16+
The component converts then the frequency domain
17+
version of signal back to normal PCM audio stream
18+
with inverse STFT.
19+
20+
if COMP_STFT_PROCESS
21+
22+
config STFT_PROCESS_MAGNITUDE_PHASE
23+
bool "Convert FFTs to polar magnitude and phase"
24+
default n
25+
help
26+
Select for processing in polar magnitude and phase
27+
domain. Such complex values format is common for
28+
frequency domain signal processing.
29+
30+
endif # COMP_STFT_PROCESS

src/audio/stft_process/stft_process.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct stft_process_buffer {
6363
struct stft_process_fft {
6464
struct icomplex32 *fft_buf; /**< fft_padded_size */
6565
struct icomplex32 *fft_out; /**< fft_padded_size */
66+
struct ipolar32 *fft_polar;
6667
struct fft_multi_plan *fft_plan;
6768
struct fft_multi_plan *ifft_plan;
6869
int fft_fill_start_idx; /**< Set to 0 for pad left, etc. */

src/audio/stft_process/stft_process_common.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <sof/audio/component.h>
66
#include <sof/audio/audio_stream.h>
77
#include <sof/math/auditory.h>
8+
#include <sof/math/icomplex32.h>
89
#include <sof/math/matrix.h>
910
#include <sof/math/sqrt.h>
1011
#include <sof/math/trig.h>
@@ -97,6 +98,36 @@ static void stft_do_ifft(struct stft_process_state *state, int ch)
9798
stft_process_overlap_add_ifft_buffer(state, ch);
9899
}
99100

101+
#if CONFIG_STFT_PROCESS_MAGNITUDE_PHASE
102+
static void stft_convert_to_polar(struct stft_process_fft *fft)
103+
{
104+
int i;
105+
106+
for (i = 0; i < fft->half_fft_size; i++)
107+
sofm_icomplex32_to_polar(&fft->fft_out[i], &fft->fft_polar[i]);
108+
}
109+
110+
static void stft_convert_to_complex(struct stft_process_fft *fft)
111+
{
112+
int i;
113+
114+
for (i = 0; i < fft->half_fft_size; i++)
115+
sofm_ipolar32_to_complex(&fft->fft_polar[i], &fft->fft_out[i]);
116+
}
117+
118+
static void stft_apply_fft_symmetry(struct stft_process_fft *fft)
119+
{
120+
int i, j, k;
121+
122+
j = 2 * fft->half_fft_size - 2;
123+
for (i = fft->half_fft_size; i < fft->fft_size; i++) {
124+
k = j - i;
125+
fft->fft_out[i].real = fft->fft_out[k].real;
126+
fft->fft_out[i].imag = -fft->fft_out[k].imag;
127+
}
128+
}
129+
#endif
130+
100131
static void stft_do_fft_ifft(const struct processing_module *mod)
101132
{
102133
struct stft_comp_data *cd = module_get_private_data(mod);
@@ -110,7 +141,12 @@ static void stft_do_fft_ifft(const struct processing_module *mod)
110141
if (num_fft) {
111142
stft_do_fft(state, ch);
112143

113-
/* stft_process(state) */
144+
#if CONFIG_STFT_PROCESS_MAGNITUDE_PHASE
145+
/* Convert half-FFT to polar and back, and fix upper part */
146+
stft_convert_to_polar(&state->fft);
147+
stft_convert_to_complex(&state->fft);
148+
stft_apply_fft_symmetry(&state->fft);
149+
#endif
114150

115151
stft_do_ifft(state, ch);
116152
cd->fft_done = true;

src/audio/stft_process/stft_process_setup.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ int stft_process_setup(struct processing_module *mod, int max_frames,
163163
goto free_fft_buf;
164164
}
165165

166+
/* Share the fft_out buffer for polar format */
167+
fft->fft_polar = (struct ipolar32 *)fft->fft_out;
168+
166169
fft->fft_fill_start_idx = 0; /* From config pad_type */
167170

168171
/* Setup FFT */

0 commit comments

Comments
 (0)