|
28 | 28 | #include <sof/ut.h> |
29 | 29 | #include <user/eq.h> |
30 | 30 | #include <user/trace.h> |
| 31 | +#include <stdbool.h> |
31 | 32 | #include <errno.h> |
32 | 33 | #include <stddef.h> |
33 | 34 | #include <stdint.h> |
@@ -94,94 +95,92 @@ static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad *coef, |
94 | 95 | return 0; |
95 | 96 | } |
96 | 97 |
|
| 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 | + */ |
97 | 126 | static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, uint32_t rate) |
98 | 127 | { |
99 | 128 | struct comp_dev *dev = mod->dev; |
100 | 129 | 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; |
104 | 130 | struct sof_multiband_drc_config *config = cd->config; |
105 | 131 | struct multiband_drc_state *state = &cd->state; |
106 | 132 | 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; |
108 | 136 |
|
109 | 137 | if (!config) { |
110 | 138 | comp_err(dev, "multiband_drc_init_coef(), no config is set"); |
111 | 139 | return -EINVAL; |
112 | 140 | } |
113 | 141 |
|
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); |
125 | 144 | return -EINVAL; |
126 | 145 | } |
127 | 146 |
|
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); |
130 | 148 |
|
131 | | - /* Crossover: collect the coef array and assign it to every channel */ |
132 | | - crossover = config->crossover_coef; |
133 | 149 | 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); |
137 | 155 | 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); |
140 | 157 | goto err; |
141 | 158 | } |
142 | | - } |
143 | | - |
144 | | - comp_info(dev, "multiband_drc_init_coef(), initializing emphasis_eq"); |
145 | 159 |
|
146 | | - /* Emphasis: collect the coef array and assign it to every channel */ |
147 | | - emphasis = config->emp_coef; |
148 | | - for (ch = 0; ch < nch; ch++) { |
149 | 160 | ret = multiband_drc_eq_init_coef_ch(emphasis, &state->emphasis[ch]); |
150 | | - /* Free all previously allocated blocks in case of an error */ |
151 | 161 | 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); |
154 | 163 | goto err; |
155 | 164 | } |
156 | | - } |
157 | 165 |
|
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++) { |
163 | 166 | ret = multiband_drc_eq_init_coef_ch(deemphasis, &state->deemphasis[ch]); |
164 | | - /* Free all previously allocated blocks in case of an error */ |
165 | 167 | 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); |
168 | 169 | goto err; |
169 | 170 | } |
170 | 171 | } |
171 | 172 |
|
172 | | - /* Allocate all DRC pre-delay buffers and set delay time with band number */ |
173 | 173 | for (i = 0; i < num_bands; i++) { |
174 | 174 | comp_info(dev, "multiband_drc_init_coef(), initializing drc band %d", i); |
175 | 175 |
|
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); |
177 | 177 | 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"); |
180 | 179 | goto err; |
181 | 180 | } |
182 | 181 |
|
183 | 182 | 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); |
185 | 184 | if (ret < 0) { |
186 | 185 | comp_err(dev, "multiband_drc_init_coef(), could not set pre delay time"); |
187 | 186 | goto err; |
@@ -215,6 +214,22 @@ static int multiband_drc_setup(struct processing_module *mod, int16_t channels, |
215 | 214 | * End of Multiband DRC setup code. Next the standard component methods. |
216 | 215 | */ |
217 | 216 |
|
| 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 | + */ |
218 | 233 | static int multiband_drc_init(struct processing_module *mod) |
219 | 234 | { |
220 | 235 | struct module_data *md = &mod->priv; |
@@ -242,46 +257,73 @@ static int multiband_drc_init(struct processing_module *mod) |
242 | 257 | md->private = cd; |
243 | 258 | cd->multiband_drc_func = NULL; |
244 | 259 | 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); |
251 | 260 |
|
252 | | - /* Handler for configuration data */ |
253 | 261 | cd->model_handler = comp_data_blob_handler_new(dev); |
254 | 262 | if (!cd->model_handler) { |
255 | 263 | comp_err(dev, "multiband_drc_init(): comp_data_blob_handler_new() failed."); |
256 | 264 | ret = -ENOMEM; |
257 | 265 | goto cd_fail; |
258 | 266 | } |
259 | 267 |
|
260 | | - /* Get configuration data and reset DRC state */ |
261 | 268 | ret = comp_init_data_blob(cd->model_handler, bs, cfg->data); |
262 | 269 | if (ret < 0) { |
263 | 270 | comp_err(dev, "multiband_drc_init(): comp_init_data_blob() failed."); |
264 | | - goto cd_fail; |
| 271 | + goto cd_model_fail; |
265 | 272 | } |
| 273 | + |
266 | 274 | 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); |
267 | 281 |
|
268 | 282 | return 0; |
269 | 283 |
|
270 | | -cd_fail: |
| 284 | +cd_model_fail: |
271 | 285 | comp_data_blob_handler_free(cd->model_handler); |
| 286 | +cd_fail: |
272 | 287 | rfree(cd); |
273 | 288 | return ret; |
274 | 289 | } |
275 | 290 |
|
| 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 | + */ |
276 | 303 | static int multiband_drc_free(struct processing_module *mod) |
277 | 304 | { |
278 | 305 | struct multiband_drc_comp_data *cd = module_get_private_data(mod); |
279 | 306 |
|
280 | 307 | comp_info(mod->dev, "multiband_drc_free()"); |
281 | 308 |
|
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 | + } |
283 | 326 |
|
284 | | - rfree(cd); |
285 | 327 | return 0; |
286 | 328 | } |
287 | 329 |
|
|
0 commit comments