| /* Copyright (C) 2007 Hong Zhiqian */ |
| /** |
| @file fftwrap_tm.h |
| @author Hong Zhiqian |
| @brief Various compatibility routines for Speex (TriMedia version) |
| */ |
| /* |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions |
| are met: |
| |
| - Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| |
| - Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| - Neither the name of the Xiph.org Foundation nor the names of its |
| contributors may be used to endorse or promote products derived from |
| this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR |
| CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| #include <ops/custom_defs.h> |
| #include "profile_tm.h" |
| |
| #ifdef FIXED_POINT |
| |
| #define OVERRIDE_MAXIMIZE_RANGE |
| static int maximize_range(Int16 *in, Int16 *out, int bound, int len) |
| { |
| register int max_val=0; |
| register int shift=0; |
| register int i, j; |
| |
| TMDEBUG_ALIGNMEM(in); |
| TMDEBUG_ALIGNMEM(out); |
| |
| MAXIMIZERANGE_START(); |
| |
| len >>= 1; |
| |
| for ( i=0 ; i<len ; i+=4 ) |
| { |
| register int x10, x32, x54, x76; |
| |
| x10 = ld32x(in,i); |
| x32 = ld32x(in,i+1); |
| x54 = ld32x(in,i+2); |
| x76 = ld32x(in,i+3); |
| |
| x10 = dspidualabs(x10); |
| x32 = dspidualabs(x32); |
| x54 = dspidualabs(x54); |
| x76 = dspidualabs(x76); |
| |
| x10 = imax(sex16(x10), asri(16,x10)); |
| x32 = imax(sex16(x32), asri(16,x32)); |
| x54 = imax(sex16(x54), asri(16,x54)); |
| x76 = imax(sex16(x76), asri(16,x76)); |
| |
| max_val = imax(max_val,x10); |
| max_val = imax(max_val,x32); |
| max_val = imax(max_val,x54); |
| max_val = imax(max_val,x76); |
| } |
| |
| while ( max_val <= (bound>>1) && max_val != 0 ) |
| { max_val <<= 1; |
| shift++; |
| } |
| |
| if ( shift != 0 ) |
| { |
| for ( i=0,j=0 ; i<len ; i+=4,j+=16 ) |
| { |
| register int x10, x32, x54, x76; |
| |
| x10 = ld32x(in,i); |
| x32 = ld32x(in,i+1); |
| x54 = ld32x(in,i+2); |
| x76 = ld32x(in,i+3); |
| |
| x10 = dualasl(x10, shift); |
| x32 = dualasl(x32, shift); |
| x54 = dualasl(x54, shift); |
| x76 = dualasl(x76, shift); |
| |
| st32d(j,out,x10); |
| st32d(j+4,out,x32); |
| st32d(j+8,out,x54); |
| st32d(j+12,out,x76); |
| } |
| } |
| |
| MAXIMIZERANGE_STOP(); |
| |
| return shift; |
| } |
| |
| #define OVERRIDE_RENORM_RANGE |
| static void renorm_range(Int16 *in, Int16 *out, int shift, int len) |
| { |
| register int i, j, s, l; |
| |
| TMDEBUG_ALIGNMEM(in); |
| TMDEBUG_ALIGNMEM(out); |
| |
| RENORMRANGE_START(); |
| |
| s = (1<<((shift))>>1); |
| s = pack16lsb(s,s); |
| |
| len >>= 1; |
| l = len & (int)0xFFFFFFFE; |
| |
| for ( i=0,j=0 ; i<l; i+=2,j+=8 ) |
| { |
| register int x10, x32; |
| |
| x10 = ld32x(in,i); |
| x32 = ld32x(in,i+1); |
| |
| x10 = dspidualadd(x10, s); |
| x32 = dspidualadd(x32, s); |
| |
| x10 = dualasr(x10, shift); |
| x32 = dualasr(x32, shift); |
| |
| st32d(j,out,x10); |
| st32d(j+4,out,x32); |
| } |
| |
| if ( len & (int)0x01 ) |
| { |
| register int x10; |
| |
| x10 = ld32x(in,i); |
| x10 = dspidualadd(x10, s); |
| x10 = dualasr(x10, shift); |
| st32d(j,out,x10); |
| } |
| |
| RENORMRANGE_STOP(); |
| } |
| |
| #endif |
| |
| #ifdef USE_COMPACT_KISS_FFT |
| #ifdef FIXED_POINT |
| |
| #define OVERRIDE_POWER_SPECTRUM |
| void power_spectrum(const spx_word16_t *X, spx_word32_t *ps, int N) |
| { |
| register int x10, x32, x54, x76, *x; |
| register int i; |
| |
| x = (int*)(X-1); |
| |
| TMDEBUG_ALIGNMEM(x); |
| |
| POWERSPECTRUM_START(); |
| |
| x76 = 0; |
| ps[0] = MULT16_16(X[0],X[0]); |
| N >>= 1; |
| |
| for( i=1 ; i<N ; i+=4 ) |
| { |
| x10 = ld32x(x, i); |
| x32 = ld32x(x, i+1); |
| x54 = ld32x(x, i+2); |
| x76 = ld32x(x, i+3); |
| |
| ps[i] = ifir16(x10,x10); |
| ps[i+1] = ifir16(x32,x32); |
| ps[i+2] = ifir16(x54,x54); |
| ps[i+3] = ifir16(x76,x76); |
| } |
| |
| x76 = sex16(x76); |
| ps[N] = x76 * x76; |
| |
| POWERSPECTRUM_STOP(); |
| } |
| |
| #else |
| |
| #define OVERRIDE_POWER_SPECTRUM |
| void power_spectrum(const float * restrict X, float * restrict ps, int N) |
| { |
| register int i, j; |
| register float xx; |
| |
| POWERSPECTRUM_START(); |
| |
| xx = X[0]; |
| |
| ps[0]=MULT16_16(xx,xx); |
| |
| #pragma TCS_unroll=4 |
| #pragma TCS_unrollexact=1 |
| for (i=1,j=1;i<N-1;i+=2,j++) |
| { register float xi, xii; |
| |
| xi = X[i]; |
| xii = X[i+1]; |
| |
| ps[j] = MULT16_16(xi,xi) + MULT16_16(xii,xii); |
| } |
| #pragma TCS_unrollexact=0 |
| #pragma TCS_unroll=0 |
| |
| xx = X[i]; |
| ps[j]=MULT16_16(xx,xx); |
| |
| POWERSPECTRUM_STOP(); |
| } |
| |
| #endif |
| #endif |
| |