Skip to content

Commit

Permalink
Audio: MDRC: Restructure MDRC for effective memory allocation
Browse files Browse the repository at this point in the history
This check-in attempts to decrease memory allocation overhead,
enhance cache efficiency through data locality, and lessen heap
fragmentation. Within the MDRC component, combine memory
allocations for the crossover, emphasis, and deemphasis filter
coefficients into a single block.

By streamlining memory management, the update lowers the possibility
of memory leaks.

Signed-off-by: Shriram Shastry <[email protected]>
  • Loading branch information
ShriramShastry committed Jun 11, 2024
1 parent 2f3f877 commit c86a1f7
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 49 deletions.
132 changes: 83 additions & 49 deletions src/audio/multiband_drc/multiband_drc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <sof/ut.h>
#include <user/eq.h>
#include <user/trace.h>
#include <stdbool.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
Expand Down Expand Up @@ -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;
int i, ch, ret;
int num_bands = config ? config->num_bands : 0;

if (!config) {
comp_err(dev, "multiband_drc_init_coef(), no config is set");
Expand All @@ -113,75 +142,64 @@ 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;
}
}
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;
Expand All @@ -191,6 +209,8 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u
return 0;

err:
rfree(cd->coefficients_block);
cd->coefficients_block = NULL;
multiband_drc_reset_state(state);
return ret;
}
Expand Down Expand Up @@ -220,7 +240,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;

Expand All @@ -235,9 +254,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;
Expand Down Expand Up @@ -279,7 +302,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;
Expand Down
14 changes: 14 additions & 0 deletions src/audio/multiband_drc/multiband_drc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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 */
Expand Down

0 comments on commit c86a1f7

Please sign in to comment.