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