1/* Copyright (C) 2007 Hong Zhiqian */ 2/** 3 @file fftwrap_tm.h 4 @author Hong Zhiqian 5 @brief Various compatibility routines for Speex (TriMedia version) 6*/ 7/* 8 Redistribution and use in source and binary forms, with or without 9 modification, are permitted provided that the following conditions 10 are met: 11 12 - Redistributions of source code must retain the above copyright 13 notice, this list of conditions and the following disclaimer. 14 15 - Redistributions in binary form must reproduce the above copyright 16 notice, this list of conditions and the following disclaimer in the 17 documentation and/or other materials provided with the distribution. 18 19 - Neither the name of the Xiph.org Foundation nor the names of its 20 contributors may be used to endorse or promote products derived from 21 this software without specific prior written permission. 22 23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*/ 35#include <ops/custom_defs.h> 36#include "profile_tm.h" 37 38#ifdef FIXED_POINT 39 40#define OVERRIDE_MAXIMIZE_RANGE 41static int maximize_range(Int16 *in, Int16 *out, int bound, int len) 42{ 43 register int max_val=0; 44 register int shift=0; 45 register int i, j; 46 47 TMDEBUG_ALIGNMEM(in); 48 TMDEBUG_ALIGNMEM(out); 49 50 MAXIMIZERANGE_START(); 51 52 len >>= 1; 53 54 for ( i=0 ; i<len ; i+=4 ) 55 { 56 register int x10, x32, x54, x76; 57 58 x10 = ld32x(in,i); 59 x32 = ld32x(in,i+1); 60 x54 = ld32x(in,i+2); 61 x76 = ld32x(in,i+3); 62 63 x10 = dspidualabs(x10); 64 x32 = dspidualabs(x32); 65 x54 = dspidualabs(x54); 66 x76 = dspidualabs(x76); 67 68 x10 = imax(sex16(x10), asri(16,x10)); 69 x32 = imax(sex16(x32), asri(16,x32)); 70 x54 = imax(sex16(x54), asri(16,x54)); 71 x76 = imax(sex16(x76), asri(16,x76)); 72 73 max_val = imax(max_val,x10); 74 max_val = imax(max_val,x32); 75 max_val = imax(max_val,x54); 76 max_val = imax(max_val,x76); 77 } 78 79 while ( max_val <= (bound>>1) && max_val != 0 ) 80 { max_val <<= 1; 81 shift++; 82 } 83 84 if ( shift != 0 ) 85 { 86 for ( i=0,j=0 ; i<len ; i+=4,j+=16 ) 87 { 88 register int x10, x32, x54, x76; 89 90 x10 = ld32x(in,i); 91 x32 = ld32x(in,i+1); 92 x54 = ld32x(in,i+2); 93 x76 = ld32x(in,i+3); 94 95 x10 = dualasl(x10, shift); 96 x32 = dualasl(x32, shift); 97 x54 = dualasl(x54, shift); 98 x76 = dualasl(x76, shift); 99 100 st32d(j,out,x10); 101 st32d(j+4,out,x32); 102 st32d(j+8,out,x54); 103 st32d(j+12,out,x76); 104 } 105 } 106 107 MAXIMIZERANGE_STOP(); 108 109 return shift; 110} 111 112#define OVERRIDE_RENORM_RANGE 113static void renorm_range(Int16 *in, Int16 *out, int shift, int len) 114{ 115 register int i, j, s, l; 116 117 TMDEBUG_ALIGNMEM(in); 118 TMDEBUG_ALIGNMEM(out); 119 120 RENORMRANGE_START(); 121 122 s = (1<<((shift))>>1); 123 s = pack16lsb(s,s); 124 125 len >>= 1; 126 l = len & (int)0xFFFFFFFE; 127 128 for ( i=0,j=0 ; i<l; i+=2,j+=8 ) 129 { 130 register int x10, x32; 131 132 x10 = ld32x(in,i); 133 x32 = ld32x(in,i+1); 134 135 x10 = dspidualadd(x10, s); 136 x32 = dspidualadd(x32, s); 137 138 x10 = dualasr(x10, shift); 139 x32 = dualasr(x32, shift); 140 141 st32d(j,out,x10); 142 st32d(j+4,out,x32); 143 } 144 145 if ( len & (int)0x01 ) 146 { 147 register int x10; 148 149 x10 = ld32x(in,i); 150 x10 = dspidualadd(x10, s); 151 x10 = dualasr(x10, shift); 152 st32d(j,out,x10); 153 } 154 155 RENORMRANGE_STOP(); 156} 157 158#endif 159 160#ifdef USE_COMPACT_KISS_FFT 161#ifdef FIXED_POINT 162 163#define OVERRIDE_POWER_SPECTRUM 164void power_spectrum(const spx_word16_t *X, spx_word32_t *ps, int N) 165{ 166 register int x10, x32, x54, x76, *x; 167 register int i; 168 169 x = (int*)(X-1); 170 171 TMDEBUG_ALIGNMEM(x); 172 173 POWERSPECTRUM_START(); 174 175 x76 = 0; 176 ps[0] = MULT16_16(X[0],X[0]); 177 N >>= 1; 178 179 for( i=1 ; i<N ; i+=4 ) 180 { 181 x10 = ld32x(x, i); 182 x32 = ld32x(x, i+1); 183 x54 = ld32x(x, i+2); 184 x76 = ld32x(x, i+3); 185 186 ps[i] = ifir16(x10,x10); 187 ps[i+1] = ifir16(x32,x32); 188 ps[i+2] = ifir16(x54,x54); 189 ps[i+3] = ifir16(x76,x76); 190 } 191 192 x76 = sex16(x76); 193 ps[N] = x76 * x76; 194 195 POWERSPECTRUM_STOP(); 196} 197 198#else 199 200#define OVERRIDE_POWER_SPECTRUM 201void power_spectrum(const float * restrict X, float * restrict ps, int N) 202{ 203 register int i, j; 204 register float xx; 205 206 POWERSPECTRUM_START(); 207 208 xx = X[0]; 209 210 ps[0]=MULT16_16(xx,xx); 211 212#pragma TCS_unroll=4 213#pragma TCS_unrollexact=1 214 for (i=1,j=1;i<N-1;i+=2,j++) 215 { register float xi, xii; 216 217 xi = X[i]; 218 xii = X[i+1]; 219 220 ps[j] = MULT16_16(xi,xi) + MULT16_16(xii,xii); 221 } 222#pragma TCS_unrollexact=0 223#pragma TCS_unroll=0 224 225 xx = X[i]; 226 ps[j]=MULT16_16(xx,xx); 227 228 POWERSPECTRUM_STOP(); 229} 230 231#endif 232#endif 233 234