Home | History | Annotate | Download | only in decoder
      1 /******************************************************************************
      2  *                                                                            *
      3  * Copyright (C) 2018 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at:
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  *****************************************************************************
     18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
     19 */
     20 #include <math.h>
     21 #include <string.h>
     22 #include <ixheaacd_type_def.h>
     23 #include "ixheaacd_bitbuffer.h"
     24 #include "ixheaacd_config.h"
     25 
     26 #include "ixheaacd_mps_polyphase.h"
     27 #include "ixheaacd_mps_dec.h"
     28 #include "ixheaacd_mps_interface.h"
     29 
     30 #include "ixheaacd_mps_polyphase.h"
     31 
     32 #include "ixheaacd_mps_hybfilter.h"
     33 
     34 extern WORD32 ixheaacd_ia_mps_hyb_filter_coeff_8[QMF_HYBRID_FILT_ORDER];
     35 extern WORD32 ixheaacd_mps_hyb_filter_coeff_2[QMF_HYBRID_FILT_ORDER];
     36 extern WORD32 ixheaacd_cosine[8][13];
     37 extern WORD32 ixheaacd_sine[8][13];
     38 extern WORD32 ixheaacd_cosine2[2][13];
     39 
     40 static WORD32 ixheaacd_mps_mult32_local(WORD32 a, WORD32 b, WORD16 shift) {
     41   WORD64 temp;
     42 
     43   temp = (WORD64)a * (WORD64)b;
     44   temp = temp >> shift;
     45   return (WORD32)temp;
     46 }
     47 
     48 static VOID ixheaacd_mps_hyb_filt_type1(
     49     ia_cmplx_w32_struct *input, ia_cmplx_w32_struct output[8][MAX_TIME_SLOTS],
     50     WORD32 num_samples, WORD32 *filt_coeff)
     51 
     52 {
     53   WORD32 i, n, q;
     54 
     55   WORD32 modulation_fac_re, modulation_fac_im;
     56   WORD32 in_re, in_im;
     57   WORD32 temp;
     58   WORD32 coeff;
     59   WORD64 acc_re, acc_im;
     60 
     61   WORD16 shift = 8;
     62 
     63   for (i = 0; i < num_samples; i++) {
     64     for (q = 0; q < 8; q++) {
     65       acc_re = 0;
     66       acc_im = 0;
     67       for (n = 0; n < QMF_HYBRID_FILT_ORDER; n++) {
     68         modulation_fac_re = ixheaacd_cosine[q][n];
     69         modulation_fac_im = ixheaacd_sine[q][n];
     70 
     71         in_re = (WORD32)(input[n + i].re);
     72         in_im = (WORD32)(input[n + i].im);
     73 
     74         in_re = in_re << shift;
     75         in_im = in_im << shift;
     76 
     77         coeff = filt_coeff[QMF_HYBRID_FILT_ORDER - 1 - n];
     78 
     79         temp = ixheaacd_mps_mult32_local(in_re, modulation_fac_re, 30) -
     80                ixheaacd_mps_mult32_local(in_im, modulation_fac_im, 30);
     81 
     82         if (temp >= 1073741823)
     83           temp = 1073741823;
     84         else if (temp <= -1073741824)
     85           temp = -1073741824;
     86 
     87         temp = ixheaacd_mps_mult32_local(coeff, temp, 30);
     88         acc_re = acc_re + (WORD64)temp;
     89 
     90         temp = ixheaacd_mps_mult32_local(in_im, modulation_fac_re, 30) +
     91                ixheaacd_mps_mult32_local(in_re, modulation_fac_im, 30);
     92 
     93         if (temp >= 1073741823)
     94           temp = 1073741823;
     95         else if (temp <= -1073741824)
     96           temp = -1073741824;
     97 
     98         temp = ixheaacd_mps_mult32_local(coeff, temp, 30);
     99         acc_im = acc_im + (WORD64)temp;
    100       }
    101 
    102       output[q][i].re = (WORD32)(acc_re >> shift);
    103       output[q][i].im = (WORD32)(acc_im >> shift);
    104     }
    105   }
    106 }
    107 
    108 static VOID ixheaacd_mps_hyb_filt_type2(
    109     ia_cmplx_w32_struct *input, ia_cmplx_w32_struct output[2][MAX_TIME_SLOTS],
    110     WORD32 num_samples, WORD32 *filt_coeff)
    111 
    112 {
    113   WORD32 i, n, q;
    114 
    115   WORD32 modulation_fac_re;
    116   WORD32 in_re, in_im;
    117   WORD32 temp;
    118   WORD32 coeff;
    119   WORD64 acc_re, acc_im;
    120 
    121   WORD16 shift = 8;
    122 
    123   for (i = 0; i < num_samples; i++) {
    124     for (q = 0; q < 2; q++) {
    125       acc_re = 0;
    126       acc_im = 0;
    127       for (n = 0; n < QMF_HYBRID_FILT_ORDER; n++) {
    128         modulation_fac_re = ixheaacd_cosine2[q][n];
    129 
    130         in_re = (WORD32)(input[n + i].re);
    131         in_im = (WORD32)(input[n + i].im);
    132 
    133         in_re = in_re << shift;
    134         in_im = in_im << shift;
    135 
    136         coeff = filt_coeff[QMF_HYBRID_FILT_ORDER - 1 - n];
    137 
    138         temp = ixheaacd_mps_mult32_local(in_re, modulation_fac_re, 30);
    139 
    140         if (temp >= 1073741823)
    141           temp = 1073741823;
    142         else if (temp <= -1073741824)
    143           temp = -1073741824;
    144 
    145         temp = ixheaacd_mps_mult32_local(coeff, temp, 30);
    146         acc_re = acc_re + (WORD64)temp;
    147 
    148         temp = ixheaacd_mps_mult32_local(in_im, modulation_fac_re, 30);
    149 
    150         if (temp >= 1073741823)
    151           temp = 1073741823;
    152         else if (temp <= -1073741824)
    153           temp = -1073741824;
    154 
    155         temp = ixheaacd_mps_mult32_local(coeff, temp, 30);
    156         acc_im = acc_im + (WORD64)temp;
    157       }
    158 
    159       output[q][i].re = (WORD32)(acc_re >> shift);
    160       output[q][i].im = (WORD32)(acc_im >> shift);
    161     }
    162   }
    163 }
    164 
    165 VOID ixheaacd_mps_qmf_hybrid_analysis_init(ia_mps_hybrid_filt_struct *handle) {
    166   memset(handle->lf_buffer, 0,
    167          QMF_BANDS_TO_HYBRID * BUFFER_LEN_LF_MPS * sizeof(ia_cmplx_w32_struct));
    168   memset(handle->hf_buffer, 0, MAX_NUM_QMF_BANDS_MPS * BUFFER_LEN_HF_MPS *
    169                                    sizeof(ia_cmplx_flt_struct));
    170 }
    171 
    172 VOID ixheaacd_mps_qmf_hybrid_analysis(
    173     ia_mps_hybrid_filt_struct *handle,
    174     ia_cmplx_flt_struct in_qmf[MAX_TIME_SLOTS][MAX_NUM_QMF_BANDS_MPS_NEW],
    175     WORD32 num_bands, WORD32 num_samples,
    176     ia_cmplx_flt_struct hyb[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS]) {
    177   WORD32 lf_samples_shift;
    178   WORD32 hf_samples_shift;
    179   WORD32 lf_qmf_bands;
    180   WORD32 k, n;
    181 
    182   ia_cmplx_w32_struct scratch[MAX_HYBRID_ONLY_BANDS_PER_QMF][MAX_TIME_SLOTS];
    183 
    184   lf_samples_shift = BUFFER_LEN_LF_MPS - num_samples;
    185   hf_samples_shift = BUFFER_LEN_HF_MPS - num_samples;
    186 
    187   lf_qmf_bands = QMF_BANDS_TO_HYBRID;
    188 
    189   for (k = 0; k < lf_qmf_bands; k++) {
    190     for (n = 0; n < lf_samples_shift; n++) {
    191       handle->lf_buffer[k][n].re = handle->lf_buffer[k][n + num_samples].re;
    192       handle->lf_buffer[k][n].im = handle->lf_buffer[k][n + num_samples].im;
    193     }
    194   }
    195 
    196   for (k = 0; k < lf_qmf_bands; k++) {
    197     for (n = 0; n < num_samples; n++) {
    198       handle->lf_buffer[k][n + lf_samples_shift].re = (WORD32)(in_qmf[n][k].re);
    199       handle->lf_buffer[k][n + lf_samples_shift].im = (WORD32)(in_qmf[n][k].im);
    200     }
    201   }
    202 
    203   for (k = 0; k < num_bands - lf_qmf_bands; k++) {
    204     for (n = 0; n < hf_samples_shift; n++) {
    205       handle->hf_buffer[k][n].re = handle->hf_buffer[k][n + num_samples].re;
    206       handle->hf_buffer[k][n].im = handle->hf_buffer[k][n + num_samples].im;
    207     }
    208   }
    209 
    210   for (k = 0; k < num_bands - lf_qmf_bands; k++) {
    211     for (n = 0; n < num_samples; n++) {
    212       handle->hf_buffer[k][n + hf_samples_shift].re =
    213           (in_qmf[n][k + lf_qmf_bands].re);
    214       handle->hf_buffer[k][n + hf_samples_shift].im =
    215           (in_qmf[n][k + lf_qmf_bands].im);
    216     }
    217   }
    218 
    219   ixheaacd_mps_hyb_filt_type1(
    220       &(handle->lf_buffer[0][lf_samples_shift + 1 - QMF_HYBRID_FILT_ORDER]),
    221       scratch, num_samples, ixheaacd_ia_mps_hyb_filter_coeff_8);
    222 
    223   for (k = 0; k < 2; k++) {
    224     for (n = 0; n < num_samples; n++) {
    225       hyb[n][k].re = (FLOAT32)scratch[k + 6][n].re;
    226       hyb[n][k + 2].re = (FLOAT32)scratch[k][n].re;
    227       hyb[n][k + 4].re = (FLOAT32)scratch[k + 2][n].re;
    228       hyb[n][k + 4].re += (FLOAT32)scratch[5 - k][n].re;
    229 
    230       hyb[n][k].im = (FLOAT32)scratch[k + 6][n].im;
    231       hyb[n][k + 2].im = (FLOAT32)scratch[k][n].im;
    232       hyb[n][k + 4].im = (FLOAT32)scratch[k + 2][n].im;
    233       hyb[n][k + 4].im += (FLOAT32)scratch[5 - k][n].im;
    234     }
    235   }
    236 
    237   ixheaacd_mps_hyb_filt_type2(
    238       &(handle->lf_buffer[1][lf_samples_shift + 1 - QMF_HYBRID_FILT_ORDER]),
    239       scratch, num_samples, ixheaacd_mps_hyb_filter_coeff_2);
    240 
    241   for (k = 0; k < 2; k++) {
    242     for (n = 0; n < num_samples; n++) {
    243       hyb[n][k + 6].re = (FLOAT32)scratch[1 - k][n].re;
    244       hyb[n][k + 6].im = (FLOAT32)scratch[1 - k][n].im;
    245     }
    246   }
    247 
    248   ixheaacd_mps_hyb_filt_type2(
    249       &(handle->lf_buffer[2][lf_samples_shift + 1 - QMF_HYBRID_FILT_ORDER]),
    250       scratch, num_samples, ixheaacd_mps_hyb_filter_coeff_2);
    251 
    252   for (k = 0; k < 2; k++) {
    253     for (n = 0; n < num_samples; n++) {
    254       hyb[n][k + 8].re = (FLOAT32)scratch[k][n].re;
    255       hyb[n][k + 8].im = (FLOAT32)scratch[k][n].im;
    256     }
    257   }
    258 
    259   for (k = 0; k < num_bands - lf_qmf_bands; k++) {
    260     for (n = 0; n < num_samples; n++) {
    261       hyb[n][k + 10].re = (handle->hf_buffer[k][n + hf_samples_shift].re);
    262       hyb[n][k + 10].im = (handle->hf_buffer[k][n + hf_samples_shift].im);
    263     }
    264   }
    265 }
    266 
    267 VOID ixheaacd_mps_qmf_hybrid_synthesis(
    268     ia_cmplx_flt_struct hyb[MAX_TIME_SLOTS][MAX_HYBRID_BANDS_MPS],
    269     WORD32 num_bands, WORD32 num_samples,
    270     ia_cmplx_flt_struct in_qmf[MAX_TIME_SLOTS][MAX_NUM_QMF_BANDS_MPS]) {
    271   WORD32 k, n;
    272 
    273   for (n = 0; n < num_samples; n++) {
    274     in_qmf[n][0].re = hyb[n][0].re;
    275     in_qmf[n][0].im = hyb[n][0].im;
    276 
    277     for (k = 1; k < 6; k++) {
    278       in_qmf[n][0].re += hyb[n][k].re;
    279       in_qmf[n][0].im += hyb[n][k].im;
    280     }
    281 
    282     in_qmf[n][1].re = hyb[n][6].re + hyb[n][7].re;
    283     in_qmf[n][1].im = hyb[n][6].im + hyb[n][7].im;
    284 
    285     in_qmf[n][2].re = hyb[n][8].re + hyb[n][9].re;
    286     in_qmf[n][2].im = hyb[n][8].im + hyb[n][9].im;
    287 
    288     for (k = 3; k < num_bands; k++) {
    289       in_qmf[n][k].re = hyb[n][k - 3 + 10].re;
    290       in_qmf[n][k].im = hyb[n][k - 3 + 10].im;
    291     }
    292   }
    293 }
    294