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
maximize_range(Int16 * in,Int16 * out,int bound,int len)41 static 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
renorm_range(Int16 * in,Int16 * out,int shift,int len)113 static 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
power_spectrum(const spx_word16_t * X,spx_word32_t * ps,int N)164 void 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
power_spectrum(const float * restrict X,float * restrict ps,int N)201 void 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