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+ */
218241static 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+ */
276322static 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
0 commit comments