153a5a1b3Sopenharmony_ci/* Copyright (C) 2007 Hong Zhiqian */
253a5a1b3Sopenharmony_ci/**
353a5a1b3Sopenharmony_ci   @file kiss_fftr_tm.h
453a5a1b3Sopenharmony_ci   @author Hong Zhiqian
553a5a1b3Sopenharmony_ci   @brief Various compatibility routines for Speex (TriMedia version)
653a5a1b3Sopenharmony_ci*/
753a5a1b3Sopenharmony_ci/*
853a5a1b3Sopenharmony_ci   Redistribution and use in source and binary forms, with or without
953a5a1b3Sopenharmony_ci   modification, are permitted provided that the following conditions
1053a5a1b3Sopenharmony_ci   are met:
1153a5a1b3Sopenharmony_ci
1253a5a1b3Sopenharmony_ci   - Redistributions of source code must retain the above copyright
1353a5a1b3Sopenharmony_ci   notice, this list of conditions and the following disclaimer.
1453a5a1b3Sopenharmony_ci
1553a5a1b3Sopenharmony_ci   - Redistributions in binary form must reproduce the above copyright
1653a5a1b3Sopenharmony_ci   notice, this list of conditions and the following disclaimer in the
1753a5a1b3Sopenharmony_ci   documentation and/or other materials provided with the distribution.
1853a5a1b3Sopenharmony_ci
1953a5a1b3Sopenharmony_ci   - Neither the name of the Xiph.org Foundation nor the names of its
2053a5a1b3Sopenharmony_ci   contributors may be used to endorse or promote products derived from
2153a5a1b3Sopenharmony_ci   this software without specific prior written permission.
2253a5a1b3Sopenharmony_ci
2353a5a1b3Sopenharmony_ci   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2453a5a1b3Sopenharmony_ci   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2553a5a1b3Sopenharmony_ci   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2653a5a1b3Sopenharmony_ci   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
2753a5a1b3Sopenharmony_ci   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2853a5a1b3Sopenharmony_ci   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2953a5a1b3Sopenharmony_ci   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3053a5a1b3Sopenharmony_ci   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3153a5a1b3Sopenharmony_ci   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3253a5a1b3Sopenharmony_ci   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3353a5a1b3Sopenharmony_ci   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3453a5a1b3Sopenharmony_ci*/
3553a5a1b3Sopenharmony_ci#include "_kiss_fft_guts_tm.h"
3653a5a1b3Sopenharmony_ci
3753a5a1b3Sopenharmony_ci#ifdef TM_ASM
3853a5a1b3Sopenharmony_ci
3953a5a1b3Sopenharmony_ci#include "profile_tm.h"
4053a5a1b3Sopenharmony_ci
4153a5a1b3Sopenharmony_ci#ifdef FIXED_POINT
4253a5a1b3Sopenharmony_ci
4353a5a1b3Sopenharmony_ci#define TM_NDIV(res,c,frac)															\
4453a5a1b3Sopenharmony_ci	{	register int c1, c0;														\
4553a5a1b3Sopenharmony_ci																					\
4653a5a1b3Sopenharmony_ci		c1 = -asri(16,(c));															\
4753a5a1b3Sopenharmony_ci		c0 = sex16((c));															\
4853a5a1b3Sopenharmony_ci		(res) = pack16lsb(sround(c1 * (32767/(frac))), sround(c0 * (32767/(frac))));\
4953a5a1b3Sopenharmony_ci	}
5053a5a1b3Sopenharmony_ci
5153a5a1b3Sopenharmony_ci
5253a5a1b3Sopenharmony_ci#define OVERRIDE_KISS_FFTR
5353a5a1b3Sopenharmony_civoid kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar * restrict timedata, kiss_fft_cpx * restrict freqdata)
5453a5a1b3Sopenharmony_ci{
5553a5a1b3Sopenharmony_ci	register int ncfft, ncfft2, k;
5653a5a1b3Sopenharmony_ci	register int * restrict tmpbuf;
5753a5a1b3Sopenharmony_ci	register int * restrict twiddles;
5853a5a1b3Sopenharmony_ci
5953a5a1b3Sopenharmony_ci	ncfft = st->substate->nfft;
6053a5a1b3Sopenharmony_ci	ncfft2 = ncfft >> 1;
6153a5a1b3Sopenharmony_ci	tmpbuf = (int*)st->tmpbuf;
6253a5a1b3Sopenharmony_ci	twiddles = (int*)st->super_twiddles;
6353a5a1b3Sopenharmony_ci
6453a5a1b3Sopenharmony_ci	TMDEBUG_ALIGNMEM(timedata);
6553a5a1b3Sopenharmony_ci	TMDEBUG_ALIGNMEM(freqdata);
6653a5a1b3Sopenharmony_ci	TMDEBUG_ALIGNMEM(tmpbuf);
6753a5a1b3Sopenharmony_ci	TMDEBUG_ALIGNMEM(twiddles);
6853a5a1b3Sopenharmony_ci
6953a5a1b3Sopenharmony_ci	kiss_fft(st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf);
7053a5a1b3Sopenharmony_ci
7153a5a1b3Sopenharmony_ci	 {
7253a5a1b3Sopenharmony_ci		register int tdcr, tdci;
7353a5a1b3Sopenharmony_ci		tdcr = sround(st->tmpbuf[0].r * (32767/2));
7453a5a1b3Sopenharmony_ci		tdci = sround(st->tmpbuf[0].i * (32767/2));
7553a5a1b3Sopenharmony_ci
7653a5a1b3Sopenharmony_ci		freqdata[0].r = tdcr + tdci;
7753a5a1b3Sopenharmony_ci		freqdata[ncfft].r = tdcr - tdci;
7853a5a1b3Sopenharmony_ci		freqdata[ncfft].i = freqdata[0].i = 0;
7953a5a1b3Sopenharmony_ci	 }
8053a5a1b3Sopenharmony_ci
8153a5a1b3Sopenharmony_ci	 for ( k=1 ; k <= ncfft2 ; ++k )
8253a5a1b3Sopenharmony_ci	 {
8353a5a1b3Sopenharmony_ci		register int fpk, fpnk, i, tw, f1k, f2k;
8453a5a1b3Sopenharmony_ci		register int fq1, fq2;
8553a5a1b3Sopenharmony_ci
8653a5a1b3Sopenharmony_ci		i = ncfft-k;
8753a5a1b3Sopenharmony_ci
8853a5a1b3Sopenharmony_ci		fpk  = ld32x(tmpbuf,k);
8953a5a1b3Sopenharmony_ci		tw   = ld32x(twiddles,k);
9053a5a1b3Sopenharmony_ci		fpnk = ld32x(tmpbuf,i);
9153a5a1b3Sopenharmony_ci
9253a5a1b3Sopenharmony_ci		TM_DIV(fpk, fpk, 2);
9353a5a1b3Sopenharmony_ci		TM_NDIV(fpnk,fpnk,2);
9453a5a1b3Sopenharmony_ci
9553a5a1b3Sopenharmony_ci        TM_ADD( f1k, fpk , fpnk );
9653a5a1b3Sopenharmony_ci        TM_SUB( f2k, fpk , fpnk );
9753a5a1b3Sopenharmony_ci		TM_MUL( tw , f2k, tw );
9853a5a1b3Sopenharmony_ci		TM_ADD( fq1, f1k, tw );
9953a5a1b3Sopenharmony_ci		TM_SHR( fq1, fq1, 1  );
10053a5a1b3Sopenharmony_ci		TM_SUB( fq2, f1k, tw );
10153a5a1b3Sopenharmony_ci		TM_NEGMSB( fq2, fq2 );
10253a5a1b3Sopenharmony_ci		TM_SHR( fq2, fq2, 1 );
10353a5a1b3Sopenharmony_ci
10453a5a1b3Sopenharmony_ci
10553a5a1b3Sopenharmony_ci		st32d( k<<2, freqdata, fq1 );
10653a5a1b3Sopenharmony_ci		st32d( i<<2, freqdata, fq2 );
10753a5a1b3Sopenharmony_ci    }
10853a5a1b3Sopenharmony_ci}
10953a5a1b3Sopenharmony_ci
11053a5a1b3Sopenharmony_ci#define OVERRIDE_KISS_FFTRI
11153a5a1b3Sopenharmony_civoid kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx * restrict freqdata,kiss_fft_scalar * restrict timedata)
11253a5a1b3Sopenharmony_ci{
11353a5a1b3Sopenharmony_ci	register int k, ncfft, ncfft2;
11453a5a1b3Sopenharmony_ci	register int * restrict tmpbuf;
11553a5a1b3Sopenharmony_ci	register int * restrict twiddles;
11653a5a1b3Sopenharmony_ci
11753a5a1b3Sopenharmony_ci    ncfft = st->substate->nfft;
11853a5a1b3Sopenharmony_ci	ncfft2 = ncfft >> 1;
11953a5a1b3Sopenharmony_ci	tmpbuf = (int*)st->tmpbuf;
12053a5a1b3Sopenharmony_ci	twiddles = (int*)st->super_twiddles;
12153a5a1b3Sopenharmony_ci
12253a5a1b3Sopenharmony_ci	TMDEBUG_ALIGNMEM(freqdata);
12353a5a1b3Sopenharmony_ci	TMDEBUG_ALIGNMEM(timedata);
12453a5a1b3Sopenharmony_ci	TMDEBUG_ALIGNMEM(tmpbuf);
12553a5a1b3Sopenharmony_ci	TMDEBUG_ALIGNMEM(twiddles);
12653a5a1b3Sopenharmony_ci
12753a5a1b3Sopenharmony_ci	{
12853a5a1b3Sopenharmony_ci		register int fqr, fqnr;
12953a5a1b3Sopenharmony_ci
13053a5a1b3Sopenharmony_ci		fqr  = freqdata[0].r;
13153a5a1b3Sopenharmony_ci		fqnr = freqdata[ncfft].r;
13253a5a1b3Sopenharmony_ci
13353a5a1b3Sopenharmony_ci		st->tmpbuf[0].r = fqr + fqnr;
13453a5a1b3Sopenharmony_ci		st->tmpbuf[0].i = fqr - fqnr;
13553a5a1b3Sopenharmony_ci	}
13653a5a1b3Sopenharmony_ci
13753a5a1b3Sopenharmony_ci    for ( k=1 ; k <= ncfft2 ; ++k )
13853a5a1b3Sopenharmony_ci	{
13953a5a1b3Sopenharmony_ci		register int fk, fnkc, i, tw, fek, fok, tmp;
14053a5a1b3Sopenharmony_ci		register int tbk, tbn;
14153a5a1b3Sopenharmony_ci
14253a5a1b3Sopenharmony_ci		i = ncfft-k;
14353a5a1b3Sopenharmony_ci
14453a5a1b3Sopenharmony_ci		fk = ld32x(freqdata,k);
14553a5a1b3Sopenharmony_ci		tw = ld32x(twiddles,k);
14653a5a1b3Sopenharmony_ci		fnkc = pack16lsb(-freqdata[i].i, freqdata[i].r);
14753a5a1b3Sopenharmony_ci
14853a5a1b3Sopenharmony_ci        TM_ADD (fek, fk, fnkc);
14953a5a1b3Sopenharmony_ci        TM_SUB (tmp, fk, fnkc);
15053a5a1b3Sopenharmony_ci        TM_MUL (fok, tmp, tw );
15153a5a1b3Sopenharmony_ci		TM_ADD (tbk, fek, fok);
15253a5a1b3Sopenharmony_ci		TM_SUB (tbn, fek, fok);
15353a5a1b3Sopenharmony_ci		TM_NEGMSB(tbn, tbn);
15453a5a1b3Sopenharmony_ci
15553a5a1b3Sopenharmony_ci		st32d(k<<2, tmpbuf, tbk);
15653a5a1b3Sopenharmony_ci		st32d(i<<2, tmpbuf, tbn);
15753a5a1b3Sopenharmony_ci    }
15853a5a1b3Sopenharmony_ci    kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
15953a5a1b3Sopenharmony_ci}
16053a5a1b3Sopenharmony_ci
16153a5a1b3Sopenharmony_ci#else
16253a5a1b3Sopenharmony_ci
16353a5a1b3Sopenharmony_ci#define OVERRIDE_KISS_FFTR
16453a5a1b3Sopenharmony_civoid kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar * restrict timedata,kiss_fft_cpx * restrict freqdata)
16553a5a1b3Sopenharmony_ci{
16653a5a1b3Sopenharmony_ci    register kiss_fft_cpx fpnk, fpk, f1k, f2k, twk;
16753a5a1b3Sopenharmony_ci    register int k, ncfft;
16853a5a1b3Sopenharmony_ci	register kiss_fft_cpx * restrict tmpbuf, * restrict tw;
16953a5a1b3Sopenharmony_ci	register float tdcr, tdci;
17053a5a1b3Sopenharmony_ci
17153a5a1b3Sopenharmony_ci    ncfft = st->substate->nfft;
17253a5a1b3Sopenharmony_ci	tmpbuf= st->tmpbuf;
17353a5a1b3Sopenharmony_ci	tw	  = st->super_twiddles;
17453a5a1b3Sopenharmony_ci
17553a5a1b3Sopenharmony_ci	kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, tmpbuf );
17653a5a1b3Sopenharmony_ci
17753a5a1b3Sopenharmony_ci	tdcr = tmpbuf[0].r;
17853a5a1b3Sopenharmony_ci    tdci = tmpbuf[0].i;
17953a5a1b3Sopenharmony_ci
18053a5a1b3Sopenharmony_ci	freqdata[0].r = tdcr + tdci;
18153a5a1b3Sopenharmony_ci    freqdata[ncfft].r = tdcr - tdci;
18253a5a1b3Sopenharmony_ci    freqdata[ncfft].i = freqdata[0].i = 0;
18353a5a1b3Sopenharmony_ci
18453a5a1b3Sopenharmony_ci    for ( k=1;k <= ncfft/2 ; ++k )
18553a5a1b3Sopenharmony_ci	{
18653a5a1b3Sopenharmony_ci        fpk    = tmpbuf[k];
18753a5a1b3Sopenharmony_ci        fpnk.r = tmpbuf[ncfft-k].r;
18853a5a1b3Sopenharmony_ci        fpnk.i = -tmpbuf[ncfft-k].i;
18953a5a1b3Sopenharmony_ci
19053a5a1b3Sopenharmony_ci        C_ADD( f1k, fpk , fpnk );
19153a5a1b3Sopenharmony_ci        C_SUB( f2k, fpk , fpnk );
19253a5a1b3Sopenharmony_ci        C_MUL( twk, f2k , tw[k]);
19353a5a1b3Sopenharmony_ci
19453a5a1b3Sopenharmony_ci        freqdata[k].r = HALF_OF(f1k.r + twk.r);
19553a5a1b3Sopenharmony_ci        freqdata[k].i = HALF_OF(f1k.i + twk.i);
19653a5a1b3Sopenharmony_ci        freqdata[ncfft-k].r = HALF_OF(f1k.r - twk.r);
19753a5a1b3Sopenharmony_ci        freqdata[ncfft-k].i = HALF_OF(twk.i - f1k.i);
19853a5a1b3Sopenharmony_ci    }
19953a5a1b3Sopenharmony_ci}
20053a5a1b3Sopenharmony_ci
20153a5a1b3Sopenharmony_ci#define OVERRIDE_KISS_FFTRI
20253a5a1b3Sopenharmony_civoid kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx * restrict freqdata,kiss_fft_scalar * restrict timedata)
20353a5a1b3Sopenharmony_ci{
20453a5a1b3Sopenharmony_ci    register int k, ncfft;
20553a5a1b3Sopenharmony_ci	register kiss_fft_cpx * restrict tmpbuf, * restrict tw;
20653a5a1b3Sopenharmony_ci
20753a5a1b3Sopenharmony_ci
20853a5a1b3Sopenharmony_ci    ncfft = st->substate->nfft;
20953a5a1b3Sopenharmony_ci	tmpbuf= st->tmpbuf;
21053a5a1b3Sopenharmony_ci	tw	  = st->super_twiddles;
21153a5a1b3Sopenharmony_ci
21253a5a1b3Sopenharmony_ci    tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
21353a5a1b3Sopenharmony_ci    tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
21453a5a1b3Sopenharmony_ci
21553a5a1b3Sopenharmony_ci    for (k = 1; k <= ncfft / 2; ++k)
21653a5a1b3Sopenharmony_ci	{
21753a5a1b3Sopenharmony_ci        register kiss_fft_cpx fk, fnkc, fek, fok, tmp;
21853a5a1b3Sopenharmony_ci        fk = freqdata[k];
21953a5a1b3Sopenharmony_ci        fnkc.r = freqdata[ncfft - k].r;
22053a5a1b3Sopenharmony_ci        fnkc.i = -freqdata[ncfft - k].i;
22153a5a1b3Sopenharmony_ci
22253a5a1b3Sopenharmony_ci        C_ADD (fek, fk, fnkc);
22353a5a1b3Sopenharmony_ci        C_SUB (tmp, fk, fnkc);
22453a5a1b3Sopenharmony_ci        C_MUL (fok,tmp,tw[k]);
22553a5a1b3Sopenharmony_ci        C_ADD (tmpbuf[k],fek, fok);
22653a5a1b3Sopenharmony_ci        C_SUB (tmp, fek, fok);
22753a5a1b3Sopenharmony_ci		tmpbuf[ncfft - k].r = tmp.r;
22853a5a1b3Sopenharmony_ci        tmpbuf[ncfft - k].i = -tmp.i;
22953a5a1b3Sopenharmony_ci	}
23053a5a1b3Sopenharmony_ci    kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
23153a5a1b3Sopenharmony_ci}
23253a5a1b3Sopenharmony_ci
23353a5a1b3Sopenharmony_ci#endif
23453a5a1b3Sopenharmony_ci#endif
23553a5a1b3Sopenharmony_ci
236