From edbc031abaacf7400d754a4051614005b7b0aed6 Mon Sep 17 00:00:00 2001 From: Fabiola Kwasowiec Date: Tue, 17 Oct 2023 12:47:03 +0200 Subject: [PATCH] src_lite: add module Addition of SRC Lite module, which only supports a subset of conversions supported by the SRC module. Purpose of SRC Lite module is memory optimization. Code of SRC Lite is drastically reduced and requires significantly less memory. When needed one of defined conversions, driver can choose SRC Lite module instead of SRC module to optimize memory utilization. 48 -> 16kHz 44.1 -> 16 kHz 32 -> 16 kHz 44.1 -> 48 Signed-off-by: Fabiola Kwasowiec --- app/boards/intel_adsp_ace15_mtpm.conf | 1 + src/audio/Kconfig | 12 ++ .../src/coef/src_lite_ipc4_int32_define.h | 23 ++++ .../src/coef/src_lite_ipc4_int32_table.h | 43 ++++++ src/audio/src/src.c | 123 ++++++------------ src/audio/src/src.h | 86 +++++++++++- src/audio/src/src_lite.c | 32 +++++ tools/rimage/config/mtl.toml | 43 +++++- zephyr/CMakeLists.txt | 3 + 9 files changed, 279 insertions(+), 87 deletions(-) create mode 100644 src/audio/src/coef/src_lite_ipc4_int32_define.h create mode 100644 src/audio/src/coef/src_lite_ipc4_int32_table.h create mode 100644 src/audio/src/src_lite.c diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index ac1a3c846441..7f0938bbdd5b 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -3,6 +3,7 @@ CONFIG_IPC_MAJOR_4=y CONFIG_COMP_SRC=y CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_COMP_SRC_LITE=y CONFIG_COMP_DRC=y CONFIG_COMP_CROSSOVER=y CONFIG_COMP_MULTIBAND_DRC=y diff --git a/src/audio/Kconfig b/src/audio/Kconfig index 8c533713419a..b05957a835d3 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -126,6 +126,18 @@ config COMP_SRC help Select for SRC component +config COMP_SRC_LITE + bool "SRC_LITE component" + default y + help + Select for SRC_LITE component + which only supports a subset of conversions + supported by the SRC module: + 48 -> 16kHz + 44.1 -> 16 kHz + 32 -> 16 kHz + 44.1 -> 48 + config COMP_STUBS bool "Build all selected third-party (3P) components with stubs" default n diff --git a/src/audio/src/coef/src_lite_ipc4_int32_define.h b/src/audio/src/coef/src_lite_ipc4_int32_define.h new file mode 100644 index 000000000000..c690f3c7338f --- /dev/null +++ b/src/audio/src/coef/src_lite_ipc4_int32_define.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Fabiola Jasinska + */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_DEFINE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_DEFINE_H__ + +/* SRC constants */ +#define MAX_FIR_DELAY_SIZE 730 +#define MAX_OUT_DELAY_SIZE 900 +#define MAX_BLK_IN 80 +#define MAX_BLK_OUT 40 +#define NUM_IN_FS 16 +#define NUM_OUT_FS 10 +#define STAGE1_TIMES_MAX 32 +#define STAGE2_TIMES_MAX 32 +#define STAGE_BUF_SIZE 672 +#define NUM_ALL_COEFFICIENTS 69224 + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_DEFINE_H__ */ diff --git a/src/audio/src/coef/src_lite_ipc4_int32_table.h b/src/audio/src/coef/src_lite_ipc4_int32_table.h new file mode 100644 index 000000000000..add255e6bf2f --- /dev/null +++ b/src/audio/src/coef/src_lite_ipc4_int32_table.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_src_IPC4_INT32_TABLE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_src_IPC4_INT32_TABLE_H__ + +/* SRC conversions */ +#include "src_ipc4_int32_1_2_4535_5000.h" +#include "src_ipc4_int32_10_21_3455_5000.h" +#include "src_ipc4_int32_1_3_4535_5000.h" +#include "src_ipc4_int32_3_2_4535_5000.h" +#include "src_ipc4_int32_8_7_4535_5000.h" +#include "src_ipc4_int32_16_21_4535_5000.h" +#include "src_ipc4_int32_20_21_4167_5000.h" +#include "../src.h" +#include + +/* SRC table */ +int32_t src_fir_one = 1073741824; +struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &src_fir_one }; +struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &src_fir_one }; +int src_in_fs[3] = { 32000, 44100, 48000}; +int src_out_fs[2] = {16000, 48000}; + +struct src_stage *src_table1[2][3] = { + { &src_int32_1_2_4535_5000, &src_int32_10_21_3455_5000, + &src_int32_1_3_4535_5000 }, + { &src_int32_3_2_4535_5000, &src_int32_8_7_4535_5000, &src_int32_1_1_0_0 } +}; + +struct src_stage *src_table2[2][3] = { + { &src_int32_1_1_0_0, &src_int32_16_21_4535_5000, &src_int32_1_1_0_0 }, + { &src_int32_1_1_0_0, &src_int32_20_21_4167_5000, &src_int32_1_1_0_0 } +}; + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_src_IPC4_INT32_TABLE_H__ */ + +/** \endcond */ diff --git a/src/audio/src/src.c b/src/audio/src/src.c index d1966efe5e4e..c1d26abd2823 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -38,10 +38,12 @@ #include #include -#include "src.h" #include "src_config.h" -#if SRC_SHORT || CONFIG_COMP_SRC_TINY +#ifdef SRC_LITE +#include "coef/src_lite_ipc4_int32_define.h" +#include "coef/src_lite_ipc4_int32_table.h" +#elif SRC_SHORT || CONFIG_COMP_SRC_TINY #include "coef/src_tiny_int16_define.h" #include "coef/src_tiny_int16_table.h" #elif CONFIG_COMP_SRC_SMALL @@ -63,34 +65,9 @@ LOG_MODULE_REGISTER(src, CONFIG_SOF_LOG_LEVEL); -/* Calculates the needed FIR delay line length */ -static int src_fir_delay_length(struct src_stage *s) -{ - return s->subfilter_length + (s->num_of_subfilters - 1) * s->idm - + s->blk_in; -} - -/* Calculates the FIR output delay line length */ -static int src_out_delay_length(struct src_stage *s) -{ - return 1 + (s->num_of_subfilters - 1) * s->odm; -} - -/* Returns index of a matching sample rate */ -static int src_find_fs(int fs_list[], int list_length, int fs) -{ - int i; - - for (i = 0; i < list_length; i++) { - if (fs_list[i] == fs) - return i; - } - return -EINVAL; -} - /* Calculates buffers to allocate for a SRC mode */ -static int src_buffer_lengths(struct comp_dev *dev, struct comp_data *cd, - int nch) +int src_buffer_lengths(struct comp_dev *dev, struct comp_data *cd, + int nch) { struct src_stage *stage1; struct src_stage *stage2; @@ -172,15 +149,9 @@ static int src_buffer_lengths(struct comp_dev *dev, struct comp_data *cd, return 0; } -static void src_state_reset(struct src_state *state) -{ - state->fir_delay_size = 0; - state->out_delay_size = 0; -} - -static int init_stages(struct src_stage *stage1, struct src_stage *stage2, - struct polyphase_src *src, struct src_param *p, - int n, int32_t *delay_lines_start) +int init_stages(struct src_stage *stage1, struct src_stage *stage2, + struct polyphase_src *src, struct src_param *p, + int n, int32_t *delay_lines_start) { /* Clear FIR state */ src_state_reset(&src->state1); @@ -244,15 +215,6 @@ static int init_stages(struct src_stage *stage1, struct src_stage *stage2, return 0; } -void src_polyphase_reset(struct polyphase_src *src) -{ - src->number_of_stages = 0; - src->stage1 = NULL; - src->stage2 = NULL; - src_state_reset(&src->state1); - src_state_reset(&src->state2); -} - int src_polyphase_init(struct polyphase_src *src, struct src_param *p, int32_t *delay_lines_start) { @@ -291,16 +253,9 @@ int src_polyphase_init(struct polyphase_src *src, struct src_param *p, return n_stages; } -/* Fallback function */ -int src_fallback(struct comp_data *cd, struct sof_source *source, - struct sof_sink *sink) -{ - return 0; -} - /* Normal 2 stage SRC */ -static int src_2s(struct comp_data *cd, - struct sof_source *source, struct sof_sink *sink) +int src_2s(struct comp_data *cd, + struct sof_source *source, struct sof_sink *sink) { struct src_stage_prm s1; struct src_stage_prm s2; @@ -401,8 +356,8 @@ static int src_2s(struct comp_data *cd, } /* 1 stage SRC for simple conversions */ -static int src_1s(struct comp_data *cd, struct sof_source *source, - struct sof_sink *sink) +int src_1s(struct comp_data *cd, struct sof_source *source, + struct sof_sink *sink) { struct src_stage_prm s1; int ret; @@ -441,8 +396,8 @@ static int src_1s(struct comp_data *cd, struct sof_source *source, } /* A fast copy function for same in and out rate */ -static int src_copy_sxx(struct comp_data *cd, struct sof_source *source, - struct sof_sink *sink) +int src_copy_sxx(struct comp_data *cd, struct sof_source *source, + struct sof_sink *sink) { int frames = cd->param.blk_in; @@ -468,7 +423,7 @@ void src_set_alignment(struct sof_source *source, struct sof_sink *sink) sink_set_alignment_constants(sink, byte_align, frame_align_req); } -static int src_verify_params(struct processing_module *mod) +int src_verify_params(struct processing_module *mod) { struct sof_ipc_stream_params *params = mod->stream_params; struct comp_data *cd = module_get_private_data(mod); @@ -505,9 +460,9 @@ static int src_verify_params(struct processing_module *mod) return ret; } -static bool src_get_copy_limits(struct comp_data *cd, - struct sof_source *source, - struct sof_sink *sink) +bool src_get_copy_limits(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink) { struct src_param *sp; struct src_stage *s1; @@ -549,9 +504,9 @@ static bool src_get_copy_limits(struct comp_data *cd, return true; } -static int src_params_general(struct processing_module *mod, - struct sof_source *source, - struct sof_sink *sink) +int src_params_general(struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink) { struct comp_data *cd = module_get_private_data(mod); struct comp_dev *dev = mod->dev; @@ -652,9 +607,9 @@ static int src_params_general(struct processing_module *mod, return 0; } -static int src_prepare(struct processing_module *mod, - struct sof_source **sources, int num_of_sources, - struct sof_sink **sinks, int num_of_sinks) +int src_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { int ret; @@ -671,18 +626,18 @@ static int src_prepare(struct processing_module *mod, } -static bool src_is_ready_to_process(struct processing_module *mod, - struct sof_source **sources, int num_of_sources, - struct sof_sink **sinks, int num_of_sinks) +bool src_is_ready_to_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { struct comp_data *cd = module_get_private_data(mod); return src_get_copy_limits(cd, sources[0], sinks[0]); } -static int src_process(struct processing_module *mod, - struct sof_source **sources, int num_of_sources, - struct sof_sink **sinks, int num_of_sinks) +int src_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { struct comp_data *cd = module_get_private_data(mod); @@ -697,21 +652,21 @@ static int src_process(struct processing_module *mod, return cd->src_func(cd, sources[0], sinks[0]); } -static int src_set_config(struct processing_module *mod, uint32_t config_id, - enum module_cfg_fragment_position pos, uint32_t data_offset_size, - const uint8_t *fragment, size_t fragment_size, uint8_t *response, - size_t response_size) +int src_set_config(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, uint8_t *response, + size_t response_size) { return -EINVAL; } -static int src_get_config(struct processing_module *mod, uint32_t config_id, - uint32_t *data_offset_size, uint8_t *fragment, size_t fragment_size) +int src_get_config(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, size_t fragment_size) { return -EINVAL; } -static int src_reset(struct processing_module *mod) +int src_reset(struct processing_module *mod) { struct comp_data *cd = module_get_private_data(mod); @@ -723,7 +678,7 @@ static int src_reset(struct processing_module *mod) return 0; } -static int src_free(struct processing_module *mod) +int src_free(struct processing_module *mod) { struct comp_data *cd = module_get_private_data(mod); diff --git a/src/audio/src/src.h b/src/audio/src/src.h index fe2170ab1714..2ead7fa95062 100644 --- a/src/audio/src/src.h +++ b/src/audio/src/src.h @@ -104,7 +104,20 @@ static inline void src_dec_wrap_s16(int16_t **ptr, int16_t *addr, size_t size) } #endif /* CONFIG_FORMAT_S16LE */ -void src_polyphase_reset(struct polyphase_src *src); +static inline void src_state_reset(struct src_state *state) +{ + state->fir_delay_size = 0; + state->out_delay_size = 0; +} + +static inline void src_polyphase_reset(struct polyphase_src *src) +{ + src->number_of_stages = 0; + src->stage1 = NULL; + src->stage2 = NULL; + src_state_reset(&src->state1); + src_state_reset(&src->state2); +} int src_polyphase_init(struct polyphase_src *src, struct src_param *p, int32_t *delay_lines_start); @@ -173,6 +186,39 @@ int src_stream_pcm_source_rate_check(struct ipc_config_src cfg, struct sof_ipc_stream_params *params); #endif /* CONFIG_IPC_MAJOR_4 */ +/* Calculates the needed FIR delay line length */ +static inline int src_fir_delay_length(struct src_stage *s) +{ + return s->subfilter_length + (s->num_of_subfilters - 1) * s->idm + + s->blk_in; +} + +/* Calculates the FIR output delay line length */ +static inline int src_out_delay_length(struct src_stage *s) +{ + return 1 + (s->num_of_subfilters - 1) * s->odm; +} + +/* Returns index of a matching sample rate */ +static inline int src_find_fs(int fs_list[], int list_length, int fs) +{ + int i; + + for (i = 0; i < list_length; i++) { + if (fs_list[i] == fs) + return i; + } + return -EINVAL; +} + +/* Fallback function */ +static inline int src_fallback(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink) +{ + return 0; +} + int src_rate_check(const void *spec); int src_set_params(struct processing_module *mod, struct sof_sink *sink); @@ -182,9 +228,45 @@ int src_prepare_general(struct processing_module *mod, struct sof_source *source, struct sof_sink *sink); int src_init(struct processing_module *mod); -int src_fallback(struct comp_data *cd, struct sof_source *source, + +int src_buffer_lengths(struct comp_dev *dev, struct comp_data *cd, + int nch); +int init_stages(struct src_stage *stage1, struct src_stage *stage2, + struct polyphase_src *src, struct src_param *p, + int n, int32_t *delay_lines_start); +int src_1s(struct comp_data *cd, struct sof_source *source, + struct sof_sink *sink); +int src_copy_sxx(struct comp_data *cd, struct sof_source *source, struct sof_sink *sink); +int src_verify_params(struct processing_module *mod); + +bool src_get_copy_limits(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink); +int src_params_general(struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink); +int src_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); +int src_2s(struct comp_data *cd, + struct sof_source *source, struct sof_sink *sink); + +bool src_is_ready_to_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); +int src_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); +int src_set_config(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, uint8_t *response, + size_t response_size); +int src_get_config(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, size_t fragment_size); +int src_free(struct processing_module *mod); +int src_reset(struct processing_module *mod); extern const struct sof_uuid src_uuid; extern struct tr_ctx src_tr; diff --git a/src/audio/src/src_lite.c b/src/audio/src/src_lite.c new file mode 100644 index 000000000000..5b6bf40f832a --- /dev/null +++ b/src/audio/src/src_lite.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Fabiola Jasinska + +#include +#include "src.h" +#include "src_config.h" + +#define SRC_LITE 1 + +LOG_MODULE_REGISTER(src_lite, CONFIG_SOF_LOG_LEVEL); + +static const struct module_interface src_lite_interface = { + .init = src_init, + .prepare = src_prepare, + .process = src_process, + .is_ready_to_process = src_is_ready_to_process, + .set_configuration = src_set_config, + .get_configuration = src_get_config, + .reset = src_reset, + .free = src_free, +}; + +DECLARE_SOF_RT_UUID("src_lite", src_lite_uuid, 0x33441051, 0x44CD, 0x466A, + 0x83, 0xA3, 0x17, 0x84, 0x78, 0x70, 0x8A, 0xEA); + +DECLARE_TR_CTX(src_lite_tr, SOF_UUID(src_lite_uuid), LOG_LEVEL_INFO); + +DECLARE_MODULE_ADAPTER(src_lite_interface, src_lite_uuid, src_lite_tr); +SOF_MODULE_INIT(src_lite, sys_comp_module_src_lite_interface_init); diff --git a/tools/rimage/config/mtl.toml b/tools/rimage/config/mtl.toml index 453b0df89dbd..d85f797f627e 100644 --- a/tools/rimage/config/mtl.toml +++ b/tools/rimage/config/mtl.toml @@ -57,7 +57,7 @@ name = "ADSPFW" load_offset = "0x40000" [module] -count = 26 +count = 27 [[module.entry]] name = "BRNGUP" uuid = "2B79E4F3-4675-F649-89DF-3BC194A91AEB" @@ -649,3 +649,44 @@ count = 26 # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] mod_cfg = [0, 0, 0, 0, 296, 5000000, 384, 384, 0, 5000, 0] + + # SRC lite module config + [[module.entry]] + name = "SRC_LITE" + uuid = "33441051-44CD-466A-83A3-178478708AEA" + affinity_mask = "0x1" + #instance_count = "10" + domain_types = "0" + load_type = "0" + module_type = "0x1F" + auto_start = "0" + sched_caps = [1, 0x00008000] + + # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xffff, 0xc, 0x8, 0x05ff, + 1, 0, 0xf6c9, 0xc, 0x8, 0x05ff] + + # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] + mod_cfg = [0, 0, 0, 0, 12832, 1365500, 0, 0, 0, 1365, 0, + 1, 0, 0, 0, 12832, 2302300, 0, 0, 0, 2302, 0, + 2, 0, 0, 0, 12832, 3218200, 0, 0, 0, 3218, 0, + 3, 0, 0, 0, 12832, 4169700, 0, 0, 0, 4169, 0, + 4, 0, 0, 0, 12832, 5095100, 0, 0, 0, 5095, 0, + 5, 0, 0, 0, 12832, 6014800, 0, 0, 0, 6014, 0, + 6, 0, 0, 0, 12832, 6963500, 0, 0, 0, 6963, 0, + 7, 0, 0, 0, 12832, 7791000, 0, 0, 0, 7791, 0, + 8, 0, 0, 0, 12832, 8843000, 0, 0, 0, 8843, 0, + 9, 0, 0, 0, 12832, 9755100, 0, 0, 0, 9755, 0, + 10, 0, 0, 0, 12832, 10726500, 0, 0, 0, 10726, 0, + 11, 0, 0, 0, 12832, 11624100, 0, 0, 0, 11624, 0, + 12, 0, 0, 0, 12832, 12518700, 0, 0, 0, 12518, 0, + 13, 0, 0, 0, 12832, 13555000, 0, 0, 0, 13555, 0, + 14, 0, 0, 0, 12832, 14144500, 0, 0, 0, 14144, 0, + 15, 0, 0, 0, 12832, 15809800, 0, 0, 0, 15809, 0, + 16, 0, 0, 0, 12832, 16749000, 0, 0, 0, 16749, 0, + 17, 0, 0, 0, 12832, 18433500, 0, 0, 0, 18433, 0, + 18, 0, 0, 0, 12832, 19425900, 0, 0, 0, 19425, 0, + 19, 0, 0, 0, 12832, 20396900, 0, 0, 0, 20396, 0, + 20, 0, 0, 0, 12832, 20881000, 0, 0, 0, 20881, 0, + 21, 0, 0, 0, 12832, 23431000, 0, 0, 0, 23431, 0, + 22, 0, 0, 0, 12832, 30471000, 0, 0, 0, 30471, 0] \ No newline at end of file diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 8deca5155919..b398b59b17db 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -600,6 +600,9 @@ elseif(CONFIG_IPC_MAJOR_4) ) endif() +zephyr_library_sources_ifdef(CONFIG_COMP_SRC_LITE + ${SOF_AUDIO_PATH}/src/src_lite.c +) zephyr_library_sources_ifdef(CONFIG_COMP_BASEFW_IPC4 ${SOF_AUDIO_PATH}/base_fw.c )