LCOV - code coverage report
Current view: top level - media/libav/libavcodec - fft_template.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 121 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * FFT/IFFT transforms
       3             :  * Copyright (c) 2008 Loren Merritt
       4             :  * Copyright (c) 2002 Fabrice Bellard
       5             :  * Partly based on libdjbfft by D. J. Bernstein
       6             :  *
       7             :  * This file is part of Libav.
       8             :  *
       9             :  * Libav is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public
      11             :  * License as published by the Free Software Foundation; either
      12             :  * version 2.1 of the License, or (at your option) any later version.
      13             :  *
      14             :  * Libav is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with Libav; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      23             : 
      24             : /**
      25             :  * @file
      26             :  * FFT/IFFT transforms.
      27             :  */
      28             : 
      29             : #include <stdlib.h>
      30             : #include <string.h>
      31             : #include "libavutil/mathematics.h"
      32             : #include "fft.h"
      33             : #include "fft-internal.h"
      34             : 
      35             : /* cos(2*pi*x/n) for 0<=x<=n/4, followed by its reverse */
      36             : #if !CONFIG_HARDCODED_TABLES
      37             : COSTABLE(16);
      38             : COSTABLE(32);
      39             : COSTABLE(64);
      40             : COSTABLE(128);
      41             : COSTABLE(256);
      42             : COSTABLE(512);
      43             : COSTABLE(1024);
      44             : COSTABLE(2048);
      45             : COSTABLE(4096);
      46             : COSTABLE(8192);
      47             : COSTABLE(16384);
      48             : COSTABLE(32768);
      49             : COSTABLE(65536);
      50             : #endif
      51             : COSTABLE_CONST FFTSample * const FFT_NAME(ff_cos_tabs)[] = {
      52             :     NULL, NULL, NULL, NULL,
      53             :     FFT_NAME(ff_cos_16),
      54             :     FFT_NAME(ff_cos_32),
      55             :     FFT_NAME(ff_cos_64),
      56             :     FFT_NAME(ff_cos_128),
      57             :     FFT_NAME(ff_cos_256),
      58             :     FFT_NAME(ff_cos_512),
      59             :     FFT_NAME(ff_cos_1024),
      60             :     FFT_NAME(ff_cos_2048),
      61             :     FFT_NAME(ff_cos_4096),
      62             :     FFT_NAME(ff_cos_8192),
      63             :     FFT_NAME(ff_cos_16384),
      64             :     FFT_NAME(ff_cos_32768),
      65             :     FFT_NAME(ff_cos_65536),
      66             : };
      67             : 
      68             : static void fft_permute_c(FFTContext *s, FFTComplex *z);
      69             : static void fft_calc_c(FFTContext *s, FFTComplex *z);
      70             : 
      71           0 : static int split_radix_permutation(int i, int n, int inverse)
      72             : {
      73             :     int m;
      74           0 :     if(n <= 2) return i&1;
      75           0 :     m = n >> 1;
      76           0 :     if(!(i&m))            return split_radix_permutation(i, m, inverse)*2;
      77           0 :     m >>= 1;
      78           0 :     if(inverse == !(i&m)) return split_radix_permutation(i, m, inverse)*4 + 1;
      79           0 :     else                  return split_radix_permutation(i, m, inverse)*4 - 1;
      80             : }
      81             : 
      82           0 : av_cold void ff_init_ff_cos_tabs(int index)
      83             : {
      84             : #if !CONFIG_HARDCODED_TABLES
      85             :     int i;
      86           0 :     int m = 1<<index;
      87           0 :     double freq = 2*M_PI/m;
      88           0 :     FFTSample *tab = FFT_NAME(ff_cos_tabs)[index];
      89           0 :     for(i=0; i<=m/4; i++)
      90           0 :         tab[i] = FIX15(cos(i*freq));
      91           0 :     for(i=1; i<m/4; i++)
      92           0 :         tab[m/2-i] = tab[i];
      93             : #endif
      94           0 : }
      95             : 
      96             : static const int avx_tab[] = {
      97             :     0, 4, 1, 5, 8, 12, 9, 13, 2, 6, 3, 7, 10, 14, 11, 15
      98             : };
      99             : 
     100           0 : static int is_second_half_of_fft32(int i, int n)
     101             : {
     102           0 :     if (n <= 32)
     103           0 :         return i >= 16;
     104           0 :     else if (i < n/2)
     105           0 :         return is_second_half_of_fft32(i, n/2);
     106           0 :     else if (i < 3*n/4)
     107           0 :         return is_second_half_of_fft32(i - n/2, n/4);
     108             :     else
     109           0 :         return is_second_half_of_fft32(i - 3*n/4, n/4);
     110             : }
     111             : 
     112           0 : static av_cold void fft_perm_avx(FFTContext *s)
     113             : {
     114             :     int i;
     115           0 :     int n = 1 << s->nbits;
     116             : 
     117           0 :     for (i = 0; i < n; i += 16) {
     118             :         int k;
     119           0 :         if (is_second_half_of_fft32(i, n)) {
     120           0 :             for (k = 0; k < 16; k++)
     121           0 :                 s->revtab[-split_radix_permutation(i + k, n, s->inverse) & (n - 1)] =
     122           0 :                     i + avx_tab[k];
     123             : 
     124             :         } else {
     125           0 :             for (k = 0; k < 16; k++) {
     126           0 :                 int j = i + k;
     127           0 :                 j = (j & ~7) | ((j >> 1) & 3) | ((j << 2) & 4);
     128           0 :                 s->revtab[-split_radix_permutation(i + k, n, s->inverse) & (n - 1)] = j;
     129             :             }
     130             :         }
     131             :     }
     132           0 : }
     133             : 
     134           0 : av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse)
     135             : {
     136             :     int i, j, n;
     137             : 
     138           0 :     if (nbits < 2 || nbits > 16)
     139             :         goto fail;
     140           0 :     s->nbits = nbits;
     141           0 :     n = 1 << nbits;
     142             : 
     143           0 :     s->revtab = av_malloc(n * sizeof(uint16_t));
     144           0 :     if (!s->revtab)
     145           0 :         goto fail;
     146           0 :     s->tmp_buf = av_malloc(n * sizeof(FFTComplex));
     147           0 :     if (!s->tmp_buf)
     148           0 :         goto fail;
     149           0 :     s->inverse = inverse;
     150           0 :     s->fft_permutation = FF_FFT_PERM_DEFAULT;
     151             : 
     152           0 :     s->fft_permute = fft_permute_c;
     153           0 :     s->fft_calc    = fft_calc_c;
     154             : #if CONFIG_MDCT
     155             :     s->imdct_calc  = ff_imdct_calc_c;
     156             :     s->imdct_half  = ff_imdct_half_c;
     157             :     s->mdct_calc   = ff_mdct_calc_c;
     158             : #endif
     159             : 
     160             : #if FFT_FLOAT
     161             :     if (ARCH_AARCH64) ff_fft_init_aarch64(s);
     162             :     if (ARCH_ARM)     ff_fft_init_arm(s);
     163             :     if (ARCH_PPC)     ff_fft_init_ppc(s);
     164           0 :     if (ARCH_X86)     ff_fft_init_x86(s);
     165             :     if (CONFIG_MDCT)  s->mdct_calcw = s->mdct_calc;
     166             : #else
     167             :     if (CONFIG_MDCT)  s->mdct_calcw = ff_mdct_calcw_c;
     168             :     if (ARCH_ARM)     ff_fft_fixed_init_arm(s);
     169             : #endif
     170             : 
     171           0 :     for(j=4; j<=nbits; j++) {
     172           0 :         ff_init_ff_cos_tabs(j);
     173             :     }
     174             : 
     175           0 :     if (s->fft_permutation == FF_FFT_PERM_AVX) {
     176           0 :         fft_perm_avx(s);
     177             :     } else {
     178           0 :         for(i=0; i<n; i++) {
     179           0 :             int j = i;
     180           0 :             if (s->fft_permutation == FF_FFT_PERM_SWAP_LSBS)
     181           0 :                 j = (j&~3) | ((j>>1)&1) | ((j<<1)&2);
     182           0 :             s->revtab[-split_radix_permutation(i, n, s->inverse) & (n-1)] = j;
     183             :         }
     184             :     }
     185             : 
     186           0 :     return 0;
     187             :  fail:
     188           0 :     av_freep(&s->revtab);
     189           0 :     av_freep(&s->tmp_buf);
     190           0 :     return -1;
     191             : }
     192             : 
     193           0 : static void fft_permute_c(FFTContext *s, FFTComplex *z)
     194             : {
     195             :     int j, np;
     196           0 :     const uint16_t *revtab = s->revtab;
     197           0 :     np = 1 << s->nbits;
     198             :     /* TODO: handle split-radix permute in a more optimal way, probably in-place */
     199           0 :     for(j=0;j<np;j++) s->tmp_buf[revtab[j]] = z[j];
     200           0 :     memcpy(z, s->tmp_buf, np * sizeof(FFTComplex));
     201           0 : }
     202             : 
     203           0 : av_cold void ff_fft_end(FFTContext *s)
     204             : {
     205           0 :     av_freep(&s->revtab);
     206           0 :     av_freep(&s->tmp_buf);
     207           0 : }
     208             : 
     209             : #define BUTTERFLIES(a0,a1,a2,a3) {\
     210             :     BF(t3, t5, t5, t1);\
     211             :     BF(a2.re, a0.re, a0.re, t5);\
     212             :     BF(a3.im, a1.im, a1.im, t3);\
     213             :     BF(t4, t6, t2, t6);\
     214             :     BF(a3.re, a1.re, a1.re, t4);\
     215             :     BF(a2.im, a0.im, a0.im, t6);\
     216             : }
     217             : 
     218             : // force loading all the inputs before storing any.
     219             : // this is slightly slower for small data, but avoids store->load aliasing
     220             : // for addresses separated by large powers of 2.
     221             : #define BUTTERFLIES_BIG(a0,a1,a2,a3) {\
     222             :     FFTSample r0=a0.re, i0=a0.im, r1=a1.re, i1=a1.im;\
     223             :     BF(t3, t5, t5, t1);\
     224             :     BF(a2.re, a0.re, r0, t5);\
     225             :     BF(a3.im, a1.im, i1, t3);\
     226             :     BF(t4, t6, t2, t6);\
     227             :     BF(a3.re, a1.re, r1, t4);\
     228             :     BF(a2.im, a0.im, i0, t6);\
     229             : }
     230             : 
     231             : #define TRANSFORM(a0,a1,a2,a3,wre,wim) {\
     232             :     CMUL(t1, t2, a2.re, a2.im, wre, -wim);\
     233             :     CMUL(t5, t6, a3.re, a3.im, wre,  wim);\
     234             :     BUTTERFLIES(a0,a1,a2,a3)\
     235             : }
     236             : 
     237             : #define TRANSFORM_ZERO(a0,a1,a2,a3) {\
     238             :     t1 = a2.re;\
     239             :     t2 = a2.im;\
     240             :     t5 = a3.re;\
     241             :     t6 = a3.im;\
     242             :     BUTTERFLIES(a0,a1,a2,a3)\
     243             : }
     244             : 
     245             : /* z[0...8n-1], w[1...2n-1] */
     246             : #define PASS(name)\
     247             : static void name(FFTComplex *z, const FFTSample *wre, unsigned int n)\
     248             : {\
     249             :     FFTDouble t1, t2, t3, t4, t5, t6;\
     250             :     int o1 = 2*n;\
     251             :     int o2 = 4*n;\
     252             :     int o3 = 6*n;\
     253             :     const FFTSample *wim = wre+o1;\
     254             :     n--;\
     255             : \
     256             :     TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3]);\
     257             :     TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\
     258             :     do {\
     259             :         z += 2;\
     260             :         wre += 2;\
     261             :         wim -= 2;\
     262             :         TRANSFORM(z[0],z[o1],z[o2],z[o3],wre[0],wim[0]);\
     263             :         TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\
     264             :     } while(--n);\
     265             : }
     266             : 
     267           0 : PASS(pass)
     268             : #undef BUTTERFLIES
     269             : #define BUTTERFLIES BUTTERFLIES_BIG
     270           0 : PASS(pass_big)
     271             : 
     272             : #define DECL_FFT(n,n2,n4)\
     273             : static void fft##n(FFTComplex *z)\
     274             : {\
     275             :     fft##n2(z);\
     276             :     fft##n4(z+n4*2);\
     277             :     fft##n4(z+n4*3);\
     278             :     pass(z,FFT_NAME(ff_cos_##n),n4/2);\
     279             : }
     280             : 
     281           0 : static void fft4(FFTComplex *z)
     282             : {
     283             :     FFTDouble t1, t2, t3, t4, t5, t6, t7, t8;
     284             : 
     285           0 :     BF(t3, t1, z[0].re, z[1].re);
     286           0 :     BF(t8, t6, z[3].re, z[2].re);
     287           0 :     BF(z[2].re, z[0].re, t1, t6);
     288           0 :     BF(t4, t2, z[0].im, z[1].im);
     289           0 :     BF(t7, t5, z[2].im, z[3].im);
     290           0 :     BF(z[3].im, z[1].im, t4, t8);
     291           0 :     BF(z[3].re, z[1].re, t3, t7);
     292           0 :     BF(z[2].im, z[0].im, t2, t5);
     293           0 : }
     294             : 
     295           0 : static void fft8(FFTComplex *z)
     296             : {
     297             :     FFTDouble t1, t2, t3, t4, t5, t6;
     298             : 
     299           0 :     fft4(z);
     300             : 
     301           0 :     BF(t1, z[5].re, z[4].re, -z[5].re);
     302           0 :     BF(t2, z[5].im, z[4].im, -z[5].im);
     303           0 :     BF(t5, z[7].re, z[6].re, -z[7].re);
     304           0 :     BF(t6, z[7].im, z[6].im, -z[7].im);
     305             : 
     306           0 :     BUTTERFLIES(z[0],z[2],z[4],z[6]);
     307           0 :     TRANSFORM(z[1],z[3],z[5],z[7],sqrthalf,sqrthalf);
     308           0 : }
     309             : 
     310             : #if !CONFIG_SMALL
     311           0 : static void fft16(FFTComplex *z)
     312             : {
     313             :     FFTDouble t1, t2, t3, t4, t5, t6;
     314           0 :     FFTSample cos_16_1 = FFT_NAME(ff_cos_16)[1];
     315           0 :     FFTSample cos_16_3 = FFT_NAME(ff_cos_16)[3];
     316             : 
     317           0 :     fft8(z);
     318           0 :     fft4(z+8);
     319           0 :     fft4(z+12);
     320             : 
     321           0 :     TRANSFORM_ZERO(z[0],z[4],z[8],z[12]);
     322           0 :     TRANSFORM(z[2],z[6],z[10],z[14],sqrthalf,sqrthalf);
     323           0 :     TRANSFORM(z[1],z[5],z[9],z[13],cos_16_1,cos_16_3);
     324           0 :     TRANSFORM(z[3],z[7],z[11],z[15],cos_16_3,cos_16_1);
     325           0 : }
     326             : #else
     327             : DECL_FFT(16,8,4)
     328             : #endif
     329           0 : DECL_FFT(32,16,8)
     330           0 : DECL_FFT(64,32,16)
     331           0 : DECL_FFT(128,64,32)
     332           0 : DECL_FFT(256,128,64)
     333           0 : DECL_FFT(512,256,128)
     334             : #if !CONFIG_SMALL
     335             : #define pass pass_big
     336             : #endif
     337           0 : DECL_FFT(1024,512,256)
     338           0 : DECL_FFT(2048,1024,512)
     339           0 : DECL_FFT(4096,2048,1024)
     340           0 : DECL_FFT(8192,4096,2048)
     341           0 : DECL_FFT(16384,8192,4096)
     342           0 : DECL_FFT(32768,16384,8192)
     343           0 : DECL_FFT(65536,32768,16384)
     344             : 
     345             : static void (* const fft_dispatch[])(FFTComplex*) = {
     346             :     fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024,
     347             :     fft2048, fft4096, fft8192, fft16384, fft32768, fft65536,
     348             : };
     349             : 
     350           0 : static void fft_calc_c(FFTContext *s, FFTComplex *z)
     351             : {
     352           0 :     fft_dispatch[s->nbits-2](z);
     353           0 : }

Generated by: LCOV version 1.13