1 /*******************************************************************************
2 * Copyright (C) 2018 Cadence Design Systems, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to use this Software with Cadence processor cores only and
7 * not with any other processors and platforms, subject to
8 * the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included
11 * in all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 ******************************************************************************/
22
23 /*******************************************************************************
24 * xa-mixer.c
25 *
26 * Sample mixer plugin
27 *
28 ******************************************************************************/
29
30 #define MODULE_TAG MIXER
31
32 /*******************************************************************************
33 * Includes
34 ******************************************************************************/
35
36 #include "xf-plugin.h"
37 #include "audio/xa-mixer-api.h"
38
39 /*******************************************************************************
40 * Tracing configuration
41 ******************************************************************************/
42
43 TRACE_TAG(INIT, 1);
44 TRACE_TAG(PROCESS, 1);
45
46 /*******************************************************************************
47 * Internal functions definitions
48 ******************************************************************************/
49
50 /* ...API structure */
51 typedef struct XAPcmMixer
52 {
53 /* ...mixer state */
54 u32 state;
55
56 /* ...number of samples in a frame */
57 u32 frame_size;
58
59 /* ...number of channels (channel mask?) */
60 u32 channels;
61
62 /* ...PCM sample width */
63 u32 pcm_width;
64
65 /* ...sampling rate */
66 u32 sample_rate;
67
68 /* ...number of bytes in input/output buffer */
69 u32 buffer_size;
70
71 /* ...master volume and individual track volumes*/
72 u32 volume[XA_MIXER_MAX_TRACK_NUMBER + 1];
73
74 /* ...input buffers */
75 void *input[XA_MIXER_MAX_TRACK_NUMBER];
76
77 /* ...number of samples in individual buffers */
78 u32 input_length[XA_MIXER_MAX_TRACK_NUMBER];
79
80 /* ...output buffer */
81 void *output;
82
83 /* ...number of produced bytes - do I need that? have buffer-size already - tbd */
84 u32 produced;
85
86 /* ...scratch buffer pointer */
87 void *scratch;
88
89 } XAPcmMixer;
90
91 /*******************************************************************************
92 * Mixer state flags
93 ******************************************************************************/
94
95 #define XA_MIXER_FLAG_PREINIT_DONE (1 << 0)
96 #define XA_MIXER_FLAG_POSTINIT_DONE (1 << 1)
97 #define XA_MIXER_FLAG_RUNNING (1 << 2)
98 #define XA_MIXER_FLAG_OUTPUT (1 << 3)
99 #define XA_MIXER_FLAG_COMPLETE (1 << 4)
100
101 /*******************************************************************************
102 * DSP functions
103 ******************************************************************************/
104
105 #define DSP_SATURATE_S16(s32) \
106 (s16)((s32) > 0x7fff ? 0x7fff : ((s32) < -0x8000 ? -0x8000 : (s32)))
107
108 /* ...mixer preinitialization (default parameters) */
xa_mixer_preinit(XAPcmMixer * d)109 static inline void xa_mixer_preinit(XAPcmMixer *d)
110 {
111 u32 i;
112
113 /* ...pre-configuration initialization; reset internal data */
114 memset(d, 0, sizeof(*d));
115
116 /* ...set default parameters */
117 d->pcm_width = 16, d->channels = 2, d->frame_size = 512;
118
119 /* ...set default volumes (last index is a master volume)*/
120 for (i = 0; i <= XA_MIXER_MAX_TRACK_NUMBER; i++)
121 {
122 d->volume[i] = ((1 << 12) << 16) | (1 << 12);
123 }
124 }
125
126 /* ...do mixing of stereo PCM-16 streams */
xa_mixer_do_execute_stereo_16bit(XAPcmMixer * d)127 static XA_ERRORCODE xa_mixer_do_execute_stereo_16bit(XAPcmMixer *d)
128 {
129 s16 *output = d->output;
130 s16 *b[XA_MIXER_MAX_TRACK_NUMBER];
131 u16 v_l[XA_MIXER_MAX_TRACK_NUMBER];
132 u16 v_r[XA_MIXER_MAX_TRACK_NUMBER];
133 u16 w_l, w_r;
134 u32 t32;
135 u32 i, j;
136
137 /* ...retrieve master volume - assume up to 24dB amplifying (4 bits) */
138 t32 = d->volume[XA_MIXER_MAX_TRACK_NUMBER];
139 w_l = (u16)(t32 & 0xFFFF), w_r = (u16)(t32 >> 16);
140
141 /* ...prepare individual tracks */
142 for (j = 0; j < XA_MIXER_MAX_TRACK_NUMBER; j++)
143 {
144 u32 n = d->input_length[j];
145
146 /* ...check if we have input buffer available */
147 if (n == 0)
148 {
149 /* ...output silence (multiply garbage in the scratch buffer by 0) */
150 b[j] = d->scratch;
151 v_l[j] = v_r[j] = 0;
152 }
153 else
154 {
155 s32 k = (s32)(d->buffer_size - n);
156
157 /* ...put input buffer */
158 XF_CHK_ERR(b[j] = d->input[j], XA_MIXER_EXEC_FATAL_INPUT);
159
160 /* ...if length is not sufficient, pad buffer remainder */
161 (k > 0 ? memset((void *)b[j] + n, 0x00, k) : 0);
162
163 /* ...set individual track volume/balance */
164 t32 = d->volume[j];
165 v_l[j] = (u16)(t32 & 0xFFFF), v_r[j] = (u16)(t32 >> 16);
166 }
167
168 TRACE(PROCESS, _b("b[%u] = %p%s"), j, b[j], (n == 0 ? " - scratch" : ""));
169 }
170
171 /* ...process all tracks */
172 for (i = 0; i < d->frame_size; i++)
173 {
174 s32 l32 = 0, r32 = 0;
175
176 /* ...fill-in every channel in our map (unrolls loop here) */
177 for (j = 0; j < XA_MIXER_MAX_TRACK_NUMBER; j++)
178 {
179 /* ...left channel processing (no saturation here yet) */
180 l32 += *b[j]++ * v_l[j];
181
182 /* ...right channel processing */
183 r32 += *b[j]++ * v_r[j];
184 }
185
186 /* ...normalize (truncate towards -inf) and multiply by master volume */
187 l32 = ((l32 >> 12) * w_l) >> 12;
188 r32 = ((r32 >> 12) * w_r) >> 12;
189
190 /* ...saturate and store in buffer */
191 *output++ = DSP_SATURATE_S16(l32);
192 *output++ = DSP_SATURATE_S16(r32);
193 }
194
195 /* ...save total number of produced bytes */
196 d->produced = (u32)((void *)output - d->output);
197
198 /* ...put flag saying we have output buffer */
199 d->state |= XA_MIXER_FLAG_OUTPUT;
200
201 TRACE(PROCESS, _b("produced: %u bytes (%u samples)"), d->produced, d->frame_size);
202
203 /* ...reset input buffer length? */
204 //memset(d->input_length, 0, sizeof(d->input_length));
205
206 /* ...return success result code */
207 return XA_NO_ERROR;
208 }
209
210 /* ...runtime reset */
xa_mixer_do_runtime_init(XAPcmMixer * d)211 static XA_ERRORCODE xa_mixer_do_runtime_init(XAPcmMixer *d)
212 {
213 /* ...no special processing is needed here */
214 return XA_NO_ERROR;
215 }
216
217 /*******************************************************************************
218 * Commands processing
219 ******************************************************************************/
220
221 /* ...codec API size query */
xa_mixer_get_api_size(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)222 static XA_ERRORCODE xa_mixer_get_api_size(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
223 {
224 /* ...check parameters are sane */
225 XF_CHK_ERR(pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
226
227 /* ...retrieve API structure size */
228 *(WORD32 *)pv_value = sizeof(*d);
229
230 return XA_NO_ERROR;
231 }
232
233 /* ...standard codec initialization routine */
xa_mixer_init(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)234 static XA_ERRORCODE xa_mixer_init(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
235 {
236 /* ...sanity check - mixer must be valid */
237 XF_CHK_ERR(d, XA_API_FATAL_INVALID_CMD_TYPE);
238
239 /* ...process particular initialization type */
240 switch (i_idx)
241 {
242 case XA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS:
243 {
244 /* ...pre-configuration initialization; reset internal data */
245 xa_mixer_preinit(d);
246
247 /* ...and mark mixer has been created */
248 d->state = XA_MIXER_FLAG_PREINIT_DONE;
249
250 return XA_NO_ERROR;
251 }
252
253 case XA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS:
254 {
255 /* ...post-configuration initialization (all parameters are set) */
256 XF_CHK_ERR(d->state & XA_MIXER_FLAG_PREINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
257
258 /* ...calculate input/output buffer size in bytes */
259 d->buffer_size = d->channels * d->frame_size * (d->pcm_width == 16 ? sizeof(s16) : sizeof(s32));
260
261 /* ...mark post-initialization is complete */
262 d->state |= XA_MIXER_FLAG_POSTINIT_DONE;
263
264 return XA_NO_ERROR;
265 }
266
267 case XA_CMD_TYPE_INIT_PROCESS:
268 {
269 /* ...kick run-time initialization process; make sure mixer is setup */
270 XF_CHK_ERR(d->state & XA_MIXER_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
271
272 /* ...enter into execution stage */
273 d->state |= XA_MIXER_FLAG_RUNNING;
274
275 return XA_NO_ERROR;
276 }
277
278 case XA_CMD_TYPE_INIT_DONE_QUERY:
279 {
280 /* ...check if initialization is done; make sure pointer is sane */
281 XF_CHK_ERR(pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
282
283 /* ...put current status */
284 *(WORD32 *)pv_value = (d->state & XA_MIXER_FLAG_RUNNING ? 1 : 0);
285
286 return XA_NO_ERROR;
287 }
288
289 default:
290 /* ...unrecognized command type */
291 TRACE(ERROR, _x("Unrecognized command type: %X"), i_idx);
292 return XA_API_FATAL_INVALID_CMD_TYPE;
293 }
294 }
295
296 /* ...set mixer configuration parameter */
xa_mixer_set_config_param(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)297 static XA_ERRORCODE xa_mixer_set_config_param(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
298 {
299 u32 i_value;
300
301 /* ...sanity check - mixer pointer must be sane */
302 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
303
304 /* ...pre-initialization must be completed, mixer must be idle */
305 XF_CHK_ERR(d->state & XA_MIXER_FLAG_PREINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
306
307 /* ...get parameter value */
308 i_value = (u32) *(WORD32 *)pv_value;
309
310 /* ...process individual configuration parameter */
311 switch (i_idx)
312 {
313 case XA_MIXER_CONFIG_PARAM_PCM_WIDTH:
314 /* ...check value is permitted (16 bits only) */
315 XF_CHK_ERR(i_value == 16, XA_MIXER_CONFIG_NONFATAL_RANGE);
316 d->pcm_width = (u32)i_value;
317 return XA_NO_ERROR;
318
319 case XA_MIXER_CONFIG_PARAM_CHANNELS:
320 /* ...allow stereo only */
321 XF_CHK_ERR(i_value == 2, XA_MIXER_CONFIG_NONFATAL_RANGE);
322 d->channels = (u32)i_value;
323 return XA_NO_ERROR;
324
325 case XA_MIXER_CONFIG_PARAM_SAMPLE_RATE:
326 /* ...set mixer sample rate */
327 d->sample_rate = (u32)i_value;
328 return XA_NO_ERROR;
329
330 default:
331 TRACE(ERROR, _x("Invalid parameter: %X"), i_idx);
332 return XA_API_FATAL_INVALID_CMD_TYPE;
333 }
334 }
335
336 /* ...retrieve configuration parameter */
xa_mixer_get_config_param(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)337 static XA_ERRORCODE xa_mixer_get_config_param(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
338 {
339 /* ...sanity check - mixer must be initialized */
340 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
341
342 /* ...make sure pre-initialization is completed */
343 XF_CHK_ERR(d->state & XA_MIXER_FLAG_PREINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
344
345 /* ...process individual configuration parameter */
346 switch (i_idx)
347 {
348 case XA_MIXER_CONFIG_PARAM_INPUT_TRACKS:
349 /* ...return maximal number of input tracks supported */
350 *(WORD32 *)pv_value = XA_MIXER_MAX_TRACK_NUMBER;
351 return XA_NO_ERROR;
352
353 case XA_MIXER_CONFIG_PARAM_SAMPLE_RATE:
354 /* ...return mixer sample rate */
355 *(WORD32 *)pv_value = d->sample_rate;
356 return XA_NO_ERROR;
357
358 case XA_MIXER_CONFIG_PARAM_PCM_WIDTH:
359 /* ...return current PCM width */
360 *(WORD32 *)pv_value = d->pcm_width;
361 return XA_NO_ERROR;
362
363 case XA_MIXER_CONFIG_PARAM_CHANNELS:
364 /* ...return current channel number */
365 *(WORD32 *)pv_value = d->channels;
366 return XA_NO_ERROR;
367
368 case XA_MIXER_CONFIG_PARAM_FRAME_SIZE:
369 /* ...return current in/out frame length (in samples) */
370 *(WORD32 *)pv_value = d->frame_size;
371 return XA_NO_ERROR;
372
373 case XA_MIXER_CONFIG_PARAM_BUFFER_SIZE:
374 /* ...return current in/out frame length (in bytes) */
375 *(WORD32 *)pv_value = d->buffer_size;
376 return XA_NO_ERROR;
377
378 default:
379 TRACE(ERROR, _x("Invalid parameter: %X"), i_idx);
380 return XA_API_FATAL_INVALID_CMD_TYPE;
381 }
382 }
383
384 /* ...execution command */
xa_mixer_execute(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)385 static XA_ERRORCODE xa_mixer_execute(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
386 {
387 /* ...sanity check - mixer must be valid */
388 XF_CHK_ERR(d, XA_API_FATAL_INVALID_CMD_TYPE);
389
390 /* ...mixer must be in running state */
391 XF_CHK_ERR(d->state & XA_MIXER_FLAG_RUNNING, XA_API_FATAL_INVALID_CMD_TYPE);
392
393 /* ...process individual command type */
394 switch (i_idx)
395 {
396 case XA_CMD_TYPE_DO_EXECUTE:
397 /* ...perform mixing of the channels */
398 return xa_mixer_do_execute_stereo_16bit(d);
399
400 case XA_CMD_TYPE_DONE_QUERY:
401 /* ...check if processing is complete */
402 XF_CHK_ERR(pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
403 *(WORD32 *)pv_value = (d->state & XA_MIXER_FLAG_COMPLETE ? 1 : 0);
404 return XA_NO_ERROR;
405
406 case XA_CMD_TYPE_DO_RUNTIME_INIT:
407 /* ...reset mixer operation */
408 return xa_mixer_do_runtime_init(d);
409
410 default:
411 /* ...unrecognized command */
412 TRACE(ERROR, _x("Invalid index: %X"), i_idx);
413 return XA_API_FATAL_INVALID_CMD_TYPE;
414 }
415 }
416
417 /* ...set number of input bytes */
xa_mixer_set_input_bytes(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)418 static XA_ERRORCODE xa_mixer_set_input_bytes(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
419 {
420 u32 size;
421
422 /* ...sanity check - check parameters */
423 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
424
425 /* ...track index must be valid */
426 XF_CHK_ERR(i_idx >= 0 && i_idx < XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE);
427
428 /* ...mixer must be initialized */
429 XF_CHK_ERR(d->state & XA_MIXER_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
430
431 /* ...input buffer must exist */
432 XF_CHK_ERR(d->input[i_idx], XA_API_FATAL_INVALID_CMD_TYPE);
433
434 /* ...input frame length should not be zero (in bytes) */
435 XF_CHK_ERR((size = (u32)*(WORD32 *)pv_value) > 0, XA_MIXER_EXEC_NONFATAL_INPUT);
436
437 /* ...all is correct; set input buffer length in bytes */
438 d->input_length[i_idx] = size;
439
440 return XA_NO_ERROR;
441 }
442
443 /* ...get number of output bytes */
xa_mixer_get_output_bytes(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)444 static XA_ERRORCODE xa_mixer_get_output_bytes(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
445 {
446 /* ...sanity check - check parameters */
447 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
448
449 /* ...track index must be zero */
450 XF_CHK_ERR(i_idx == XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE);
451
452 /* ...mixer must be running */
453 XF_CHK_ERR(d->state & XA_MIXER_FLAG_RUNNING, XA_API_FATAL_INVALID_CMD_TYPE);
454
455 /* ...output buffer must exist */
456 XF_CHK_ERR(d->output, XA_MIXER_EXEC_NONFATAL_OUTPUT);
457
458 /* ...return number of produced bytes */
459 *(WORD32 *)pv_value = (d->state & XA_MIXER_FLAG_OUTPUT ? d->buffer_size : 0);
460
461 return XA_NO_ERROR;
462 }
463
464 /* ...get number of consumed bytes */
xa_mixer_get_curidx_input_buf(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)465 static XA_ERRORCODE xa_mixer_get_curidx_input_buf(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
466 {
467 /* ...sanity check - check parameters */
468 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
469
470 /* ...track index must be valid */
471 XF_CHK_ERR(i_idx >= 0 && i_idx < XA_MIXER_MAX_TRACK_NUMBER, XA_API_FATAL_INVALID_CMD_TYPE);
472
473 /* ...mixer must be running */
474 XF_CHK_ERR(d->state & XA_MIXER_FLAG_RUNNING, XA_MIXER_EXEC_FATAL_STATE);
475
476 /* ...input buffer must exist */
477 XF_CHK_ERR(d->input[i_idx], XA_MIXER_EXEC_FATAL_INPUT);
478
479 /* ...return number of bytes consumed (always consume fixed-length chunk) */
480 *(WORD32 *)pv_value = d->input_length[i_idx], d->input_length[i_idx] = 0;
481
482 return XA_NO_ERROR;
483 }
484
485 /*******************************************************************************
486 * Memory information API
487 ******************************************************************************/
488
489 /* ..get total amount of data for memory tables */
xa_mixer_get_memtabs_size(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)490 static XA_ERRORCODE xa_mixer_get_memtabs_size(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
491 {
492 /* ...basic sanity checks */
493 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
494
495 /* ...check mixer is pre-initialized */
496 XF_CHK_ERR(d->state & XA_MIXER_FLAG_PREINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
497
498 /* ...we have all our tables inside API structure - good? tbd */
499 *(WORD32 *)pv_value = 0;
500
501 return XA_NO_ERROR;
502 }
503
504 /* ..set memory tables pointer */
xa_mixer_set_memtabs_ptr(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)505 static XA_ERRORCODE xa_mixer_set_memtabs_ptr(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
506 {
507 /* ...basic sanity checks */
508 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
509
510 /* ...check mixer is pre-initialized */
511 XF_CHK_ERR(d->state & XA_MIXER_FLAG_PREINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
512
513 /* ...do not do anything; just return success - tbd */
514 return XA_NO_ERROR;
515 }
516
517 /* ...return total amount of memory buffers */
xa_mixer_get_n_memtabs(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)518 static XA_ERRORCODE xa_mixer_get_n_memtabs(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
519 {
520 /* ...basic sanity checks */
521 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
522
523 /* ...we have N input buffers, 1 output buffer and 1 scratch buffer */
524 *(WORD32 *)pv_value = XA_MIXER_MAX_TRACK_NUMBER + 1 + 1;
525
526 return XA_NO_ERROR;
527 }
528
529 /* ...return memory buffer data */
xa_mixer_get_mem_info_size(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)530 static XA_ERRORCODE xa_mixer_get_mem_info_size(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
531 {
532 /* ...basic sanity check */
533 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
534
535 /* ...return frame buffer minimal size only after post-initialization is done */
536 XF_CHK_ERR(d->state & XA_MIXER_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
537
538 /* ...all buffers are of the same length */
539 *(WORD32 *)pv_value = (WORD32) d->buffer_size;
540
541 return XA_NO_ERROR;
542 }
543
544 /* ...return memory alignment data */
xa_mixer_get_mem_info_alignment(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)545 static XA_ERRORCODE xa_mixer_get_mem_info_alignment(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
546 {
547 /* ...basic sanity check */
548 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
549
550 /* ...return frame buffer minimal size only after post-initialization is done */
551 XF_CHK_ERR(d->state & XA_MIXER_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
552
553 /* ...all buffers are 4-bytes aligned */
554 *(WORD32 *)pv_value = 4;
555
556 return XA_NO_ERROR;
557 }
558
559 /* ...return memory type data */
xa_mixer_get_mem_info_type(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)560 static XA_ERRORCODE xa_mixer_get_mem_info_type(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
561 {
562 /* ...basic sanity check */
563 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
564
565 /* ...return frame buffer minimal size only after post-initialization is done */
566 XF_CHK_ERR(d->state & XA_MIXER_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
567
568 switch (i_idx)
569 {
570 case 0 ... XA_MIXER_MAX_TRACK_NUMBER - 1:
571 /* ...input buffers */
572 *(WORD32 *)pv_value = XA_MEMTYPE_INPUT;
573 return XA_NO_ERROR;
574
575 case XA_MIXER_MAX_TRACK_NUMBER:
576 /* ...output buffer */
577 *(WORD32 *)pv_value = XA_MEMTYPE_OUTPUT;
578 return XA_NO_ERROR;
579
580 case XA_MIXER_MAX_TRACK_NUMBER + 1:
581 /* ...scratch buffer */
582 *(WORD32 *)pv_value = XA_MEMTYPE_SCRATCH;
583 return XA_NO_ERROR;
584
585 default:
586 /* ...invalid index */
587 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
588 }
589 }
590
591 /* ...set memory pointer */
xa_mixer_set_mem_ptr(XAPcmMixer * d,WORD32 i_idx,pVOID pv_value)592 static XA_ERRORCODE xa_mixer_set_mem_ptr(XAPcmMixer *d, WORD32 i_idx, pVOID pv_value)
593 {
594 /* ...basic sanity check */
595 XF_CHK_ERR(d && pv_value, XA_API_FATAL_INVALID_CMD_TYPE);
596
597 /* ...codec must be initialized */
598 XF_CHK_ERR(d->state & XA_MIXER_FLAG_POSTINIT_DONE, XA_API_FATAL_INVALID_CMD_TYPE);
599
600 /* ...select memory buffer */
601 switch (i_idx)
602 {
603 case 0 ... XA_MIXER_MAX_TRACK_NUMBER - 1:
604 /* ...input buffers */
605 d->input[i_idx] = pv_value;
606 return XA_NO_ERROR;
607
608 case XA_MIXER_MAX_TRACK_NUMBER:
609 /* ...output buffer */
610 d->output = pv_value;
611 return XA_NO_ERROR;
612
613 case XA_MIXER_MAX_TRACK_NUMBER + 1:
614 /* ...scratch buffer */
615 d->scratch = pv_value;
616 return XA_NO_ERROR;
617
618 default:
619 /* ...invalid index */
620 return XF_CHK_ERR(0, XA_API_FATAL_INVALID_CMD_TYPE);
621 }
622 }
623
624 /*******************************************************************************
625 * API command hooks
626 ******************************************************************************/
627
628 static XA_ERRORCODE (* const xa_mixer_api[])(XAPcmMixer *, WORD32, pVOID) =
629 {
630 [XA_API_CMD_GET_API_SIZE] = xa_mixer_get_api_size,
631
632 [XA_API_CMD_INIT] = xa_mixer_init,
633 [XA_API_CMD_SET_CONFIG_PARAM] = xa_mixer_set_config_param,
634 [XA_API_CMD_GET_CONFIG_PARAM] = xa_mixer_get_config_param,
635
636 [XA_API_CMD_EXECUTE] = xa_mixer_execute,
637 [XA_API_CMD_SET_INPUT_BYTES] = xa_mixer_set_input_bytes,
638 [XA_API_CMD_GET_OUTPUT_BYTES] = xa_mixer_get_output_bytes,
639 [XA_API_CMD_GET_CURIDX_INPUT_BUF] = xa_mixer_get_curidx_input_buf,
640
641 [XA_API_CMD_GET_MEMTABS_SIZE] = xa_mixer_get_memtabs_size,
642 [XA_API_CMD_SET_MEMTABS_PTR] = xa_mixer_set_memtabs_ptr,
643 [XA_API_CMD_GET_N_MEMTABS] = xa_mixer_get_n_memtabs,
644 [XA_API_CMD_GET_MEM_INFO_SIZE] = xa_mixer_get_mem_info_size,
645 [XA_API_CMD_GET_MEM_INFO_ALIGNMENT] = xa_mixer_get_mem_info_alignment,
646 [XA_API_CMD_GET_MEM_INFO_TYPE] = xa_mixer_get_mem_info_type,
647 [XA_API_CMD_SET_MEM_PTR] = xa_mixer_set_mem_ptr,
648 };
649
650 /* ...total numer of commands supported */
651 #define XA_MIXER_API_COMMANDS_NUM (sizeof(xa_mixer_api) / sizeof(xa_mixer_api[0]))
652
653 /*******************************************************************************
654 * API entry point
655 ******************************************************************************/
656
xa_mixer(xa_codec_handle_t p_xa_module_obj,WORD32 i_cmd,WORD32 i_idx,pVOID pv_value)657 XA_ERRORCODE xa_mixer(xa_codec_handle_t p_xa_module_obj, WORD32 i_cmd, WORD32 i_idx, pVOID pv_value)
658 {
659 XAPcmMixer *d = (XAPcmMixer *) p_xa_module_obj;
660
661 /* ...check if command index is sane */
662 XF_CHK_ERR(i_cmd < XA_MIXER_API_COMMANDS_NUM, XA_API_FATAL_INVALID_CMD);
663
664 /* ...see if command is defined */
665 XF_CHK_ERR(xa_mixer_api[i_cmd], XA_API_FATAL_INVALID_CMD);
666
667 /* ...execute requested command */
668 return xa_mixer_api[i_cmd](d, i_idx, pv_value);
669 }
670