wmafixed.h

Go to the documentation of this file.
00001 /****************************************************************************
00002  *             __________               __   ___.
00003  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
00004  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
00005  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
00006  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
00007  *                     \/            \/     \/    \/            \/
00008  *
00009  * Copyright (C) 2007 Michael Giacomelli
00010  *
00011  * All files in this archive are subject to the GNU General Public License.
00012  * See the file COPYING in the source tree root for full license agreement.
00013  *
00014  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00015  * KIND, either express or implied.
00016  *
00017  ****************************************************************************/
00018 
00019 /*  fixed precision code.  We use a combination of Sign 15.16 and Sign.31
00020     precision here.
00021 
00022     The WMA decoder does not always follow this convention, and occasionally
00023     renormalizes values to other formats in order to maximize precision.
00024     However, only the two precisions above are provided in this file.
00025 
00026 */
00027 
00028 #include <inttypes.h>
00029 
00030 #define PRECISION       16
00031 #define PRECISION64     16
00032 
00033 #define fixtof64(x)       (float)((float)(x) / (float)(1 << PRECISION64))        //does not work on int64_t!
00034 #define ftofix32(x)       ((int32_t)((x) * (float)(1 << PRECISION) + ((x) < 0 ? -0.5 : 0.5)))
00035 #define itofix64(x)       (IntTo64(x))
00036 #define itofix32(x)       ((x) << PRECISION)
00037 #define fixtoi32(x)       ((x) >> PRECISION)
00038 #define fixtoi64(x)       (IntFrom64(x))
00039 
00040 /*fixed functions*/
00041 
00042 int64_t IntTo64(int x);
00043 int IntFrom64(int64_t x);
00044 int32_t Fixed32From64(int64_t x);
00045 int64_t Fixed32To64(int32_t x);
00046 int64_t fixmul64byfixed(int64_t x, int32_t y);
00047 int32_t fixdiv32(int32_t x, int32_t y);
00048 int64_t fixdiv64(int64_t x, int64_t y);
00049 int32_t fixsqrt32(int32_t x);
00050 long fsincos(unsigned long phase, int32_t *cos);
00051 
00052 #ifdef __arm__
00053 
00054 /*Sign-15.16 format */
00055 
00056 #define fixmul32(x, y)  \
00057     ({ int32_t __hi;  \
00058        uint32_t __lo;  \
00059        int32_t __result;  \
00060        asm ("smull   %0, %1, %3, %4\n\t"  \
00061             "movs    %0, %0, lsr %5\n\t"  \
00062             "adc    %2, %0, %1, lsl %6"  \
00063             : "=&r" (__lo), "=&r" (__hi), "=r" (__result)  \
00064             : "%r" (x), "r" (y),  \
00065               "M" (PRECISION), "M" (32 - PRECISION)  \
00066             : "cc");  \
00067        __result;  \
00068     })
00069 
00070 #define fixmul32b(x, y)  \
00071     ({ int32_t __hi;  \
00072        uint32_t __lo;  \
00073        int32_t __result;  \
00074        asm ("smull   %0, %1, %3, %4\n\t"  \
00075             "movs    %2, %1, lsl #1"  \
00076             : "=&r" (__lo), "=&r" (__hi), "=r" (__result)  \
00077             : "%r" (x), "r" (y)  \
00078             : "cc");  \
00079        __result;  \
00080     })
00081 
00082 #elif defined(CPU_COLDFIRE)
00083 
00084 static inline int32_t fixmul32(int32_t x, int32_t y)
00085 {
00086 #if PRECISION != 16
00087 #warning Coldfire fixmul32() only works for PRECISION == 16
00088 #endif
00089     int32_t t1;
00090     asm (
00091         "mac.l   %[x], %[y], %%acc0  \n" /* multiply */
00092         "mulu.l  %[y], %[x]      \n"     /* get lower half, avoid emac stall */
00093         "movclr.l %%acc0, %[t1]  \n"     /* get higher half */
00094         "lsr.l   #1, %[t1]       \n"
00095         "move.w  %[t1], %[x]     \n"
00096         "swap    %[x]            \n"
00097         : [t1] "=&d" (t1), [x] "+d" (x)
00098         : [y] "d"  (y)
00099     );
00100     return x;
00101 }
00102 
00103 static inline int32_t fixmul32b(int32_t x, int32_t y)
00104 {
00105     asm (
00106         "mac.l   %[x], %[y], %%acc0  \n" /* multiply */
00107         "movclr.l %%acc0, %[x]  \n"     /* get higher half */
00108         : [x] "+d" (x)
00109         : [y] "d"  (y)
00110     );
00111     return x;
00112 }
00113 
00114 #else
00115 
00116 static inline int32_t fixmul32(int32_t x, int32_t y)
00117 {
00118     int64_t temp;
00119     temp = x;
00120     temp *= y;
00121 
00122     temp >>= PRECISION;
00123 
00124     return (int32_t)temp;
00125 }
00126 
00127 static inline int32_t fixmul32b(int32_t x, int32_t y)
00128 {
00129     int64_t temp;
00130 
00131     temp = x;
00132     temp *= y;
00133 
00134     temp >>= 31;        //16+31-16 = 31 bits
00135 
00136     return (int32_t)temp;
00137 }
00138 
00139 #endif
00140 
00141 #ifdef __arm__
00142 static inline
00143 void CMUL(int32_t *x, int32_t *y,
00144           int32_t  a, int32_t  b,
00145           int32_t  t, int32_t  v)
00146 {
00147     /* This version loses one bit of precision. Could be solved at the cost
00148      * of 2 extra cycles if it becomes an issue. */
00149     int x1, y1, l;
00150     asm(
00151         "smull    %[l], %[y1], %[b], %[t] \n"
00152         "smlal    %[l], %[y1], %[a], %[v] \n"
00153         "rsb      %[b], %[b], #0          \n"
00154         "smull    %[l], %[x1], %[a], %[t] \n"
00155         "smlal    %[l], %[x1], %[b], %[v] \n"
00156         : [l] "=&r" (l), [x1]"=&r" (x1), [y1]"=&r" (y1), [b] "+r" (b)
00157         : [a] "r" (a),   [t] "r" (t),    [v] "r" (v)
00158         : "cc"
00159     );
00160     *x = x1 << 1;
00161     *y = y1 << 1;
00162 }
00163 #elif defined CPU_COLDFIRE
00164 static inline
00165 void CMUL(int32_t *x, int32_t *y,
00166           int32_t  a, int32_t  b,
00167           int32_t  t, int32_t  v)
00168 {
00169   asm volatile ("mac.l %[a], %[t], %%acc0;"
00170                 "msac.l %[b], %[v], %%acc0;"
00171                 "mac.l %[b], %[t], %%acc1;"
00172                 "mac.l %[a], %[v], %%acc1;"
00173                 "movclr.l %%acc0, %[a];"
00174                 "move.l %[a], (%[x]);"
00175                 "movclr.l %%acc1, %[a];"
00176                 "move.l %[a], (%[y]);"
00177                 : [a] "+&r" (a)
00178                 : [x] "a" (x), [y] "a" (y),
00179                   [b] "r" (b), [t] "r" (t), [v] "r" (v)
00180                 : "cc", "memory");
00181 }
00182 #else
00183 static inline
00184 void CMUL(int32_t *pre,
00185           int32_t *pim,
00186           int32_t are,
00187           int32_t aim,
00188           int32_t bre,
00189           int32_t bim)
00190 {
00191     //int64_t x,y;
00192     int32_t _aref = are;
00193     int32_t _aimf = aim;
00194     int32_t _bref = bre;
00195     int32_t _bimf = bim;
00196     int32_t _r1 = fixmul32b(_bref, _aref);
00197     int32_t _r2 = fixmul32b(_bimf, _aimf);
00198     int32_t _r3 = fixmul32b(_bref, _aimf);
00199     int32_t _r4 = fixmul32b(_bimf, _aref);
00200     *pre = _r1 - _r2;
00201     *pim = _r3 + _r4;
00202 
00203 }
00204 #endif

Generated on Tue May 25 08:04:54 2010 for VLC by  doxygen 1.5.6