Coverage Report

Created: 2026-10-28 08:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opus/celt/kiss_fft.c
Line
Count
Source
1
/*Copyright (c) 2003-2004, Mark Borgerding
2
  Lots of modifications by Jean-Marc Valin
3
  Copyright (c) 2005-2007, Xiph.Org Foundation
4
  Copyright (c) 2008,      Xiph.Org Foundation, CSIRO
5
6
  All rights reserved.
7
8
  Redistribution and use in source and binary forms, with or without
9
   modification, are permitted provided that the following conditions are met:
10
11
    * Redistributions of source code must retain the above copyright notice,
12
       this list of conditions and the following disclaimer.
13
    * Redistributions in binary form must reproduce the above copyright notice,
14
       this list of conditions and the following disclaimer in the
15
       documentation and/or other materials provided with the distribution.
16
17
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
  POSSIBILITY OF SUCH DAMAGE.*/
28
29
/* This code is originally from Mark Borgerding's KISS-FFT but has been
30
   heavily modified to better suit Opus */
31
32
#ifndef SKIP_CONFIG_H
33
#  ifdef HAVE_CONFIG_H
34
#    include "config.h"
35
#  endif
36
#endif
37
38
#include "_kiss_fft_guts.h"
39
#include "arch.h"
40
#include "os_support.h"
41
#include "mathops.h"
42
#include "stack_alloc.h"
43
44
#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API)
45
#define OPUS_CUSTOM 1
46
#endif
47
48
49
#if defined(ENABLE_PFA)
50
extern void opus_fft_pfa_c(const kiss_fft_state *st, const kiss_fft_cpx *fin, kiss_fft_cpx *fout ARG_FIXED(int downshift));
51
extern void opus_ifft_pfa_c(const kiss_fft_state *st, const kiss_fft_cpx *fin, kiss_fft_cpx *fout ARG_FIXED(int fft_shift));
52
#endif
53
54
#ifndef M_PI
55
#define M_PI 3.141592653
56
#endif
57
58
/* The guts header contains all the multiplication and addition macros that are defined for
59
   complex numbers.  It also declares the kf_ internal functions.
60
*/
61
62
#if !defined(ENABLE_PFA) || defined(OPUS_CUSTOM) || defined(ENABLE_DEEP_PLC)
63
static void kf_bfly2(
64
                     kiss_fft_cpx * Fout,
65
                     int m,
66
                     int N
67
                    )
68
77.7k
{
69
77.7k
   kiss_fft_cpx * Fout2;
70
77.7k
   int i;
71
77.7k
   (void)m;
72
#ifdef CUSTOM_MODES
73
   if (m==1)
74
   {
75
      celt_assert(m==1);
76
      for (i=0;i<N;i++)
77
      {
78
         kiss_fft_cpx t;
79
         Fout2 = Fout + 1;
80
         t = *Fout2;
81
         C_SUB( *Fout2 ,  *Fout , t );
82
         C_ADDTO( *Fout ,  t );
83
         Fout += 2;
84
      }
85
   } else
86
#endif
87
77.7k
   {
88
77.7k
      celt_coef tw;
89
77.7k
      tw = QCONST32(0.7071067812f, COEF_SHIFT-1);
90
      /* We know that m==4 here because the radix-2 is just after a radix-4 */
91
77.7k
      celt_assert(m==4);
92
3.46M
      for (i=0;i<N;i++)
93
3.38M
      {
94
3.38M
         kiss_fft_cpx t;
95
3.38M
         Fout2 = Fout + 4;
96
3.38M
         t = Fout2[0];
97
3.38M
         C_SUB( Fout2[0] ,  Fout[0] , t );
98
3.38M
         C_ADDTO( Fout[0] ,  t );
99
100
3.38M
         t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
101
3.38M
         t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
102
3.38M
         C_SUB( Fout2[1] ,  Fout[1] , t );
103
3.38M
         C_ADDTO( Fout[1] ,  t );
104
105
3.38M
         t.r = Fout2[2].i;
106
3.38M
         t.i = NEG32_ovflw(Fout2[2].r);
107
3.38M
         C_SUB( Fout2[2] ,  Fout[2] , t );
108
3.38M
         C_ADDTO( Fout[2] ,  t );
109
110
3.38M
         t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
111
3.38M
         t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw);
112
3.38M
         C_SUB( Fout2[3] ,  Fout[3] , t );
113
3.38M
         C_ADDTO( Fout[3] ,  t );
114
3.38M
         Fout += 8;
115
3.38M
      }
116
77.7k
   }
117
77.7k
}
118
119
static void kf_bfly4(
120
                     kiss_fft_cpx * Fout,
121
                     const size_t fstride,
122
                     const kiss_fft_state *st,
123
                     int m,
124
                     int N,
125
                     int mm
126
                    )
127
547k
{
128
547k
   int i;
129
130
547k
   if (m==1)
131
328k
   {
132
      /* Degenerate case where all the twiddles are 1. */
133
18.5M
      for (i=0;i<N;i++)
134
18.1M
      {
135
18.1M
         kiss_fft_cpx scratch0, scratch1;
136
137
18.1M
         C_SUB( scratch0 , *Fout, Fout[2] );
138
18.1M
         C_ADDTO(*Fout, Fout[2]);
139
18.1M
         C_ADD( scratch1 , Fout[1] , Fout[3] );
140
18.1M
         C_SUB( Fout[2], *Fout, scratch1 );
141
18.1M
         C_ADDTO( *Fout , scratch1 );
142
18.1M
         C_SUB( scratch1 , Fout[1] , Fout[3] );
143
144
18.1M
         Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
145
18.1M
         Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
146
18.1M
         Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
147
18.1M
         Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
148
18.1M
         Fout+=4;
149
18.1M
      }
150
328k
   } else {
151
219k
      int j;
152
219k
      kiss_fft_cpx scratch[6];
153
219k
      const kiss_twiddle_cpx *tw1,*tw2,*tw3;
154
219k
      const int m2=2*m;
155
219k
      const int m3=3*m;
156
219k
      kiss_fft_cpx * Fout_beg = Fout;
157
3.51M
      for (i=0;i<N;i++)
158
3.29M
      {
159
3.29M
         Fout = Fout_beg + i*mm;
160
3.29M
         tw3 = tw2 = tw1 = st->twiddles;
161
         /* m is guaranteed to be a multiple of 4. */
162
19.4M
         for (j=0;j<m;j++)
163
16.1M
         {
164
16.1M
            C_MUL(scratch[0],Fout[m] , *tw1 );
165
16.1M
            C_MUL(scratch[1],Fout[m2] , *tw2 );
166
16.1M
            C_MUL(scratch[2],Fout[m3] , *tw3 );
167
168
16.1M
            C_SUB( scratch[5] , *Fout, scratch[1] );
169
16.1M
            C_ADDTO(*Fout, scratch[1]);
170
16.1M
            C_ADD( scratch[3] , scratch[0] , scratch[2] );
171
16.1M
            C_SUB( scratch[4] , scratch[0] , scratch[2] );
172
16.1M
            C_SUB( Fout[m2], *Fout, scratch[3] );
173
16.1M
            tw1 += fstride;
174
16.1M
            tw2 += fstride*2;
175
16.1M
            tw3 += fstride*3;
176
16.1M
            C_ADDTO( *Fout , scratch[3] );
177
178
16.1M
            Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
179
16.1M
            Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
180
16.1M
            Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
181
16.1M
            Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
182
16.1M
            ++Fout;
183
16.1M
         }
184
3.29M
      }
185
219k
   }
186
547k
}
187
188
189
#ifndef RADIX_TWO_ONLY
190
191
static void kf_bfly3(
192
                     kiss_fft_cpx * Fout,
193
                     const size_t fstride,
194
                     const kiss_fft_state *st,
195
                     int m,
196
                     int N,
197
                     int mm
198
                    )
199
328k
{
200
328k
   int i;
201
328k
   size_t k;
202
328k
   const size_t m2 = 2*m;
203
328k
   const kiss_twiddle_cpx *tw1,*tw2;
204
328k
   kiss_fft_cpx scratch[5];
205
328k
   kiss_twiddle_cpx epi3;
206
207
328k
   kiss_fft_cpx * Fout_beg = Fout;
208
#ifdef FIXED_POINT
209
   /*epi3.r = -16384;*/ /* Unused */
210
   epi3.i = -QCONST32(0.86602540f, COEF_SHIFT-1);
211
#else
212
328k
   epi3 = st->twiddles[fstride*m];
213
328k
#endif
214
1.96M
   for (i=0;i<N;i++)
215
1.64M
   {
216
1.64M
      Fout = Fout_beg + i*mm;
217
1.64M
      tw1=tw2=st->twiddles;
218
      /* For non-custom modes, m is guaranteed to be a multiple of 4. */
219
1.64M
      k=m;
220
24.2M
      do {
221
222
24.2M
         C_MUL(scratch[1],Fout[m] , *tw1);
223
24.2M
         C_MUL(scratch[2],Fout[m2] , *tw2);
224
225
24.2M
         C_ADD(scratch[3],scratch[1],scratch[2]);
226
24.2M
         C_SUB(scratch[0],scratch[1],scratch[2]);
227
24.2M
         tw1 += fstride;
228
24.2M
         tw2 += fstride*2;
229
230
24.2M
         Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r));
231
24.2M
         Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i));
232
233
24.2M
         C_MULBYSCALAR( scratch[0] , epi3.i );
234
235
24.2M
         C_ADDTO(*Fout,scratch[3]);
236
237
24.2M
         Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i);
238
24.2M
         Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r);
239
240
24.2M
         Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i);
241
24.2M
         Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r);
242
243
24.2M
         ++Fout;
244
24.2M
      } while(--k);
245
1.64M
   }
246
328k
}
247
248
249
#ifndef OVERRIDE_kf_bfly5
250
static void kf_bfly5(
251
                     kiss_fft_cpx * Fout,
252
                     const size_t fstride,
253
                     const kiss_fft_state *st,
254
                     int m,
255
                     int N,
256
                     int mm
257
                    )
258
328k
{
259
328k
   kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
260
328k
   int i, u;
261
328k
   kiss_fft_cpx scratch[13];
262
328k
   const kiss_twiddle_cpx *tw;
263
328k
   kiss_twiddle_cpx ya,yb;
264
328k
   kiss_fft_cpx * Fout_beg = Fout;
265
266
#ifdef FIXED_POINT
267
   ya.r = QCONST32(0.30901699f, COEF_SHIFT-1);
268
   ya.i = -QCONST32(0.95105652f, COEF_SHIFT-1);
269
   yb.r = -QCONST32(0.80901699f, COEF_SHIFT-1);
270
   yb.i = -QCONST32(0.58778525f, COEF_SHIFT-1);
271
#else
272
328k
   ya = st->twiddles[fstride*m];
273
328k
   yb = st->twiddles[fstride*2*m];
274
328k
#endif
275
328k
   tw=st->twiddles;
276
277
656k
   for (i=0;i<N;i++)
278
328k
   {
279
328k
      Fout = Fout_beg + i*mm;
280
328k
      Fout0=Fout;
281
328k
      Fout1=Fout0+m;
282
328k
      Fout2=Fout0+2*m;
283
328k
      Fout3=Fout0+3*m;
284
328k
      Fout4=Fout0+4*m;
285
286
      /* For non-custom modes, m is guaranteed to be a multiple of 4. */
287
14.8M
      for ( u=0; u<m; ++u ) {
288
14.5M
         scratch[0] = *Fout0;
289
290
14.5M
         C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
291
14.5M
         C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
292
14.5M
         C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
293
14.5M
         C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
294
295
14.5M
         C_ADD( scratch[7],scratch[1],scratch[4]);
296
14.5M
         C_SUB( scratch[10],scratch[1],scratch[4]);
297
14.5M
         C_ADD( scratch[8],scratch[2],scratch[3]);
298
14.5M
         C_SUB( scratch[9],scratch[2],scratch[3]);
299
300
14.5M
         Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r));
301
14.5M
         Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i));
302
303
14.5M
         scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r)));
304
14.5M
         scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r)));
305
306
14.5M
         scratch[6].r =  ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i));
307
14.5M
         scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i)));
308
309
14.5M
         C_SUB(*Fout1,scratch[5],scratch[6]);
310
14.5M
         C_ADD(*Fout4,scratch[5],scratch[6]);
311
312
14.5M
         scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r)));
313
14.5M
         scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r)));
314
14.5M
         scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i));
315
14.5M
         scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i));
316
317
14.5M
         C_ADD(*Fout2,scratch[11],scratch[12]);
318
14.5M
         C_SUB(*Fout3,scratch[11],scratch[12]);
319
320
14.5M
         ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
321
14.5M
      }
322
328k
   }
323
328k
}
324
#endif /* OVERRIDE_kf_bfly5 */
325
326
327
#endif
328
329
330
#ifdef CUSTOM_MODES
331
332
static
333
void compute_bitrev_table(
334
         int Fout,
335
         opus_int16 *f,
336
         const size_t fstride,
337
         int in_stride,
338
         opus_int16 * factors,
339
         const kiss_fft_state *st
340
            )
341
{
342
   const int p=*factors++; /* the radix  */
343
   const int m=*factors++; /* stage's fft length/p */
344
345
    /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
346
   if (m==1)
347
   {
348
      int j;
349
      for (j=0;j<p;j++)
350
      {
351
         *f = Fout+j;
352
         f += fstride*in_stride;
353
      }
354
   } else {
355
      int j;
356
      for (j=0;j<p;j++)
357
      {
358
         compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
359
         f += fstride*in_stride;
360
         Fout += m;
361
      }
362
   }
363
}
364
365
/*  facbuf is populated by p1,m1,p2,m2, ...
366
    where
367
    p[i] * m[i] = m[i-1]
368
    m0 = n                  */
369
static
370
int kf_factor(int n,opus_int16 * facbuf)
371
{
372
    int p=4;
373
    int i;
374
    int stages=0;
375
    int nbak = n;
376
377
    /*factor out powers of 4, powers of 2, then any remaining primes */
378
    do {
379
        while (n % p) {
380
            switch (p) {
381
                case 4: p = 2; break;
382
                case 2: p = 3; break;
383
                default: p += 2; break;
384
            }
385
            if (p>32000 || (opus_int32)p*(opus_int32)p > n)
386
                p = n;          /* no more factors, skip to end */
387
        }
388
        n /= p;
389
#ifdef RADIX_TWO_ONLY
390
        if (p!=2 && p != 4)
391
#else
392
        if (p>5)
393
#endif
394
        {
395
           return 0;
396
        }
397
        facbuf[2*stages] = p;
398
        if (p==2 && stages > 1)
399
        {
400
           facbuf[2*stages] = 4;
401
           facbuf[2] = 2;
402
        }
403
        stages++;
404
    } while (n > 1);
405
    n = nbak;
406
    /* Reverse the order to get the radix 4 at the end, so we can use the
407
       fast degenerate case. It turns out that reversing the order also
408
       improves the noise behaviour. */
409
    for (i=0;i<stages/2;i++)
410
    {
411
       int tmp;
412
       tmp = facbuf[2*i];
413
       facbuf[2*i] = facbuf[2*(stages-i-1)];
414
       facbuf[2*(stages-i-1)] = tmp;
415
    }
416
    for (i=0;i<stages;i++)
417
    {
418
        n /= facbuf[2*i];
419
        facbuf[2*i+1] = n;
420
    }
421
    return 1;
422
}
423
424
static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
425
{
426
   int i;
427
#ifdef FIXED_POINT
428
   for (i=0;i<nfft;++i) {
429
      opus_val32 phase = -i;
430
#ifdef ENABLE_QEXT
431
      twiddles[i].r = (int)MIN32(2147483647, floor(.5+2147483648*cos((2*M_PI/nfft)*phase)));
432
      twiddles[i].i = (int)MIN32(2147483647, floor(.5+2147483648*sin((2*M_PI/nfft)*phase)));
433
#else
434
      kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
435
#endif
436
   }
437
#else
438
   for (i=0;i<nfft;++i) {
439
      const double pi=3.14159265358979323846264338327;
440
      double phase = ( -2*pi /nfft ) * i;
441
      kf_cexp(twiddles+i, phase );
442
   }
443
#endif
444
}
445
446
int opus_fft_alloc_arch_c(kiss_fft_state *st) {
447
   (void)st;
448
   return 0;
449
}
450
451
/*
452
 *
453
 * Allocates all necessary storage space for the fft and ifft.
454
 * The return value is a contiguous block of memory.  As such,
455
 * It can be freed with free().
456
 * */
457
kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,
458
                                        const kiss_fft_state *base, int arch)
459
{
460
    kiss_fft_state *st=NULL;
461
    size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
462
463
    if ( lenmem==NULL ) {
464
        st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
465
    }else{
466
        if (mem != NULL && *lenmem >= memneeded)
467
            st = (kiss_fft_state*)mem;
468
        *lenmem = memneeded;
469
    }
470
    if (st) {
471
        opus_int16 *bitrev;
472
        kiss_twiddle_cpx *twiddles;
473
474
        st->nfft=nfft;
475
#ifdef FIXED_POINT
476
        st->scale_shift = celt_ilog2(st->nfft);
477
# ifdef ENABLE_QEXT
478
        if (st->nfft == 1<<st->scale_shift)
479
           st->scale = QCONST32(1.0f, 30);
480
        else
481
           st->scale = (((opus_int64)1073741824<<st->scale_shift)+st->nfft/2)/st->nfft;
482
# else
483
        if (st->nfft == 1<<st->scale_shift)
484
           st->scale = Q15ONE;
485
        else
486
           st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift);
487
# endif
488
#else
489
        st->scale = 1.f/nfft;
490
#endif
491
#if defined(ENABLE_PFA)
492
        if (nfft == 60 || nfft == 120 || nfft == 240 || nfft == 480
493
#if defined(ENABLE_QEXT)
494
            || nfft == 960
495
#endif
496
           )
497
        {
498
           st->twiddles = NULL;
499
           st->shift = -1;
500
           st->bitrev = NULL;
501
        } else
502
#endif
503
        {
504
           if (base != NULL && base->twiddles != NULL)
505
           {
506
              st->twiddles = base->twiddles;
507
              st->shift = 0;
508
              while (st->shift < 32 && nfft<<st->shift != base->nfft)
509
                 st->shift++;
510
              if (st->shift>=32)
511
                 goto fail;
512
           } else {
513
              st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
514
              compute_twiddles(twiddles, nfft);
515
              st->shift = -1;
516
           }
517
           if (!kf_factor(nfft,st->factors))
518
           {
519
              goto fail;
520
           }
521
522
           /* bitrev */
523
           st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nfft);
524
           if (st->bitrev==NULL)
525
               goto fail;
526
           compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
527
        }
528
529
        /* Initialize architecture specific fft parameters */
530
        if (opus_fft_alloc_arch(st, arch))
531
            goto fail;
532
    }
533
    return st;
534
fail:
535
    opus_fft_free(st, arch);
536
    return NULL;
537
}
538
539
kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch)
540
{
541
   return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch);
542
}
543
544
void opus_fft_free_arch_c(kiss_fft_state *st) {
545
   (void)st;
546
}
547
548
void opus_fft_free(const kiss_fft_state *cfg, int arch)
549
{
550
   if (cfg)
551
   {
552
      opus_fft_free_arch((kiss_fft_state *)cfg, arch);
553
      opus_free((opus_int16*)cfg->bitrev);
554
      if (cfg->shift < 0)
555
         opus_free((kiss_twiddle_cpx*)cfg->twiddles);
556
      opus_free((kiss_fft_state*)cfg);
557
   }
558
}
559
560
#endif /* CUSTOM_MODES */
561
562
#if !defined(ENABLE_PFA) || defined(OPUS_CUSTOM) || defined(ENABLE_DEEP_PLC)
563
#ifdef FIXED_POINT
564
#ifndef OVERRIDE_fft_downshift
565
static void fft_downshift(kiss_fft_cpx *x, int N, int *total, int step) {
566
   int shift;
567
   shift = IMIN(step, *total);
568
   *total -= shift;
569
   if (shift == 1) {
570
      int i;
571
      for (i=0;i<N;i++) {
572
         x[i].r = SHR32(x[i].r, 1);
573
         x[i].i = SHR32(x[i].i, 1);
574
      }
575
   } else if (shift>0) {
576
      int i;
577
      for (i=0;i<N;i++) {
578
         x[i].r = PSHR32(x[i].r, shift);
579
         x[i].i = PSHR32(x[i].i, shift);
580
      }
581
   }
582
}
583
#endif /* OVERRIDE_fft_downshift */
584
#else
585
#define fft_downshift(x, N, total, step)
586
#endif
587
588
void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout ARG_FIXED(int downshift))
589
328k
{
590
328k
    int m2, m;
591
328k
    int p;
592
328k
    int L;
593
328k
    int fstride[MAXFACTORS];
594
328k
    int i;
595
328k
    int shift;
596
597
    /* st->shift can be -1 */
598
328k
    shift = st->shift>0 ? st->shift : 0;
599
600
328k
    fstride[0] = 1;
601
328k
    L=0;
602
1.28M
    do {
603
1.28M
       p = st->factors[2*L];
604
1.28M
       m = st->factors[2*L+1];
605
1.28M
       fstride[L+1] = fstride[L]*p;
606
1.28M
       L++;
607
1.28M
    } while(m!=1);
608
328k
    m = st->factors[2*L-1];
609
1.60M
    for (i=L-1;i>=0;i--)
610
1.28M
    {
611
1.28M
       if (i!=0)
612
953k
          m2 = st->factors[2*i-1];
613
328k
       else
614
328k
          m2 = 1;
615
1.28M
       switch (st->factors[2*i])
616
1.28M
       {
617
77.7k
       case 2:
618
77.7k
          fft_downshift(fout, st->nfft, &downshift, 1);
619
77.7k
          kf_bfly2(fout, m, fstride[i]);
620
77.7k
          break;
621
547k
       case 4:
622
547k
          fft_downshift(fout, st->nfft, &downshift, 2);
623
547k
          kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2);
624
547k
          break;
625
0
 #ifndef RADIX_TWO_ONLY
626
328k
       case 3:
627
328k
          fft_downshift(fout, st->nfft, &downshift, 2);
628
328k
          kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
629
328k
          break;
630
328k
       case 5:
631
328k
          fft_downshift(fout, st->nfft, &downshift, 3);
632
328k
          kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
633
328k
          break;
634
1.28M
 #endif
635
1.28M
       }
636
1.28M
       m = m2;
637
1.28M
    }
638
328k
    fft_downshift(fout, st->nfft, &downshift, downshift);
639
328k
}
640
#endif /* !ENABLE_PFA || OPUS_CUSTOM || ENABLE_DEEP_PLC */
641
#endif
642
643
void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
644
0
{
645
#if defined(ENABLE_PFA)
646
   if (st->nfft == 60 || st->nfft == 120 || st->nfft == 240 || st->nfft == 480
647
#if defined(ENABLE_QEXT)
648
       || st->nfft == 960
649
#endif
650
      )
651
   {
652
      int i;
653
      celt_coef scale = st->scale;
654
      VARDECL(kiss_fft_cpx, tmp);
655
      SAVE_STACK;
656
      ALLOC(tmp, st->nfft, kiss_fft_cpx);
657
      for (i = 0; i < st->nfft; i++) {
658
#ifndef FIXED_POINT
659
         tmp[i].r = fin[i].r * scale;
660
         tmp[i].i = fin[i].i * scale;
661
#else
662
         tmp[i].r = S_MUL2(fin[i].r, scale);
663
         tmp[i].i = S_MUL2(fin[i].i, scale);
664
#endif
665
      }
666
      opus_fft_pfa_c(st, tmp, fout ARG_FIXED(st->scale_shift - 1));
667
      RESTORE_STACK;
668
      return;
669
   }
670
#if !defined(OPUS_CUSTOM) && !defined(ENABLE_DEEP_PLC)
671
   celt_assert2(0, "PFA FFT called with unsupported size in non-custom mode");
672
#endif
673
#endif
674
675
0
#if !defined(ENABLE_PFA) || defined(OPUS_CUSTOM) || defined(ENABLE_DEEP_PLC)
676
0
   int i;
677
0
   celt_coef scale;
678
#ifdef FIXED_POINT
679
   /* Allows us to scale with MULT16_32_Q16(), which is faster than
680
      MULT16_32_Q15() on ARM. */
681
   int scale_shift = st->scale_shift-1;
682
#endif
683
0
   scale = st->scale;
684
685
0
   celt_assert2 (fin != fout, "In-place FFT not supported");
686
   /* Bit-reverse the input */
687
0
   for (i=0;i<st->nfft;i++)
688
0
   {
689
0
      kiss_fft_cpx x = fin[i];
690
0
      fout[st->bitrev[i]].r = S_MUL2(x.r, scale);
691
0
      fout[st->bitrev[i]].i = S_MUL2(x.i, scale);
692
0
   }
693
0
   opus_fft_impl(st, fout ARG_FIXED(scale_shift));
694
0
#endif
695
0
}
696
697
698
void opus_ifft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
699
0
{
700
#if defined(ENABLE_PFA)
701
   if (st->nfft == 60 || st->nfft == 120 || st->nfft == 240 || st->nfft == 480
702
#if defined(ENABLE_QEXT)
703
       || st->nfft == 960
704
#endif
705
      )
706
   {
707
      opus_ifft_pfa_c(st, fin, fout ARG_FIXED(0));
708
      return;
709
   }
710
#if !defined(OPUS_CUSTOM) && !defined(ENABLE_DEEP_PLC)
711
   celt_assert2(0, "PFA IFFT called with unsupported size in non-custom mode");
712
#endif
713
#endif
714
715
0
#if !defined(ENABLE_PFA) || defined(OPUS_CUSTOM) || defined(ENABLE_DEEP_PLC)
716
0
   int i;
717
0
   celt_assert2 (fin != fout, "In-place FFT not supported");
718
   /* Bit-reverse the input */
719
0
   for (i=0;i<st->nfft;i++)
720
0
      fout[st->bitrev[i]] = fin[i];
721
0
   for (i=0;i<st->nfft;i++)
722
0
      fout[i].i = -fout[i].i;
723
0
   opus_fft_impl(st, fout ARG_FIXED(0));
724
0
   for (i=0;i<st->nfft;i++)
725
0
      fout[i].i = -fout[i].i;
726
0
#endif
727
0
}