pvmp3_alias_reduction.cpp 8.14 KB
/* ------------------------------------------------------------------
 * Copyright (C) 1998-2009 PacketVideo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 * -------------------------------------------------------------------
 */
/*
------------------------------------------------------------------------------

   PacketVideo Corp.
   MP3 Decoder Library

   Filename: pvmp3_alias_reduction.cpp

     Date: 09/21/2007

------------------------------------------------------------------------------
 REVISION HISTORY


 Description:

------------------------------------------------------------------------------
 INPUT AND OUTPUT DEFINITIONS

Input
    int32 *input_buffer,          Ptr to fequency lines of current channel
    struct gr_info_s *gr_info,    structure with granuke information for the
                                  input
    mp3Header *info               mp3 header information

------------------------------------------------------------------------------
 FUNCTION DESCRIPTION

    Alias Reduction



    Alias reduction before processing by the IMDCT

                   Csi  +
     >---------0---------0-------->
                \       / -
             Cai \     /
                  \   /
                   \ /
                    \
                  /  \
             Cai /    \
               /       \  +
     >--------0---------0---------->
                  Csi  +

      Aliasing Butterfly
      Alias reduction is not applied to short blocks

------------------------------------------------------------------------------
 REQUIREMENTS


------------------------------------------------------------------------------
 REFERENCES

 [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
     ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension

------------------------------------------------------------------------------
 PSEUDO-CODE
                1                                ci
  csi = ----------------           csi = ----------------
        sqrt( 1 + (ci^2))                sqrt( 1 + (ci^2))


  ci = -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037

 ------------------------------------------------------------------------------
*/


/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/

#include "pvmp3_alias_reduction.h"
#include "pv_mp3dec_fxd_op.h"


/*----------------------------------------------------------------------------
; MACROS
; Define module specific macros here
----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------
; DEFINES
; Include all pre-processor statements here. Include conditional
; compile variables also.
----------------------------------------------------------------------------*/
#define NUM_BUTTERFLIES 8

#define Q31_fmt(a)    (int32(double(0x7FFFFFFF)*a))

/*----------------------------------------------------------------------------
; LOCAL FUNCTION DEFINITIONS
; Function Prototype declaration
----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
; LOCAL STORE/BUFFER/POINTER DEFINITIONS
; Variable declaration - defined here and used outside this module
----------------------------------------------------------------------------*/
const int32 c_signal [ NUM_BUTTERFLIES ] =
{

    Q31_fmt(0.85749292571254f), Q31_fmt(0.88174199731771f),
    Q31_fmt(0.94962864910273f), Q31_fmt(0.98331459249179f),
    Q31_fmt(0.99551781606759f), Q31_fmt(0.99916055817815f),
    Q31_fmt(0.99989919524445f), Q31_fmt(0.99999315507028f)

};


const int32 c_alias [ NUM_BUTTERFLIES ] =
{

    Q31_fmt(-0.51449575542753f), Q31_fmt(-0.47173196856497f),
    Q31_fmt(-0.31337745420390f), Q31_fmt(-0.18191319961098f),
    Q31_fmt(-0.09457419252642f), Q31_fmt(-0.04096558288530f),
    Q31_fmt(-0.01419856857247f), Q31_fmt(-0.00369997467376f)
};

/*----------------------------------------------------------------------------
; EXTERNAL FUNCTION REFERENCES
; Declare functions defined elsewhere and referenced in this module
----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
; Declare variables used in this module but defined elsewhere
----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
; FUNCTION CODE
----------------------------------------------------------------------------*/

void pvmp3_alias_reduction(int32 *input_buffer,         /* Ptr to spec values of current channel */
                           granuleInfo *gr_info,
                           int32  *used_freq_lines,
                           mp3Header *info)
{
    int32 *ptr1;
    int32 *ptr2;
    int32 *ptr3;
    int32 *ptr4;
    const int32 *ptr_csi;
    const int32 *ptr_csa;
    int32  sblim;

    int32 i, j;

    *used_freq_lines = fxp_mul32_Q32(*used_freq_lines << 16, (int32)(0x7FFFFFFF / (float)18 - 1.0f)) >> 15;


    if (gr_info->window_switching_flag &&  gr_info->block_type == 2)
    {
        if (gr_info->mixed_block_flag)
        {
            sblim = ((info->version_x == MPEG_2_5) && (info->sampling_frequency == 2)) ? 3 : 1;
        }
        else
        {
            return;  /* illegal parameter */
        }
    }
    else
    {
        sblim = *used_freq_lines + 1;

        if (sblim > SUBBANDS_NUMBER - 1)
        {
            sblim = SUBBANDS_NUMBER - 1;  /* default */
        }

    }


    ptr3 = &input_buffer[17];
    ptr4 = &input_buffer[18];
    ptr_csi = c_signal;
    ptr_csa = c_alias;

    /*   NUM_BUTTERFLIES (=8) butterflies between each pair of sub-bands*/

    for (i = NUM_BUTTERFLIES >> 1; i != 0; i--)
    {
        int32 csi1  = *ptr_csi++;
        int32 csi2  = *ptr_csi++;
        int32 csa1  = *ptr_csa++;
        int32 csa2  = *ptr_csa++;

        ptr1 = ptr3;
        ptr3 -= 2;
        ptr2 = ptr4;
        ptr4 += 2;

        /*
         *  "sblim"  alias-reduction operations between each
         *  pair of sub-bands
         */

        for (j = sblim >> 1; j != 0; j--)
        {
            int32 y = *ptr2;
            int32 x = *ptr1 << 1;
            *ptr1--  = fxp_msb32_Q32(fxp_mul32_Q32(x, csi1), y << 1, csa1);
            *ptr2++  = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi1), x, csa1);
            y = *ptr2;
            x = *ptr1 << 1;
            *ptr1    = fxp_msb32_Q32(fxp_mul32_Q32(x, csi2), y << 1, csa2);
            *ptr2    = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi2), x, csa2);
            ptr1 += 19;
            ptr2 += 17;
            y = *ptr2;
            x = *ptr1 << 1;
            *ptr1--  = fxp_msb32_Q32(fxp_mul32_Q32(x, csi1), y << 1, csa1);
            *ptr2++  = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi1), x, csa1);
            y = *ptr2;
            x = *ptr1 << 1;
            *ptr1    = fxp_msb32_Q32(fxp_mul32_Q32(x, csi2), y << 1, csa2);
            *ptr2    = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi2), x, csa2);
            ptr1 += 19;
            ptr2 += 17;

        }

        if (sblim & 1)
        {
            int32 x = *ptr1 << 1;
            int32 y = *ptr2;
            *ptr1--  = fxp_msb32_Q32(fxp_mul32_Q32(x, csi1), y << 1, csa1);
            *ptr2++  = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi1), x, csa1);

            x = *ptr1 << 1;
            y = *ptr2;
            *ptr1    = fxp_msb32_Q32(fxp_mul32_Q32(x, csi2), y << 1, csa2);
            *ptr2    = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi2), x, csa2);
        }
    }

}