Home | History | Annotate | Download | only in mixer
      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