From d1dea28daf26c457661daee0751b2e4e79f18fd0 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Fri, 31 Jan 2025 15:49:34 +0200 Subject: [PATCH 1/2] Audio: Crossover: Change to HiFi5 optimized DF1 IIR type The direct-form I (DF1) is compatible with direct-form-transposed (DF2T). The filter type is changed since DF1 is better potential for optimization for SIMD. In a HiFi5 platform this change saves with two band crossover 0.8 MCPS, from 10.02 MCPS to 9.26 MCPS. The saving will be higher in higher order filter banks such as in multiband DRC component. Signed-off-by: Seppo Ingalsuo --- src/audio/crossover/crossover.c | 6 +++--- src/audio/crossover/crossover.h | 6 +++--- src/audio/crossover/crossover_generic.c | 10 +++++----- src/include/module/crossover/crossover_common.h | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/audio/crossover/crossover.c b/src/audio/crossover/crossover.c index 3c91c329a2f4..3a4af0d43314 100644 --- a/src/audio/crossover/crossover.c +++ b/src/audio/crossover/crossover.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -157,13 +157,13 @@ static int crossover_assign_sinks(struct processing_module *mod, * \param[out] lr4 initialized struct */ static int crossover_init_coef_lr4(struct sof_eq_iir_biquad *coef, - struct iir_state_df2t *lr4) + struct iir_state_df1 *lr4) { int ret; /* Only one set of coefficients is stored in config for both biquads * in series due to identity. To maintain the structure of - * iir_state_df2t, it requires two copies of coefficients in a row. + * iir_state_df1, it requires two copies of coefficients in a row. */ lr4->coef = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(struct sof_eq_iir_biquad) * 2); diff --git a/src/audio/crossover/crossover.h b/src/audio/crossover/crossover.h index f193c058a375..64fc86023ad0 100644 --- a/src/audio/crossover/crossover.h +++ b/src/audio/crossover/crossover.h @@ -8,7 +8,7 @@ #define __SOF_AUDIO_CROSSOVER_CROSSOVER_H__ #include -#include +#include #include #include #include @@ -119,10 +119,10 @@ extern const size_t crossover_split_fncount; * \brief Runs input in through the LR4 filter and returns it's output. */ static inline int32_t crossover_generic_process_lr4(int32_t in, - struct iir_state_df2t *lr4) + struct iir_state_df1 *lr4) { /* Cascade two biquads with same coefficients in series. */ - return iir_df2t(lr4, in); + return iir_df1(lr4, in); } static inline void crossover_free_config(struct sof_crossover_config **config) diff --git a/src/audio/crossover/crossover_generic.c b/src/audio/crossover/crossover_generic.c index e445777113d4..028018934816 100644 --- a/src/audio/crossover/crossover_generic.c +++ b/src/audio/crossover/crossover_generic.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include "crossover.h" @@ -21,8 +21,8 @@ * As a side effect, this function mutates the delay values of both * filters. */ -static inline void crossover_generic_lr4_split(struct iir_state_df2t *lp, - struct iir_state_df2t *hp, +static inline void crossover_generic_lr4_split(struct iir_state_df1 *lp, + struct iir_state_df1 *hp, int32_t x, int32_t *y1, int32_t *y2) { @@ -39,8 +39,8 @@ static inline void crossover_generic_lr4_split(struct iir_state_df2t *lp, * to be out of phase. We need to pass the signal through another set of LR4 * filters to align back the phase. */ -static inline void crossover_generic_lr4_merge(struct iir_state_df2t *lp, - struct iir_state_df2t *hp, +static inline void crossover_generic_lr4_merge(struct iir_state_df1 *lp, + struct iir_state_df1 *hp, int32_t x, int32_t *y) { int32_t z1, z2; diff --git a/src/include/module/crossover/crossover_common.h b/src/include/module/crossover/crossover_common.h index 6cd4acddf85d..28c6e8aa7775 100644 --- a/src/include/module/crossover/crossover_common.h +++ b/src/include/module/crossover/crossover_common.h @@ -8,7 +8,7 @@ #ifndef __SOF_CROSSOVER_COMMON_H__ #define __SOF_CROSSOVER_COMMON_H__ -#include +#include #include /* Number of sinks for a 2 way crossover filter */ @@ -29,8 +29,8 @@ */ struct crossover_state { /* Store the state for each LR4 filter. */ - struct iir_state_df2t lowpass[CROSSOVER_MAX_LR4]; - struct iir_state_df2t highpass[CROSSOVER_MAX_LR4]; + struct iir_state_df1 lowpass[CROSSOVER_MAX_LR4]; + struct iir_state_df1 highpass[CROSSOVER_MAX_LR4]; }; typedef void (*crossover_split)(int32_t in, int32_t out[], @@ -46,7 +46,7 @@ int crossover_init_coef_ch(struct sof_eq_iir_biquad *coef, /** * \brief Reset the state of an LR4 filter. */ -static inline void crossover_reset_state_lr4(struct iir_state_df2t *lr4) +static inline void crossover_reset_state_lr4(struct iir_state_df1 *lr4) { rfree(lr4->coef); rfree(lr4->delay); From 8ea4b54f4c885c057c46f406e773696eaa3fa07a Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Fri, 31 Jan 2025 16:41:51 +0200 Subject: [PATCH 2/2] Audio: Multiband DRC: Switch to HiFi5 optimized IIR DF1 type The direct-form I (DF1) is compatible with direct-form-transposed (DF2T). The filter type is changed since DF1 is better potential for optimization for SIMD. In a build for a HiFi5 platform this and previous patch for crossover filterbank gives with three bands DRC a saving of 6.1 MCPS, from 96.5 MCPS to 90.4 MCPS. Signed-off-by: Seppo Ingalsuo --- src/audio/multiband_drc/multiband_drc.c | 2 +- src/audio/multiband_drc/multiband_drc.h | 8 ++++---- src/audio/multiband_drc/multiband_drc_generic.c | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/audio/multiband_drc/multiband_drc.c b/src/audio/multiband_drc/multiband_drc.c index f948e3354e33..e76741f004fd 100644 --- a/src/audio/multiband_drc/multiband_drc.c +++ b/src/audio/multiband_drc/multiband_drc.c @@ -62,7 +62,7 @@ static void multiband_drc_reset_state(struct multiband_drc_state *state) } static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad *coef, - struct iir_state_df2t *eq) + struct iir_state_df1 *eq) { int ret; diff --git a/src/audio/multiband_drc/multiband_drc.h b/src/audio/multiband_drc/multiband_drc.h index 26ba6dcf33ae..20f939877209 100644 --- a/src/audio/multiband_drc/multiband_drc.h +++ b/src/audio/multiband_drc/multiband_drc.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -22,10 +22,10 @@ * Stores the state of the sub-components in Multiband DRC */ struct multiband_drc_state { - struct iir_state_df2t emphasis[PLATFORM_MAX_CHANNELS]; + struct iir_state_df1 emphasis[PLATFORM_MAX_CHANNELS]; struct crossover_state crossover[PLATFORM_MAX_CHANNELS]; struct drc_state drc[SOF_MULTIBAND_DRC_MAX_BANDS]; - struct iir_state_df2t deemphasis[PLATFORM_MAX_CHANNELS]; + struct iir_state_df1 deemphasis[PLATFORM_MAX_CHANNELS]; }; typedef void (*multiband_drc_func)(const struct processing_module *mod, @@ -89,7 +89,7 @@ static inline multiband_drc_func multiband_drc_find_proc_func_pass(enum sof_ipc_ return NULL; } -static inline void multiband_drc_iir_reset_state_ch(struct iir_state_df2t *iir) +static inline void multiband_drc_iir_reset_state_ch(struct iir_state_df1 *iir) { rfree(iir->coef); rfree(iir->delay); diff --git a/src/audio/multiband_drc/multiband_drc_generic.c b/src/audio/multiband_drc/multiband_drc_generic.c index 2a26f12f03eb..bfdb7c6d3381 100644 --- a/src/audio/multiband_drc/multiband_drc_generic.c +++ b/src/audio/multiband_drc/multiband_drc_generic.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include "multiband_drc.h" #include "../drc/drc_algorithm.h" @@ -27,7 +27,7 @@ static void multiband_drc_process_emp_crossover(struct multiband_drc_state *stat int nch, int nband) { - struct iir_state_df2t *emp_s; + struct iir_state_df1 *emp_s; struct crossover_state *crossover_s; int32_t *buf_sink_band; int ch, band; @@ -39,7 +39,7 @@ static void multiband_drc_process_emp_crossover(struct multiband_drc_state *stat crossover_s = &state->crossover[ch]; if (enable_emp) - emp_out = iir_df2t(emp_s, *buf_src); + emp_out = iir_df1(emp_s, *buf_src); else emp_out = *buf_src; @@ -162,7 +162,7 @@ static void multiband_drc_process_deemp(struct multiband_drc_state *state, int nch, int nband) { - struct iir_state_df2t *deemp_s; + struct iir_state_df1 *deemp_s; int32_t *buf_src_band; int ch, band; int32_t mix_out; @@ -178,7 +178,7 @@ static void multiband_drc_process_deemp(struct multiband_drc_state *state, } if (enable_deemp) - *buf_sink = iir_df2t(deemp_s, mix_out); + *buf_sink = iir_df1(deemp_s, mix_out); else *buf_sink = mix_out;