Skip to content

Commit f770cd2

Browse files
Audio: MDRC: Restructure MDRC for effective memory allocation
This checkin consolidates the memory allocations for the crossover, emphasis, and deemphasis filter coefficients of the multiband DRC (MDRC) component into a single contiguous block. This change reduces the memory allocation overhead, improves data locality to enhance cache efficiency, and mitigates heap fragmentation. The refactoring of memory management adds robustness to the component by reducing the chances of memory leaks and simplifying the initialization and cleanup process. By streamlining memory management, the update lowers the possibility of memory leaks. Signed-off-by: Shriram Shastry <malladi.sastry@intel.com>
1 parent 2f3f877 commit f770cd2

File tree

2 files changed

+137
-57
lines changed

2 files changed

+137
-57
lines changed

src/audio/multiband_drc/multiband_drc.c

Lines changed: 123 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <sof/ut.h>
2929
#include <user/eq.h>
3030
#include <user/trace.h>
31+
#include <stdbool.h>
3132
#include <errno.h>
3233
#include <stddef.h>
3334
#include <stdint.h>
@@ -94,17 +95,45 @@ static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad *coef,
9495
return 0;
9596
}
9697

97-
static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, uint32_t rate)
98+
/**
99+
* @Description Initialize coefficients for multiband DRC processing.
100+
*
101+
* Allocates and initializes filter coefficients for the multiband DRC module. Memory
102+
* for the crossover, emphasis, and de-emphasis filter coefficients is allocated within
103+
* a contiguous block if not previously done. The function checks for configuration
104+
* validity and adheres to predefined channel and band count limits.
105+
*
106+
* The memory layout for the coefficients_block is as follows:
107+
* @code
108+
* +-----------------------------------+
109+
* | coefficients_block |
110+
* +-----------------------------------+
111+
* | crossover_coef | num_bands * nch * sizeof(struct sof_eq_iir_biquad)
112+
* +-----------------------------------+ <-- offset for emp_coef (crossover_coef + num_bands * nch)
113+
* | emp_coef | num_bands * nch * sizeof(struct sof_eq_iir_biquad)
114+
* +-----------------------------------+ <-- offset for deemp_coef (emp_coef + num_bands * nch)
115+
* | deemp_coef | num_bands * nch * sizeof(struct sof_eq_iir_biquad)
116+
* +-----------------------------------+
117+
* @endcode
118+
*
119+
* @parameters mod Pointer to the processing module containing multiband DRC data.
120+
* @parameters nch Number of channels to process, up to PLATFORM_MAX_CHANNELS.
121+
* @parameters rate Sampling rate, not used in current implementation.
122+
*
123+
* @return 0 on success or a negative error code on failure (e.g., invalid configuration,
124+
* memory allocation failure).
125+
*/
126+
static int multiband_drc_init_coef(struct processing_module *mod,
127+
int16_t nch, uint32_t rate)
98128
{
99129
struct comp_dev *dev = mod->dev;
100130
struct multiband_drc_comp_data *cd = module_get_private_data(mod);
101-
struct sof_eq_iir_biquad *crossover;
102-
struct sof_eq_iir_biquad *emphasis;
103-
struct sof_eq_iir_biquad *deemphasis;
104131
struct sof_multiband_drc_config *config = cd->config;
105132
struct multiband_drc_state *state = &cd->state;
106133
uint32_t sample_bytes = get_sample_bytes(cd->source_format);
107-
int i, ch, ret, num_bands;
134+
struct sof_eq_iir_biquad *crossover, *emphasis, *deemphasis;
135+
int i, ch, ret;
136+
int num_bands = config ? config->num_bands : 0;
108137

109138
if (!config) {
110139
comp_err(dev, "multiband_drc_init_coef(), no config is set");
@@ -113,58 +142,37 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u
113142

114143
num_bands = config->num_bands;
115144

116-
/* Sanity checks */
117-
if (nch > PLATFORM_MAX_CHANNELS) {
118-
comp_err(dev,
119-
"multiband_drc_init_coef(), invalid channels count(%i)", nch);
120-
return -EINVAL;
121-
}
122-
if (config->num_bands > SOF_MULTIBAND_DRC_MAX_BANDS) {
123-
comp_err(dev, "multiband_drc_init_coef(), invalid bands count(%i)",
124-
config->num_bands);
145+
if (nch > PLATFORM_MAX_CHANNELS || num_bands > SOF_MULTIBAND_DRC_MAX_BANDS) {
146+
comp_err(dev, "Invalid ch count(%i) or band count(%i)", nch, num_bands);
125147
return -EINVAL;
126148
}
127149

128150
comp_info(dev, "multiband_drc_init_coef(), initializing %i-way crossover",
129-
config->num_bands);
151+
num_bands);
130152

131-
/* Crossover: collect the coef array and assign it to every channel */
132-
crossover = config->crossover_coef;
153+
struct multiband_drc_coefficients *coefficients_block = cd->coefficients_block;
154+
155+
/* Crossover, Emphasis, and Deemphasis EQ initialization for each channel */
133156
for (ch = 0; ch < nch; ch++) {
134-
ret = crossover_init_coef_ch(crossover, &state->crossover[ch],
135-
config->num_bands);
136-
/* Free all previously allocated blocks in case of an error */
157+
crossover = coefficients_block->crossover + ch * num_bands;
158+
emphasis = coefficients_block->emphasis + ch * num_bands;
159+
deemphasis = coefficients_block->deemphasis + ch * num_bands;
160+
161+
ret = crossover_init_coef_ch(crossover, &state->crossover[ch], num_bands);
137162
if (ret < 0) {
138-
comp_err(dev,
139-
"multiband_drc_init_coef(), could not assign coeffs to ch %d", ch);
163+
comp_err(dev, "Can't assign xover coeffs to ch %d", ch);
140164
goto err;
141165
}
142-
}
143166

144-
comp_info(dev, "multiband_drc_init_coef(), initializing emphasis_eq");
145-
146-
/* Emphasis: collect the coef array and assign it to every channel */
147-
emphasis = config->emp_coef;
148-
for (ch = 0; ch < nch; ch++) {
149167
ret = multiband_drc_eq_init_coef_ch(emphasis, &state->emphasis[ch]);
150-
/* Free all previously allocated blocks in case of an error */
151168
if (ret < 0) {
152-
comp_err(dev, "multiband_drc_init_coef(), could not assign coeffs to ch %d",
153-
ch);
169+
comp_err(dev, "Can't assign emp coeffs to ch %d", ch);
154170
goto err;
155171
}
156-
}
157172

158-
comp_info(dev, "multiband_drc_init_coef(), initializing deemphasis_eq");
159-
160-
/* Deemphasis: collect the coef array and assign it to every channel */
161-
deemphasis = config->deemp_coef;
162-
for (ch = 0; ch < nch; ch++) {
163173
ret = multiband_drc_eq_init_coef_ch(deemphasis, &state->deemphasis[ch]);
164-
/* Free all previously allocated blocks in case of an error */
165174
if (ret < 0) {
166-
comp_err(dev, "multiband_drc_init_coef(), could not assign coeffs to ch %d",
167-
ch);
175+
comp_err(dev, "Can't assign deemp coeffs to ch %d", ch);
168176
goto err;
169177
}
170178
}
@@ -173,15 +181,14 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u
173181
for (i = 0; i < num_bands; i++) {
174182
comp_info(dev, "multiband_drc_init_coef(), initializing drc band %d", i);
175183

176-
ret = drc_init_pre_delay_buffers(&state->drc[i], (size_t)sample_bytes, (int)nch);
184+
ret = drc_init_pre_delay_buffers(&state->drc[i], sample_bytes, nch);
177185
if (ret < 0) {
178-
comp_err(dev,
179-
"multiband_drc_init_coef(), could not init pre delay buffers");
186+
comp_err(dev, "multiband_drc_init_coef(), could not init pre delay buffers");
180187
goto err;
181188
}
182189

183190
ret = drc_set_pre_delay_time(&state->drc[i],
184-
cd->config->drc_coef[i].pre_delay_time, rate);
191+
config->drc_coef[i].pre_delay_time, rate);
185192
if (ret < 0) {
186193
comp_err(dev, "multiband_drc_init_coef(), could not set pre delay time");
187194
goto err;
@@ -215,6 +222,22 @@ static int multiband_drc_setup(struct processing_module *mod, int16_t channels,
215222
* End of Multiband DRC setup code. Next the standard component methods.
216223
*/
217224

225+
/**
226+
* Initialize Multiband Dynamic Range Control (DRC) component.
227+
*
228+
* Allocates and initializes memory for the multiband DRC component data,
229+
* including state structure, coefficient blocks, and module interface.
230+
* The multiband DRC coefficient block is also allocated here for efficient
231+
* access during processing. The function checks and ensures that the
232+
* provided configuration blob size is within expected limits. If successful,
233+
* the component state is reset and multiband DRC processing is enabled by
234+
* default.
235+
*
236+
* @parameters mod Pointer to the processing module to be initialized.
237+
*
238+
* @return 0 on success, -EINVAL if configuration blob size is too large,
239+
* -ENOMEM if memory allocation fails for component data.
240+
*/
218241
static int multiband_drc_init(struct processing_module *mod)
219242
{
220243
struct module_data *md = &mod->priv;
@@ -236,52 +259,95 @@ static int multiband_drc_init(struct processing_module *mod)
236259
}
237260

238261
cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd));
239-
if (!cd)
262+
if (!cd) {
263+
comp_err(dev, "multiband_drc_init(), allocation for multiband_drc_comp_data failed");
240264
return -ENOMEM;
265+
}
241266

242267
md->private = cd;
243268
cd->multiband_drc_func = NULL;
244269
cd->crossover_split = NULL;
245-
/* Initialize to enabled is a workaround for IPC4 kernel version 6.6 and
246-
* before where the processing is never enabled via switch control. New
247-
* kernel sends the IPC4 switch control and sets this to desired state
248-
* before prepare.
249-
*/
250-
multiband_drc_process_enable(&cd->process_enabled);
251270

252-
/* Handler for configuration data */
253271
cd->model_handler = comp_data_blob_handler_new(dev);
254272
if (!cd->model_handler) {
255273
comp_err(dev, "multiband_drc_init(): comp_data_blob_handler_new() failed.");
256274
ret = -ENOMEM;
257275
goto cd_fail;
258276
}
259277

260-
/* Get configuration data and reset DRC state */
261278
ret = comp_init_data_blob(cd->model_handler, bs, cfg->data);
262279
if (ret < 0) {
263280
comp_err(dev, "multiband_drc_init(): comp_init_data_blob() failed.");
264-
goto cd_fail;
281+
goto cd_model_fail;
282+
}
283+
284+
cd->coefficients_block = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
285+
sizeof(struct multiband_drc_coefficients));
286+
if (!cd->coefficients_block) {
287+
comp_err(dev, "Failed to allocate coeff block during initialization");
288+
ret = -ENOMEM;
289+
goto cd_init_coef_fail;
265290
}
291+
266292
multiband_drc_reset_state(&cd->state);
293+
/* Initialize to enabled is a workaround for IPC4 kernel version 6.6 and
294+
* before where the processing is never enabled via switch control. New
295+
* kernel sends the IPC4 switch control and sets this to desired state
296+
* before prepare.
297+
*/
298+
multiband_drc_process_enable(&cd->process_enabled);
267299

268300
return 0;
269301

270-
cd_fail:
302+
cd_init_coef_fail:
271303
comp_data_blob_handler_free(cd->model_handler);
304+
cd_model_fail:
272305
rfree(cd);
306+
cd_fail:
273307
return ret;
274308
}
275309

310+
/**
311+
* Free resources allocated by Multiband DRC processing component.
312+
*
313+
* This function releases all memory and resources associated with the
314+
* multiband DRC component's operation. This includes dynamically allocated
315+
* filter state instances and the coefficient block as well as freeing up
316+
* the model handler.
317+
*
318+
* @parameters "mod" Pointer to the processing module to be freed.
319+
*
320+
* @return 0 indicating success.
321+
*/
276322
static int multiband_drc_free(struct processing_module *mod)
277323
{
278324
struct multiband_drc_comp_data *cd = module_get_private_data(mod);
279325

280326
comp_info(mod->dev, "multiband_drc_free()");
281327

282-
comp_data_blob_handler_free(cd->model_handler);
328+
if (cd) {
329+
struct multiband_drc_state *state = &cd->state;
330+
331+
/* Free emphasis/deemphasis IIR filter states for all channels */
332+
for (int i = 0; i < PLATFORM_MAX_CHANNELS; i++) {
333+
multiband_drc_iir_reset_state_ch(&state->emphasis[i]);
334+
multiband_drc_iir_reset_state_ch(&state->deemphasis[i]);
335+
}
336+
337+
/* Freeing other resources as part of the component data */
338+
comp_data_blob_handler_free(cd->model_handler);
339+
340+
if (cd->coefficients_block) {
341+
rfree(cd->coefficients_block);
342+
cd->coefficients_block = NULL;
343+
}
344+
345+
/* Reset the rest of the component data */
346+
multiband_drc_reset_state(state);
347+
rfree(cd);
348+
module_set_private_data(mod, NULL);
349+
}
283350

284-
rfree(cd);
285351
return 0;
286352
}
287353

src/audio/multiband_drc/multiband_drc.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
/**
2222
* Stores the state of the sub-components in Multiband DRC
2323
*/
24+
struct multiband_drc_coefficients {
25+
struct sof_eq_iir_biquad crossover[SOF_MULTIBAND_DRC_MAX_BANDS * PLATFORM_MAX_CHANNELS];
26+
struct sof_eq_iir_biquad emphasis[SOF_MULTIBAND_DRC_MAX_BANDS * PLATFORM_MAX_CHANNELS];
27+
struct sof_eq_iir_biquad deemphasis[SOF_MULTIBAND_DRC_MAX_BANDS * PLATFORM_MAX_CHANNELS];
28+
};
29+
2430
struct multiband_drc_state {
2531
struct iir_state_df2t emphasis[PLATFORM_MAX_CHANNELS];
2632
struct crossover_state crossover[PLATFORM_MAX_CHANNELS];
@@ -38,6 +44,14 @@ struct multiband_drc_comp_data {
3844
struct multiband_drc_state state; /**< compressor state */
3945
struct comp_data_blob_handler *model_handler;
4046
struct sof_multiband_drc_config *config; /**< pointer to setup blob */
47+
/**
48+
* Pointer to the coefficients of the filters used in multiband DRC processing
49+
* which includes crossover, emphasis, and deemphasis filters. These coefficients
50+
* are used by the processing functions and are allocated during the initialization
51+
* phase. This allows efficient access to filter parameters required for audio
52+
* processing across all channels and bands.
53+
*/
54+
struct multiband_drc_coefficients *coefficients_block; /**< Filter coefficients */
4155
bool config_ready; /**< set when fully received */
4256
enum sof_ipc_frame source_format; /**< source frame format */
4357
bool process_enabled; /**< true if component is enabled */

0 commit comments

Comments
 (0)