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) */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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