diff --git a/src/audio/multiband_drc/multiband_drc.c b/src/audio/multiband_drc/multiband_drc.c index e10b63d28d9a..7c8741e16c89 100644 --- a/src/audio/multiband_drc/multiband_drc.c +++ b/src/audio/multiband_drc/multiband_drc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -94,17 +95,45 @@ static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad *coef, return 0; } -static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, uint32_t rate) +/** + * @Description Initialize coefficients for multiband DRC processing. + * + * Allocates and initializes filter coefficients for the multiband DRC module. Memory + * for the crossover, emphasis, and de-emphasis filter coefficients is allocated within + * a contiguous block if not previously done. The function checks for configuration + * validity and adheres to predefined channel and band count limits. + * + * The memory layout for the coefficients_block is as follows: + * @code + * +-----------------------------------+ + * | coefficients_block | + * +-----------------------------------+ + * | crossover_coef | num_bands * nch * sizeof(struct sof_eq_iir_biquad) + * +-----------------------------------+ <-- offset for emp_coef (crossover_coef + num_bands * nch) + * | emp_coef | num_bands * nch * sizeof(struct sof_eq_iir_biquad) + * +-----------------------------------+ <-- offset for deemp_coef (emp_coef + num_bands * nch) + * | deemp_coef | num_bands * nch * sizeof(struct sof_eq_iir_biquad) + * +-----------------------------------+ + * @endcode + * + * @parameters mod Pointer to the processing module containing multiband DRC data. + * @parameters nch Number of channels to process, up to PLATFORM_MAX_CHANNELS. + * @parameters rate Sampling rate, not used in current implementation. + * + * @return 0 on success or a negative error code on failure (e.g., invalid configuration, + * memory allocation failure). + */ + +static int multiband_drc_init_coef(struct processing_module *mod, + int16_t nch, uint32_t rate) { struct comp_dev *dev = mod->dev; struct multiband_drc_comp_data *cd = module_get_private_data(mod); - struct sof_eq_iir_biquad *crossover; - struct sof_eq_iir_biquad *emphasis; - struct sof_eq_iir_biquad *deemphasis; struct sof_multiband_drc_config *config = cd->config; struct multiband_drc_state *state = &cd->state; uint32_t sample_bytes = get_sample_bytes(cd->source_format); int i, ch, ret, num_bands; + bool alloc_success = false; if (!config) { comp_err(dev, "multiband_drc_init_coef(), no config is set"); @@ -113,75 +142,65 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u num_bands = config->num_bands; - /* Sanity checks */ - if (nch > PLATFORM_MAX_CHANNELS) { - comp_err(dev, - "multiband_drc_init_coef(), invalid channels count(%i)", nch); - return -EINVAL; - } - if (config->num_bands > SOF_MULTIBAND_DRC_MAX_BANDS) { - comp_err(dev, "multiband_drc_init_coef(), invalid bands count(%i)", - config->num_bands); + if (nch > PLATFORM_MAX_CHANNELS || num_bands > SOF_MULTIBAND_DRC_MAX_BANDS) { + comp_err(dev, "Invalid ch count(%i) or band count(%i)", nch, num_bands); return -EINVAL; } comp_info(dev, "multiband_drc_init_coef(), initializing %i-way crossover", - config->num_bands); + num_bands); + + /* Allocation for coefficients_block */ + if (!cd->coefficients_block) { + cd->coefficients_block = rballoc(0, SOF_MEM_CAPS_RAM, + sizeof(struct multiband_drc_coefficients)); + if (!cd->coefficients_block) { + comp_err(dev, "Failed to allocate coeff block multiband_drc_init_coef()"); + return -ENOMEM; + } + alloc_success = true; /* Allocation was successful */ + } + struct multiband_drc_coefficients *coefficients_block = cd->coefficients_block; + + /* Crossover, Emphasis, and Deemphasis EQ initialization for each channel */ + struct sof_eq_iir_biquad *crossover, *emphasis, *deemphasis; - /* Crossover: collect the coef array and assign it to every channel */ - crossover = config->crossover_coef; for (ch = 0; ch < nch; ch++) { - ret = crossover_init_coef_ch(crossover, &state->crossover[ch], - config->num_bands); - /* Free all previously allocated blocks in case of an error */ + crossover = coefficients_block->crossover + ch * num_bands; + emphasis = coefficients_block->emphasis + ch * num_bands; + deemphasis = coefficients_block->deemphasis + ch * num_bands; + + ret = crossover_init_coef_ch(crossover, &state->crossover[ch], num_bands); if (ret < 0) { - comp_err(dev, - "multiband_drc_init_coef(), could not assign coeffs to ch %d", ch); + comp_err(dev, "Can't assign xover coeffs to ch %d", ch); goto err; } - } - comp_info(dev, "multiband_drc_init_coef(), initializing emphasis_eq"); - - /* Emphasis: collect the coef array and assign it to every channel */ - emphasis = config->emp_coef; - for (ch = 0; ch < nch; ch++) { ret = multiband_drc_eq_init_coef_ch(emphasis, &state->emphasis[ch]); - /* Free all previously allocated blocks in case of an error */ if (ret < 0) { - comp_err(dev, "multiband_drc_init_coef(), could not assign coeffs to ch %d", - ch); + comp_err(dev, "Can't assign emp coeffs to ch %d", ch); goto err; } - } - - comp_info(dev, "multiband_drc_init_coef(), initializing deemphasis_eq"); - /* Deemphasis: collect the coef array and assign it to every channel */ - deemphasis = config->deemp_coef; - for (ch = 0; ch < nch; ch++) { ret = multiband_drc_eq_init_coef_ch(deemphasis, &state->deemphasis[ch]); - /* Free all previously allocated blocks in case of an error */ if (ret < 0) { - comp_err(dev, "multiband_drc_init_coef(), could not assign coeffs to ch %d", - ch); + comp_err(dev, "Can't assign deemp coeffs to ch %d", ch); goto err; } } - /* Allocate all DRC pre-delay buffers and set delay time with band number */ + /* Initialize DRC state for each band */ for (i = 0; i < num_bands; i++) { comp_info(dev, "multiband_drc_init_coef(), initializing drc band %d", i); - ret = drc_init_pre_delay_buffers(&state->drc[i], (size_t)sample_bytes, (int)nch); + ret = drc_init_pre_delay_buffers(&state->drc[i], sample_bytes, nch); if (ret < 0) { - comp_err(dev, - "multiband_drc_init_coef(), could not init pre delay buffers"); + comp_err(dev, "multiband_drc_init_coef(), could not init pre delay buffers"); goto err; } ret = drc_set_pre_delay_time(&state->drc[i], - cd->config->drc_coef[i].pre_delay_time, rate); + config->drc_coef[i].pre_delay_time, rate); if (ret < 0) { comp_err(dev, "multiband_drc_init_coef(), could not set pre delay time"); goto err; @@ -191,6 +210,10 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u return 0; err: + if (alloc_success && ret < 0) { + rfree(cd->coefficients_block); + cd->coefficients_block = NULL; + } multiband_drc_reset_state(state); return ret; } @@ -220,7 +243,6 @@ static int multiband_drc_init(struct processing_module *mod) struct module_data *md = &mod->priv; struct comp_dev *dev = mod->dev; struct module_config *cfg = &md->cfg; - struct multiband_drc_comp_data *cd; size_t bs = cfg->size; int ret; @@ -235,9 +257,13 @@ static int multiband_drc_init(struct processing_module *mod) return -EINVAL; } - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) + /* Memory allocation for multiband_drc_comp_data */ + struct multiband_drc_comp_data *cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, + SOF_MEM_CAPS_RAM, sizeof(*cd)); + if (!cd) { + comp_err(dev, "multiband_drc_init(), allocation for multiband_drc_comp_data failed"); return -ENOMEM; + } md->private = cd; cd->multiband_drc_func = NULL; @@ -279,7 +305,18 @@ static int multiband_drc_free(struct processing_module *mod) comp_info(mod->dev, "multiband_drc_free()"); - comp_data_blob_handler_free(cd->model_handler); + if (cd) { + struct multiband_drc_state *state = &cd->state; + + /* Free emphasis/deemphasis IIR filter states for all channels */ + for (int i = 0; i < PLATFORM_MAX_CHANNELS; i++) { + multiband_drc_iir_reset_state_ch(&state->emphasis[i]); + multiband_drc_iir_reset_state_ch(&state->deemphasis[i]); + } + + /* Freeing other resources as part of the component data */ + comp_data_blob_handler_free(cd->model_handler); + } rfree(cd); return 0; diff --git a/src/audio/multiband_drc/multiband_drc.h b/src/audio/multiband_drc/multiband_drc.h index a1801f27ab6c..37eeff3a0b85 100644 --- a/src/audio/multiband_drc/multiband_drc.h +++ b/src/audio/multiband_drc/multiband_drc.h @@ -21,6 +21,12 @@ /** * Stores the state of the sub-components in Multiband DRC */ +struct multiband_drc_coefficients { + struct sof_eq_iir_biquad crossover[SOF_MULTIBAND_DRC_MAX_BANDS * PLATFORM_MAX_CHANNELS]; + struct sof_eq_iir_biquad emphasis[SOF_MULTIBAND_DRC_MAX_BANDS * PLATFORM_MAX_CHANNELS]; + struct sof_eq_iir_biquad deemphasis[SOF_MULTIBAND_DRC_MAX_BANDS * PLATFORM_MAX_CHANNELS]; +} __packed; + struct multiband_drc_state { struct iir_state_df2t emphasis[PLATFORM_MAX_CHANNELS]; struct crossover_state crossover[PLATFORM_MAX_CHANNELS]; @@ -38,6 +44,14 @@ struct multiband_drc_comp_data { struct multiband_drc_state state; /**< compressor state */ struct comp_data_blob_handler *model_handler; struct sof_multiband_drc_config *config; /**< pointer to setup blob */ + /** + * Pointer to the coefficients of the filters used in multiband DRC processing + * which includes crossover, emphasis, and deemphasis filters. These coefficients + * are used by the processing functions and are allocated during the initialization + * phase. This allows efficient access to filter parameters required for audio + * processing across all channels and bands. + */ + struct multiband_drc_coefficients *coefficients_block; /**< Filter coefficients */ bool config_ready; /**< set when fully received */ enum sof_ipc_frame source_format; /**< source frame format */ bool process_enabled; /**< true if component is enabled */