Skip to content

Commit 9ce82c1

Browse files
Audio: MDRC: Restructure MDRC for effective memory allocation
Remove redundant struct multiband_drc_coefficients and simplify memory management by handling memory allocation directly. 1. Removed `struct multiband_drc_coefficients` from multiband_drc.h and multiband_drc.c. 2. Updated `multiband_drc_init` function to eliminate the allocation of the obsolete `coefficients_block`. 3. Adjusted `multiband_drc_free` to no longer check and free the now-nonexistent `coefficients_block`. 4. Directly handled memory allocation and initialization of crossover, emphasis, and de-emphasis coefficients in `multiband_drc_init_coef`. 5. Simplified overall memory management, removing unnecessary layers of indirection. This change reduces 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. Ensured thorough testing to verify no functionality is broken or new issues introduced. Signed-off-by: Shriram Shastry <malladi.sastry@intel.com>
1 parent 28a5265 commit 9ce82c1

2 files changed

Lines changed: 110 additions & 59 deletions

File tree

src/audio/multiband_drc/multiband_drc.c

Lines changed: 101 additions & 59 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,94 +95,92 @@ static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad *coef,
9495
return 0;
9596
}
9697

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+
*/
97126
static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, uint32_t rate)
98127
{
99128
struct comp_dev *dev = mod->dev;
100129
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;
104130
struct sof_multiband_drc_config *config = cd->config;
105131
struct multiband_drc_state *state = &cd->state;
106132
uint32_t sample_bytes = get_sample_bytes(cd->source_format);
107-
int i, ch, ret, num_bands;
133+
struct sof_eq_iir_biquad *crossover, *emphasis, *deemphasis;
134+
int i, ch, ret;
135+
int num_bands = config ? config->num_bands : 0;
108136

109137
if (!config) {
110138
comp_err(dev, "multiband_drc_init_coef(), no config is set");
111139
return -EINVAL;
112140
}
113141

114-
num_bands = config->num_bands;
115-
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);
142+
if (nch > PLATFORM_MAX_CHANNELS || num_bands > SOF_MULTIBAND_DRC_MAX_BANDS) {
143+
comp_err(dev, "Invalid ch count(%i) or band count(%i)", nch, num_bands);
125144
return -EINVAL;
126145
}
127146

128-
comp_info(dev, "multiband_drc_init_coef(), initializing %i-way crossover",
129-
config->num_bands);
147+
comp_info(dev, "multiband_drc_init_coef(), initializing %i-way crossover", num_bands);
130148

131-
/* Crossover: collect the coef array and assign it to every channel */
132-
crossover = config->crossover_coef;
133149
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 */
150+
crossover = config->crossover_coef + ch * num_bands;
151+
emphasis = config->emp_coef + ch * num_bands;
152+
deemphasis = config->deemp_coef + ch * num_bands;
153+
154+
ret = crossover_init_coef_ch(crossover, &state->crossover[ch], num_bands);
137155
if (ret < 0) {
138-
comp_err(dev,
139-
"multiband_drc_init_coef(), could not assign coeffs to ch %d", ch);
156+
comp_err(dev, "Can't assign xover coeffs to ch %d", ch);
140157
goto err;
141158
}
142-
}
143-
144-
comp_info(dev, "multiband_drc_init_coef(), initializing emphasis_eq");
145159

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

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++) {
163166
ret = multiband_drc_eq_init_coef_ch(deemphasis, &state->deemphasis[ch]);
164-
/* Free all previously allocated blocks in case of an error */
165167
if (ret < 0) {
166-
comp_err(dev, "multiband_drc_init_coef(), could not assign coeffs to ch %d",
167-
ch);
168+
comp_err(dev, "Can't assign deemp coeffs to ch %d", ch);
168169
goto err;
169170
}
170171
}
171172

172-
/* Allocate all DRC pre-delay buffers and set delay time with band number */
173173
for (i = 0; i < num_bands; i++) {
174174
comp_info(dev, "multiband_drc_init_coef(), initializing drc band %d", i);
175175

176-
ret = drc_init_pre_delay_buffers(&state->drc[i], (size_t)sample_bytes, (int)nch);
176+
ret = drc_init_pre_delay_buffers(&state->drc[i], sample_bytes, nch);
177177
if (ret < 0) {
178-
comp_err(dev,
179-
"multiband_drc_init_coef(), could not init pre delay buffers");
178+
comp_err(dev, "multiband_drc_init_coef(), can't init pre delay buffers");
180179
goto err;
181180
}
182181

183182
ret = drc_set_pre_delay_time(&state->drc[i],
184-
cd->config->drc_coef[i].pre_delay_time, rate);
183+
config->drc_coef[i].pre_delay_time, rate);
185184
if (ret < 0) {
186185
comp_err(dev, "multiband_drc_init_coef(), could not set pre delay time");
187186
goto err;
@@ -215,6 +214,22 @@ static int multiband_drc_setup(struct processing_module *mod, int16_t channels,
215214
* End of Multiband DRC setup code. Next the standard component methods.
216215
*/
217216

217+
/**
218+
* Initialize Multiband Dynamic Range Control (DRC) component.
219+
*
220+
* Allocates and initializes memory for the multiband DRC component data,
221+
* including state structure, coefficient blocks, and module interface.
222+
* The multiband DRC coefficient block is also allocated here for efficient
223+
* access during processing. The function checks and ensures that the
224+
* provided configuration blob size is within expected limits. If successful,
225+
* the component state is reset and multiband DRC processing is enabled by
226+
* default.
227+
*
228+
* @parameters mod Pointer to the processing module to be initialized.
229+
*
230+
* @return 0 on success, -EINVAL if configuration blob size is too large,
231+
* -ENOMEM if memory allocation fails for component data.
232+
*/
218233
static int multiband_drc_init(struct processing_module *mod)
219234
{
220235
struct module_data *md = &mod->priv;
@@ -242,46 +257,73 @@ static int multiband_drc_init(struct processing_module *mod)
242257
md->private = cd;
243258
cd->multiband_drc_func = NULL;
244259
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);
251260

252-
/* Handler for configuration data */
253261
cd->model_handler = comp_data_blob_handler_new(dev);
254262
if (!cd->model_handler) {
255263
comp_err(dev, "multiband_drc_init(): comp_data_blob_handler_new() failed.");
256264
ret = -ENOMEM;
257265
goto cd_fail;
258266
}
259267

260-
/* Get configuration data and reset DRC state */
261268
ret = comp_init_data_blob(cd->model_handler, bs, cfg->data);
262269
if (ret < 0) {
263270
comp_err(dev, "multiband_drc_init(): comp_init_data_blob() failed.");
264-
goto cd_fail;
271+
goto cd_model_fail;
265272
}
273+
266274
multiband_drc_reset_state(&cd->state);
275+
/* Initialize to enabled is a workaround for IPC4 kernel version 6.6 and
276+
* before where the processing is never enabled via switch control. New
277+
* kernel sends the IPC4 switch control and sets this to desired state
278+
* before prepare.
279+
*/
280+
multiband_drc_process_enable(&cd->process_enabled);
267281

268282
return 0;
269283

270-
cd_fail:
284+
cd_model_fail:
271285
comp_data_blob_handler_free(cd->model_handler);
286+
cd_fail:
272287
rfree(cd);
273288
return ret;
274289
}
275290

291+
/**
292+
* Free resources allocated by Multiband DRC processing component.
293+
*
294+
* This function releases all memory and resources associated with the
295+
* multiband DRC component's operation. This includes dynamically allocated
296+
* filter state instances and the coefficient block as well as freeing up
297+
* the model handler.
298+
*
299+
* @parameters "mod" Pointer to the processing module to be freed.
300+
*
301+
* @return 0 indicating success.
302+
*/
276303
static int multiband_drc_free(struct processing_module *mod)
277304
{
278305
struct multiband_drc_comp_data *cd = module_get_private_data(mod);
279306

280307
comp_info(mod->dev, "multiband_drc_free()");
281308

282-
comp_data_blob_handler_free(cd->model_handler);
309+
if (cd) {
310+
struct multiband_drc_state *state = &cd->state;
311+
312+
/* Free emphasis/deemphasis IIR filter states for all channels */
313+
for (int i = 0; i < PLATFORM_MAX_CHANNELS; i++) {
314+
multiband_drc_iir_reset_state_ch(&state->emphasis[i]);
315+
multiband_drc_iir_reset_state_ch(&state->deemphasis[i]);
316+
}
317+
318+
/* Freeing other resources as part of the component data */
319+
comp_data_blob_handler_free(cd->model_handler);
320+
321+
/* Reset the rest of the component data */
322+
multiband_drc_reset_state(state);
323+
rfree(cd);
324+
module_set_private_data(mod, NULL);
325+
}
283326

284-
rfree(cd);
285327
return 0;
286328
}
287329

src/audio/multiband_drc/multiband_drc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
/**
2222
* Stores the state of the sub-components in Multiband DRC
2323
*/
24+
2425
struct multiband_drc_state {
2526
struct iir_state_df2t emphasis[PLATFORM_MAX_CHANNELS];
2627
struct crossover_state crossover[PLATFORM_MAX_CHANNELS];
@@ -38,6 +39,14 @@ struct multiband_drc_comp_data {
3839
struct multiband_drc_state state; /**< compressor state */
3940
struct comp_data_blob_handler *model_handler;
4041
struct sof_multiband_drc_config *config; /**< pointer to setup blob */
42+
/**
43+
* Pointer to the coefficients of the filters used in multiband DRC processing
44+
* which includes crossover, emphasis, and deemphasis filters. These coefficients
45+
* are used by the processing functions and are allocated during the initialization
46+
* phase. This allows efficient access to filter parameters required for audio
47+
* processing across all channels and bands.
48+
*/
49+
struct multiband_drc_coefficients *coefficients_block; /**< Filter coefficients */
4150
bool config_ready; /**< set when fully received */
4251
enum sof_ipc_frame source_format; /**< source frame format */
4352
bool process_enabled; /**< true if component is enabled */

0 commit comments

Comments
 (0)