misc/libtremor/misc.h
changeset 5170 f7e49eff3708
equal deleted inserted replaced
5169:e353ca78d28b 5170:f7e49eff3708
       
     1 /********************************************************************
       
     2  *                                                                  *
       
     3  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
       
     4  *                                                                  *
       
     5  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
       
     6  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
       
     7  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
       
     8  *                                                                  *
       
     9  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
       
    10  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
       
    11  *                                                                  *
       
    12  ********************************************************************
       
    13 
       
    14  function: miscellaneous math and prototypes
       
    15 
       
    16  ********************************************************************/
       
    17 
       
    18 #ifndef _V_RANDOM_H_
       
    19 #define _V_RANDOM_H_
       
    20 #include "ivorbiscodec.h"
       
    21 #include "os.h"
       
    22 
       
    23 #include "asm_arm.h"
       
    24 #include <stdlib.h> /* for abs() */
       
    25   
       
    26 #ifndef _V_WIDE_MATH
       
    27 #define _V_WIDE_MATH
       
    28   
       
    29 #ifndef  _LOW_ACCURACY_
       
    30 /* 64 bit multiply */
       
    31 
       
    32 #if !(defined WIN32 && defined WINCE)
       
    33 #include <sys/types.h>
       
    34 #endif
       
    35 
       
    36 #if BYTE_ORDER==LITTLE_ENDIAN
       
    37 union magic {
       
    38   struct {
       
    39     ogg_int32_t lo;
       
    40     ogg_int32_t hi;
       
    41   } halves;
       
    42   ogg_int64_t whole;
       
    43 };
       
    44 #endif 
       
    45 
       
    46 #if BYTE_ORDER==BIG_ENDIAN
       
    47 union magic {
       
    48   struct {
       
    49     ogg_int32_t hi;
       
    50     ogg_int32_t lo;
       
    51   } halves;
       
    52   ogg_int64_t whole;
       
    53 };
       
    54 #endif
       
    55 
       
    56 STIN ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) {
       
    57   union magic magic;
       
    58   magic.whole = (ogg_int64_t)x * y;
       
    59   return magic.halves.hi;
       
    60 }
       
    61 
       
    62 STIN ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) {
       
    63   return MULT32(x,y)<<1;
       
    64 }
       
    65 
       
    66 STIN ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) {
       
    67   union magic magic;
       
    68   magic.whole  = (ogg_int64_t)x * y;
       
    69   return ((ogg_uint32_t)(magic.halves.lo)>>15) | ((magic.halves.hi)<<17);
       
    70 }
       
    71 
       
    72 #else
       
    73 /* 32 bit multiply, more portable but less accurate */
       
    74 
       
    75 /*
       
    76  * Note: Precision is biased towards the first argument therefore ordering
       
    77  * is important.  Shift values were chosen for the best sound quality after
       
    78  * many listening tests.
       
    79  */
       
    80 
       
    81 /*
       
    82  * For MULT32 and MULT31: The second argument is always a lookup table
       
    83  * value already preshifted from 31 to 8 bits.  We therefore take the 
       
    84  * opportunity to save on text space and use unsigned char for those
       
    85  * tables in this case.
       
    86  */
       
    87 
       
    88 STIN ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) {
       
    89   return (x >> 9) * y;  /* y preshifted >>23 */
       
    90 }
       
    91 
       
    92 STIN ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) {
       
    93   return (x >> 8) * y;  /* y preshifted >>23 */
       
    94 }
       
    95 
       
    96 STIN ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) {
       
    97   return (x >> 6) * y;  /* y preshifted >>9 */
       
    98 }
       
    99 
       
   100 #endif
       
   101 
       
   102 /*
       
   103  * This should be used as a memory barrier, forcing all cached values in
       
   104  * registers to wr writen back to memory.  Might or might not be beneficial
       
   105  * depending on the architecture and compiler.
       
   106  */
       
   107 #define MB()
       
   108 
       
   109 /*
       
   110  * The XPROD functions are meant to optimize the cross products found all
       
   111  * over the place in mdct.c by forcing memory operation ordering to avoid
       
   112  * unnecessary register reloads as soon as memory is being written to.
       
   113  * However this is only beneficial on CPUs with a sane number of general
       
   114  * purpose registers which exclude the Intel x86.  On Intel, better let the
       
   115  * compiler actually reload registers directly from original memory by using
       
   116  * macros.
       
   117  */
       
   118 
       
   119 #ifdef __i386__
       
   120 
       
   121 #define XPROD32(_a, _b, _t, _v, _x, _y)		\
       
   122   { *(_x)=MULT32(_a,_t)+MULT32(_b,_v);		\
       
   123     *(_y)=MULT32(_b,_t)-MULT32(_a,_v); }
       
   124 #define XPROD31(_a, _b, _t, _v, _x, _y)		\
       
   125   { *(_x)=MULT31(_a,_t)+MULT31(_b,_v);		\
       
   126     *(_y)=MULT31(_b,_t)-MULT31(_a,_v); }
       
   127 #define XNPROD31(_a, _b, _t, _v, _x, _y)	\
       
   128   { *(_x)=MULT31(_a,_t)-MULT31(_b,_v);		\
       
   129     *(_y)=MULT31(_b,_t)+MULT31(_a,_v); }
       
   130 
       
   131 #else
       
   132 
       
   133 STIN void XPROD32(ogg_int32_t  a, ogg_int32_t  b,
       
   134 			   ogg_int32_t  t, ogg_int32_t  v,
       
   135 			   ogg_int32_t *x, ogg_int32_t *y)
       
   136 {
       
   137   *x = MULT32(a, t) + MULT32(b, v);
       
   138   *y = MULT32(b, t) - MULT32(a, v);
       
   139 }
       
   140 
       
   141 STIN void XPROD31(ogg_int32_t  a, ogg_int32_t  b,
       
   142 			   ogg_int32_t  t, ogg_int32_t  v,
       
   143 			   ogg_int32_t *x, ogg_int32_t *y)
       
   144 {
       
   145   *x = MULT31(a, t) + MULT31(b, v);
       
   146   *y = MULT31(b, t) - MULT31(a, v);
       
   147 }
       
   148 
       
   149 STIN void XNPROD31(ogg_int32_t  a, ogg_int32_t  b,
       
   150 			    ogg_int32_t  t, ogg_int32_t  v,
       
   151 			    ogg_int32_t *x, ogg_int32_t *y)
       
   152 {
       
   153   *x = MULT31(a, t) - MULT31(b, v);
       
   154   *y = MULT31(b, t) + MULT31(a, v);
       
   155 }
       
   156 
       
   157 #endif
       
   158 
       
   159 #endif
       
   160 
       
   161 #ifndef _V_CLIP_MATH
       
   162 #define _V_CLIP_MATH
       
   163 
       
   164 STIN ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
       
   165   int ret=x;
       
   166   ret-= ((x<=32767)-1)&(x-32767);
       
   167   ret-= ((x>=-32768)-1)&(x+32768);
       
   168   return(ret);
       
   169 }
       
   170 
       
   171 #endif
       
   172 
       
   173 STIN ogg_int32_t VFLOAT_MULT(ogg_int32_t a,ogg_int32_t ap,
       
   174 				      ogg_int32_t b,ogg_int32_t bp,
       
   175 				      ogg_int32_t *p){
       
   176   if(a && b){
       
   177 #ifndef _LOW_ACCURACY_
       
   178     *p=ap+bp+32;
       
   179     return MULT32(a,b);
       
   180 #else
       
   181     *p=ap+bp+31;
       
   182     return (a>>15)*(b>>16); 
       
   183 #endif
       
   184   }else
       
   185     return 0;
       
   186 }
       
   187 
       
   188 int _ilog(unsigned int);
       
   189 
       
   190 STIN ogg_int32_t VFLOAT_MULTI(ogg_int32_t a,ogg_int32_t ap,
       
   191 				      ogg_int32_t i,
       
   192 				      ogg_int32_t *p){
       
   193 
       
   194   int ip=_ilog(abs(i))-31;
       
   195   return VFLOAT_MULT(a,ap,i<<-ip,ip,p);
       
   196 }
       
   197 
       
   198 STIN ogg_int32_t VFLOAT_ADD(ogg_int32_t a,ogg_int32_t ap,
       
   199 				      ogg_int32_t b,ogg_int32_t bp,
       
   200 				      ogg_int32_t *p){
       
   201 
       
   202   if(!a){
       
   203     *p=bp;
       
   204     return b;
       
   205   }else if(!b){
       
   206     *p=ap;
       
   207     return a;
       
   208   }
       
   209 
       
   210   /* yes, this can leak a bit. */
       
   211   if(ap>bp){
       
   212     int shift=ap-bp+1;
       
   213     *p=ap+1;
       
   214     a>>=1;
       
   215     if(shift<32){
       
   216       b=(b+(1<<(shift-1)))>>shift;
       
   217     }else{
       
   218       b=0;
       
   219     }
       
   220   }else{
       
   221     int shift=bp-ap+1;
       
   222     *p=bp+1;
       
   223     b>>=1;
       
   224     if(shift<32){
       
   225       a=(a+(1<<(shift-1)))>>shift;
       
   226     }else{
       
   227       a=0;
       
   228     }
       
   229   }
       
   230 
       
   231   a+=b;
       
   232   if((a&0xc0000000)==0xc0000000 || 
       
   233      (a&0xc0000000)==0){
       
   234     a<<=1;
       
   235     (*p)--;
       
   236   }
       
   237   return(a);
       
   238 }
       
   239 
       
   240 #endif
       
   241 
       
   242 
       
   243 
       
   244