//// AudioFOA.cpp// libraries/audio/src//// Created by Ken Cooke on 10/28/16.// Copyright 2016 High Fidelity, Inc.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "AudioFOA.h" #include <string.h>#include <assert.h> #include "AudioFOAData.h" #if defined(_MSC_VER)#define ALIGN32 __declspec(align(32))#elif defined(__GNUC__)#define ALIGN32 __attribute__((aligned(32)))#else#define ALIGN32#endif //// Vectorized FFT based on radix 2/4/8 Stockham auto-sort// scalar reference version//typedef struct { float re; float im;} complex_t; static const float SQRT1_2 = 0.707106781f; // 1/sqrt(2) static const complex_t w_fft_256_0[] = { { 1.000000000e+00f, 0.000000000e+00f }, { 9.238795042e-01f, 3.826834261e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, { 0.000000000e+00f, 1.000000000e+00f }, {-3.826834261e-01f, 9.238795042e-01f }, {-7.071067691e-01f, 7.071067691e-01f }, {-9.238795042e-01f, 3.826834261e-01f }, }; static const complex_t w_fft_256_1[] = { { 1.000000000e+00f, 0.000000000e+00f }, { 1.000000000e+00f, 0.000000000e+00f }, { 1.000000000e+00f, 0.000000000e+00f }, { 9.951847196e-01f, 9.801714122e-02f }, { 9.807852507e-01f, 1.950903237e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 9.807852507e-01f, 1.950903237e-01f }, { 9.238795042e-01f, 3.826834261e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, { 9.238795042e-01f, 3.826834261e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, { 8.819212914e-01f, 4.713967443e-01f }, { 5.555702448e-01f, 8.314695954e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, {-1.950903237e-01f, 9.807852507e-01f }, { 7.730104327e-01f, 6.343932748e-01f }, { 1.950903237e-01f, 9.807852507e-01f }, {-4.713967443e-01f, 8.819212914e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 0.000000000e+00f, 1.000000000e+00f }, {-7.071067691e-01f, 7.071067691e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, {-1.950903237e-01f, 9.807852507e-01f }, {-8.819212914e-01f, 4.713967443e-01f }, { 5.555702448e-01f, 8.314695954e-01f }, {-3.826834261e-01f, 9.238795042e-01f }, {-9.807852507e-01f, 1.950903237e-01f }, { 4.713967443e-01f, 8.819212914e-01f }, {-5.555702448e-01f, 8.314695954e-01f }, {-9.951847196e-01f,-9.801714122e-02f }, { 3.826834261e-01f, 9.238795042e-01f }, {-7.071067691e-01f, 7.071067691e-01f }, {-9.238795042e-01f,-3.826834261e-01f }, { 2.902846634e-01f, 9.569403529e-01f }, {-8.314695954e-01f, 5.555702448e-01f }, {-7.730104327e-01f,-6.343932748e-01f }, { 1.950903237e-01f, 9.807852507e-01f }, {-9.238795042e-01f, 3.826834261e-01f }, {-5.555702448e-01f,-8.314695954e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, {-9.807852507e-01f, 1.950903237e-01f }, {-2.902846634e-01f,-9.569403529e-01f }, }; static const complex_t w_fft_256_2[] = { { 1.000000000e+00f, 0.000000000e+00f }, { 1.000000000e+00f, 0.000000000e+00f }, { 1.000000000e+00f, 0.000000000e+00f }, { 9.996988177e-01f, 2.454122901e-02f }, { 9.987954497e-01f, 4.906767607e-02f }, { 9.972904325e-01f, 7.356456667e-02f }, { 9.987954497e-01f, 4.906767607e-02f }, { 9.951847196e-01f, 9.801714122e-02f }, { 9.891765118e-01f, 1.467304677e-01f }, { 9.972904325e-01f, 7.356456667e-02f }, { 9.891765118e-01f, 1.467304677e-01f }, { 9.757021070e-01f, 2.191012353e-01f }, { 9.951847196e-01f, 9.801714122e-02f }, { 9.807852507e-01f, 1.950903237e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 9.924795628e-01f, 1.224106774e-01f }, { 9.700312614e-01f, 2.429801822e-01f }, { 9.329928160e-01f, 3.598950505e-01f }, { 9.891765118e-01f, 1.467304677e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 9.039893150e-01f, 4.275550842e-01f }, { 9.852776527e-01f, 1.709618866e-01f }, { 9.415440559e-01f, 3.368898630e-01f }, { 8.700869679e-01f, 4.928981960e-01f }, { 9.807852507e-01f, 1.950903237e-01f }, { 9.238795042e-01f, 3.826834261e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 9.757021070e-01f, 2.191012353e-01f }, { 9.039893150e-01f, 4.275550842e-01f }, { 7.883464098e-01f, 6.152315736e-01f }, { 9.700312614e-01f, 2.429801822e-01f }, { 8.819212914e-01f, 4.713967443e-01f }, { 7.409511209e-01f, 6.715589762e-01f }, { 9.637760520e-01f, 2.667127550e-01f }, { 8.577286005e-01f, 5.141027570e-01f }, { 6.895405650e-01f, 7.242470980e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, { 9.495281577e-01f, 3.136817515e-01f }, { 8.032075167e-01f, 5.956993103e-01f }, { 5.758081675e-01f, 8.175848126e-01f }, { 9.415440559e-01f, 3.368898630e-01f }, { 7.730104327e-01f, 6.343932748e-01f }, { 5.141027570e-01f, 8.577286005e-01f }, { 9.329928160e-01f, 3.598950505e-01f }, { 7.409511209e-01f, 6.715589762e-01f }, { 4.496113360e-01f, 8.932242990e-01f }, { 9.238795042e-01f, 3.826834261e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, { 9.142097831e-01f, 4.052413106e-01f }, { 6.715589762e-01f, 7.409511209e-01f }, { 3.136817515e-01f, 9.495281577e-01f }, { 9.039893150e-01f, 4.275550842e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, { 2.429801822e-01f, 9.700312614e-01f }, { 8.932242990e-01f, 4.496113360e-01f }, { 5.956993103e-01f, 8.032075167e-01f }, { 1.709618866e-01f, 9.852776527e-01f }, { 8.819212914e-01f, 4.713967443e-01f }, { 5.555702448e-01f, 8.314695954e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, { 8.700869679e-01f, 4.928981960e-01f }, { 5.141027570e-01f, 8.577286005e-01f }, { 2.454122901e-02f, 9.996988177e-01f }, { 8.577286005e-01f, 5.141027570e-01f }, { 4.713967443e-01f, 8.819212914e-01f }, {-4.906767607e-02f, 9.987954497e-01f }, { 8.448535800e-01f, 5.349976420e-01f }, { 4.275550842e-01f, 9.039893150e-01f }, {-1.224106774e-01f, 9.924795628e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, {-1.950903237e-01f, 9.807852507e-01f }, { 8.175848126e-01f, 5.758081675e-01f }, { 3.368898630e-01f, 9.415440559e-01f }, {-2.667127550e-01f, 9.637760520e-01f }, { 8.032075167e-01f, 5.956993103e-01f }, { 2.902846634e-01f, 9.569403529e-01f }, {-3.368898630e-01f, 9.415440559e-01f }, { 7.883464098e-01f, 6.152315736e-01f }, { 2.429801822e-01f, 9.700312614e-01f }, {-4.052413106e-01f, 9.142097831e-01f }, { 7.730104327e-01f, 6.343932748e-01f }, { 1.950903237e-01f, 9.807852507e-01f }, {-4.713967443e-01f, 8.819212914e-01f }, { 7.572088242e-01f, 6.531728506e-01f }, { 1.467304677e-01f, 9.891765118e-01f }, {-5.349976420e-01f, 8.448535800e-01f }, { 7.409511209e-01f, 6.715589762e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, {-5.956993103e-01f, 8.032075167e-01f }, { 7.242470980e-01f, 6.895405650e-01f }, { 4.906767607e-02f, 9.987954497e-01f }, {-6.531728506e-01f, 7.572088242e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 0.000000000e+00f, 1.000000000e+00f }, {-7.071067691e-01f, 7.071067691e-01f }, { 6.895405650e-01f, 7.242470980e-01f }, {-4.906767607e-02f, 9.987954497e-01f }, {-7.572088242e-01f, 6.531728506e-01f }, { 6.715589762e-01f, 7.409511209e-01f }, {-9.801714122e-02f, 9.951847196e-01f }, {-8.032075167e-01f, 5.956993103e-01f }, { 6.531728506e-01f, 7.572088242e-01f }, {-1.467304677e-01f, 9.891765118e-01f }, {-8.448535800e-01f, 5.349976420e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, {-1.950903237e-01f, 9.807852507e-01f }, {-8.819212914e-01f, 4.713967443e-01f }, { 6.152315736e-01f, 7.883464098e-01f }, {-2.429801822e-01f, 9.700312614e-01f }, {-9.142097831e-01f, 4.052413106e-01f }, { 5.956993103e-01f, 8.032075167e-01f }, {-2.902846634e-01f, 9.569403529e-01f }, {-9.415440559e-01f, 3.368898630e-01f }, { 5.758081675e-01f, 8.175848126e-01f }, {-3.368898630e-01f, 9.415440559e-01f }, {-9.637760520e-01f, 2.667127550e-01f }, { 5.555702448e-01f, 8.314695954e-01f }, {-3.826834261e-01f, 9.238795042e-01f }, {-9.807852507e-01f, 1.950903237e-01f }, { 5.349976420e-01f, 8.448535800e-01f }, {-4.275550842e-01f, 9.039893150e-01f }, {-9.924795628e-01f, 1.224106774e-01f }, { 5.141027570e-01f, 8.577286005e-01f }, {-4.713967443e-01f, 8.819212914e-01f }, {-9.987954497e-01f, 4.906767607e-02f }, { 4.928981960e-01f, 8.700869679e-01f }, {-5.141027570e-01f, 8.577286005e-01f }, {-9.996988177e-01f,-2.454122901e-02f }, { 4.713967443e-01f, 8.819212914e-01f }, {-5.555702448e-01f, 8.314695954e-01f }, {-9.951847196e-01f,-9.801714122e-02f }, { 4.496113360e-01f, 8.932242990e-01f }, {-5.956993103e-01f, 8.032075167e-01f }, {-9.852776527e-01f,-1.709618866e-01f }, { 4.275550842e-01f, 9.039893150e-01f }, {-6.343932748e-01f, 7.730104327e-01f }, {-9.700312614e-01f,-2.429801822e-01f }, { 4.052413106e-01f, 9.142097831e-01f }, {-6.715589762e-01f, 7.409511209e-01f }, {-9.495281577e-01f,-3.136817515e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, {-7.071067691e-01f, 7.071067691e-01f }, {-9.238795042e-01f,-3.826834261e-01f }, { 3.598950505e-01f, 9.329928160e-01f }, {-7.409511209e-01f, 6.715589762e-01f }, {-8.932242990e-01f,-4.496113360e-01f }, { 3.368898630e-01f, 9.415440559e-01f }, {-7.730104327e-01f, 6.343932748e-01f }, {-8.577286005e-01f,-5.141027570e-01f }, { 3.136817515e-01f, 9.495281577e-01f }, {-8.032075167e-01f, 5.956993103e-01f }, {-8.175848126e-01f,-5.758081675e-01f }, { 2.902846634e-01f, 9.569403529e-01f }, {-8.314695954e-01f, 5.555702448e-01f }, {-7.730104327e-01f,-6.343932748e-01f }, { 2.667127550e-01f, 9.637760520e-01f }, {-8.577286005e-01f, 5.141027570e-01f }, {-7.242470980e-01f,-6.895405650e-01f }, { 2.429801822e-01f, 9.700312614e-01f }, {-8.819212914e-01f, 4.713967443e-01f }, {-6.715589762e-01f,-7.409511209e-01f }, { 2.191012353e-01f, 9.757021070e-01f }, {-9.039893150e-01f, 4.275550842e-01f }, {-6.152315736e-01f,-7.883464098e-01f }, { 1.950903237e-01f, 9.807852507e-01f }, {-9.238795042e-01f, 3.826834261e-01f }, {-5.555702448e-01f,-8.314695954e-01f }, { 1.709618866e-01f, 9.852776527e-01f }, {-9.415440559e-01f, 3.368898630e-01f }, {-4.928981960e-01f,-8.700869679e-01f }, { 1.467304677e-01f, 9.891765118e-01f }, {-9.569403529e-01f, 2.902846634e-01f }, {-4.275550842e-01f,-9.039893150e-01f }, { 1.224106774e-01f, 9.924795628e-01f }, {-9.700312614e-01f, 2.429801822e-01f }, {-3.598950505e-01f,-9.329928160e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, {-9.807852507e-01f, 1.950903237e-01f }, {-2.902846634e-01f,-9.569403529e-01f }, { 7.356456667e-02f, 9.972904325e-01f }, {-9.891765118e-01f, 1.467304677e-01f }, {-2.191012353e-01f,-9.757021070e-01f }, { 4.906767607e-02f, 9.987954497e-01f }, {-9.951847196e-01f, 9.801714122e-02f }, {-1.467304677e-01f,-9.891765118e-01f }, { 2.454122901e-02f, 9.996988177e-01f }, {-9.987954497e-01f, 4.906767607e-02f }, {-7.356456667e-02f,-9.972904325e-01f }, }; static complex_t w_rfft_512[] = { {-4.999623597e-01f, 4.938642383e-01f }, {-4.998494089e-01f, 4.877293706e-01f }, {-4.996611774e-01f, 4.815963805e-01f }, {-4.993977249e-01f, 4.754661620e-01f }, {-4.990590513e-01f, 4.693396389e-01f }, {-4.986452162e-01f, 4.632177055e-01f }, {-4.981563091e-01f, 4.571013451e-01f }, {-4.975923598e-01f, 4.509914219e-01f }, {-4.969534874e-01f, 4.448888898e-01f }, {-4.962397814e-01f, 4.387946725e-01f }, {-4.954513311e-01f, 4.327096343e-01f }, {-4.945882559e-01f, 4.266347587e-01f }, {-4.936507046e-01f, 4.205709100e-01f }, {-4.926388264e-01f, 4.145190716e-01f }, {-4.915527403e-01f, 4.084800482e-01f }, {-4.903926253e-01f, 4.024548531e-01f }, {-4.891586900e-01f, 3.964443207e-01f }, {-4.878510535e-01f, 3.904493749e-01f }, {-4.864699841e-01f, 3.844709396e-01f }, {-4.850156307e-01f, 3.785099089e-01f }, {-4.834882319e-01f, 3.725671768e-01f }, {-4.818880260e-01f, 3.666436076e-01f }, {-4.802152514e-01f, 3.607401550e-01f }, {-4.784701765e-01f, 3.548576832e-01f }, {-4.766530097e-01f, 3.489970267e-01f }, {-4.747640789e-01f, 3.431591392e-01f }, {-4.728036523e-01f, 3.373448551e-01f }, {-4.707720280e-01f, 3.315550685e-01f }, {-4.686695039e-01f, 3.257906437e-01f }, {-4.664964080e-01f, 3.200524747e-01f }, {-4.642530382e-01f, 3.143413961e-01f }, {-4.619397521e-01f, 3.086583018e-01f }, {-4.595569372e-01f, 3.030039668e-01f }, {-4.571048915e-01f, 2.973793447e-01f }, {-4.545840025e-01f, 2.917852402e-01f }, {-4.519946575e-01f, 2.862224579e-01f }, {-4.493372440e-01f, 2.806918621e-01f }, {-4.466121495e-01f, 2.751943469e-01f }, {-4.438198209e-01f, 2.697306275e-01f }, {-4.409606457e-01f, 2.643016279e-01f }, {-4.380350411e-01f, 2.589080930e-01f }, {-4.350434840e-01f, 2.535508871e-01f }, {-4.319864213e-01f, 2.482308149e-01f }, {-4.288643003e-01f, 2.429486215e-01f }, {-4.256775975e-01f, 2.377051711e-01f }, {-4.224267900e-01f, 2.325011790e-01f }, {-4.191123545e-01f, 2.273375094e-01f }, {-4.157347977e-01f, 2.222148776e-01f }, {-4.122946560e-01f, 2.171340883e-01f }, {-4.087924063e-01f, 2.120959163e-01f }, {-4.052285850e-01f, 2.071010768e-01f }, {-4.016037583e-01f, 2.021503448e-01f }, {-3.979184628e-01f, 1.972444654e-01f }, {-3.941732049e-01f, 1.923842132e-01f }, {-3.903686106e-01f, 1.875702441e-01f }, {-3.865052164e-01f, 1.828033626e-01f }, {-3.825836182e-01f, 1.780842245e-01f }, {-3.786044121e-01f, 1.734135747e-01f }, {-3.745681942e-01f, 1.687920988e-01f }, {-3.704755604e-01f, 1.642205119e-01f }, {-3.663271368e-01f, 1.596994996e-01f }, {-3.621235490e-01f, 1.552297175e-01f }, {-3.578654230e-01f, 1.508118808e-01f }, {-3.535533845e-01f, 1.464466155e-01f }, {-3.491881192e-01f, 1.421345770e-01f }, {-3.447702825e-01f, 1.378764510e-01f }, {-3.403005004e-01f, 1.336728632e-01f }, {-3.357794881e-01f, 1.295244396e-01f }, {-3.312079012e-01f, 1.254318058e-01f }, {-3.265864253e-01f, 1.213955879e-01f }, {-3.219157755e-01f, 1.174163818e-01f }, {-3.171966374e-01f, 1.134947836e-01f }, {-3.124297559e-01f, 1.096313894e-01f }, {-3.076157868e-01f, 1.058267951e-01f }, {-3.027555346e-01f, 1.020815372e-01f }, {-2.978496552e-01f, 9.839624166e-02f }, {-2.928989232e-01f, 9.477141500e-02f }, {-2.879040837e-01f, 9.120759368e-02f }, {-2.828659117e-01f, 8.770534396e-02f }, {-2.777851224e-01f, 8.426520228e-02f }, {-2.726624906e-01f, 8.088764548e-02f }, {-2.674988210e-01f, 7.757321000e-02f }, {-2.622948289e-01f, 7.432240248e-02f }, {-2.570513785e-01f, 7.113569975e-02f }, {-2.517691851e-01f, 6.801357865e-02f }, {-2.464490980e-01f, 6.495651603e-02f }, {-2.410918921e-01f, 6.196495891e-02f }, {-2.356983721e-01f, 5.903935432e-02f }, {-2.302693576e-01f, 5.618017912e-02f }, {-2.248056680e-01f, 5.338785052e-02f }, {-2.193081230e-01f, 5.066275597e-02f }, {-2.137775421e-01f, 4.800534248e-02f }, {-2.082147747e-01f, 4.541599751e-02f }, {-2.026206553e-01f, 4.289510846e-02f }, {-1.969960183e-01f, 4.044306278e-02f }, {-1.913417131e-01f, 3.806024790e-02f }, {-1.856586039e-01f, 3.574696183e-02f }, {-1.799475253e-01f, 3.350359201e-02f }, {-1.742093414e-01f, 3.133049607e-02f }, {-1.684449315e-01f, 2.922797203e-02f }, {-1.626551449e-01f, 2.719634771e-02f }, {-1.568408757e-01f, 2.523592114e-02f }, {-1.510029733e-01f, 2.334699035e-02f }, {-1.451423317e-01f, 2.152982354e-02f }, {-1.392598450e-01f, 1.978474855e-02f }, {-1.333563775e-01f, 1.811197400e-02f }, {-1.274328232e-01f, 1.651176810e-02f }, {-1.214900911e-01f, 1.498436928e-02f }, {-1.155290529e-01f, 1.353001595e-02f }, {-1.095506176e-01f, 1.214894652e-02f }, {-1.035556868e-01f, 1.084131002e-02f }, {-9.754516184e-02f, 9.607374668e-03f }, {-9.151994437e-02f, 8.447259665e-03f }, {-8.548094332e-02f, 7.361173630e-03f }, {-7.942907512e-02f, 6.349295378e-03f }, {-7.336523384e-02f, 5.411744118e-03f }, {-6.729035079e-02f, 4.548668861e-03f }, {-6.120533869e-02f, 3.760218620e-03f }, {-5.511110276e-02f, 3.046512604e-03f }, {-4.900857061e-02f, 2.407640219e-03f }, {-4.289865494e-02f, 1.843690872e-03f }, {-3.678228334e-02f, 1.354783773e-03f }, {-3.066036850e-02f, 9.409487247e-04f }, {-2.453383803e-02f, 6.022751331e-04f }, {-1.840361208e-02f, 3.388226032e-04f }, {-1.227061450e-02f, 1.505911350e-04f }, {-6.135769188e-03f, 3.764033318e-05f }, {-0.000000000e+00f, 0.000000000e+00f }, }; // x[n] in interleaved order// y[n] in interleaved order// n >= 2static void fft_radix2_pass(complex_t* x, complex_t* y, const complex_t* w, int n, int p) { size_t t = n/2; assert(n >= 1); assert(p >= 1); complex_t* xp0 = &x[0*t]; complex_t* xp1 = &x[1*t]; complex_t* yp0 = &y[0*p]; complex_t* yp1 = &y[1*p]; for (size_t i = 0; i < t; i++) { size_t k = i & (p-1); // twiddle index size_t j = 2*(i-k) + k; // output index float ar0 = xp0[i].re; float ai0 = xp0[i].im; float ar1 = xp1[i].re; float ai1 = xp1[i].im; float wr1 = w[k].re; float wi1 = w[k].im; float br1 = ar1 * wr1; float bi1 = ai1 * wr1; br1 += ai1 * wi1; bi1 -= ar1 * wi1; float cr0 = ar0 + br1; float ci0 = ai0 + bi1; float cr1 = ar0 - br1; float ci1 = ai0 - bi1; yp0[j].re = cr0; yp0[j].im = ci0; yp1[j].re = cr1; yp1[j].im = ci1; }} // x[n] in interleaved order// y[n] in interleaved order// n >= 4static void fft_radix4_pass(complex_t* x, complex_t* y, const complex_t* w, int n, int p) { size_t t = n/4; assert(n >= 1); assert(p >= 1); complex_t* xp0 = &x[0*t]; complex_t* xp1 = &x[1*t]; complex_t* xp2 = &x[2*t]; complex_t* xp3 = &x[3*t]; complex_t* yp0 = &y[0*p]; complex_t* yp1 = &y[1*p]; complex_t* yp2 = &y[2*p]; complex_t* yp3 = &y[3*p]; for (size_t i = 0; i < t; i++) { size_t k = i & (p-1); // twiddle index size_t j = 4*(i-k) + k; // output index float ar1 = xp1[i].re; float ai1 = xp1[i].im; float ar2 = xp2[i].re; float ai2 = xp2[i].im; float ar3 = xp3[i].re; float ai3 = xp3[i].im; float wr1 = w[3*k+0].re; float wi1 = w[3*k+0].im; float wr2 = w[3*k+1].re; float wi2 = w[3*k+1].im; float wr3 = w[3*k+2].re; float wi3 = w[3*k+2].im; float br1 = ar1 * wr1; float bi1 = ai1 * wr1; float br2 = ar2 * wr2; float bi2 = ai2 * wr2; float br3 = ar3 * wr3; float bi3 = ai3 * wr3; br1 += ai1 * wi1; bi1 -= ar1 * wi1; br2 += ai2 * wi2; bi2 -= ar2 * wi2; br3 += ai3 * wi3; bi3 -= ar3 * wi3; float ar0 = xp0[i].re; float ai0 = xp0[i].im; float cr0 = ar0 + br2; float ci0 = ai0 + bi2; float cr2 = ar0 - br2; float ci2 = ai0 - bi2; float cr1 = br1 + br3; float ci1 = bi1 + bi3; float cr3 = br1 - br3; float ci3 = bi1 - bi3; float dr0 = cr0 + cr1; float di0 = ci0 + ci1; float dr1 = cr2 + ci3; float di1 = ci2 - cr3; float dr2 = cr0 - cr1; float di2 = ci0 - ci1; float dr3 = cr2 - ci3; float di3 = ci2 + cr3; yp0[j].re = dr0; yp0[j].im = di0; yp1[j].re = dr1; yp1[j].im = di1; yp2[j].re = dr2; yp2[j].im = di2; yp3[j].re = dr3; yp3[j].im = di3; }} static auto& fft_radix4_last = fft_radix4_pass; // x[n] in interleaved order// y[n] in interleaved order// n >= 4static void ifft_radix4_last(complex_t* x, complex_t* y, const complex_t* w, int n, int p) { size_t t = n/4; assert(n >= 1); assert(p >= 1); complex_t* xp0 = &x[0*t]; complex_t* xp1 = &x[1*t]; complex_t* xp2 = &x[2*t]; complex_t* xp3 = &x[3*t]; complex_t* yp0 = &y[0*p]; complex_t* yp1 = &y[1*p]; complex_t* yp2 = &y[2*p]; complex_t* yp3 = &y[3*p]; for (size_t i = 0; i < t; i++) { size_t k = i & (p-1); // twiddle index size_t j = 4*(i-k) + k; // output index float ar1 = xp1[i].re; float ai1 = xp1[i].im; float ar2 = xp2[i].re; float ai2 = xp2[i].im; float ar3 = xp3[i].re; float ai3 = xp3[i].im; float wr1 = w[3*k+0].re; float wi1 = w[3*k+0].im; float wr2 = w[3*k+1].re; float wi2 = w[3*k+1].im; float wr3 = w[3*k+2].re; float wi3 = w[3*k+2].im; float br1 = ar1 * wr1; float bi1 = ai1 * wr1; float br2 = ar2 * wr2; float bi2 = ai2 * wr2; float br3 = ar3 * wr3; float bi3 = ai3 * wr3; br1 += ai1 * wi1; bi1 -= ar1 * wi1; br2 += ai2 * wi2; bi2 -= ar2 * wi2; br3 += ai3 * wi3; bi3 -= ar3 * wi3; float ar0 = xp0[i].re; float ai0 = xp0[i].im; float cr0 = ar0 + br2; float ci0 = ai0 + bi2; float cr2 = ar0 - br2; float ci2 = ai0 - bi2; float cr1 = br1 + br3; float ci1 = bi1 + bi3; float cr3 = br1 - br3; float ci3 = bi1 - bi3; float dr0 = cr0 + cr1; float di0 = ci0 + ci1; float dr1 = cr2 + ci3; float di1 = ci2 - cr3; float dr2 = cr0 - cr1; float di2 = ci0 - ci1; float dr3 = cr2 - ci3; float di3 = ci2 + cr3; float scale = 1.0f/n; // scaled by 1/n for ifft dr0 *= scale; di0 *= scale; dr1 *= scale; di1 *= scale; dr2 *= scale; di2 *= scale; dr3 *= scale; di3 *= scale; yp0[j].re = di0; // swapped re,im for ifft yp0[j].im = dr0; yp1[j].re = di1; yp1[j].im = dr1; yp2[j].re = di2; yp2[j].im = dr2; yp3[j].re = di3; yp3[j].im = dr3; }} // x[n] in interleaved order// y[n] in interleaved order// n >= 8static void fft_radix8_first(complex_t* x, complex_t* y, int n, int p) { size_t t = n/8; assert(t >= 1); assert(p == 1); complex_t* xp0 = &x[0*t]; complex_t* xp1 = &x[1*t]; complex_t* xp2 = &x[2*t]; complex_t* xp3 = &x[3*t]; complex_t* xp4 = &x[4*t]; complex_t* xp5 = &x[5*t]; complex_t* xp6 = &x[6*t]; complex_t* xp7 = &x[7*t]; for (size_t i = 0; i < t; i++) { // // even // float ar0 = xp0[i].re; float ai0 = xp0[i].im; float ar2 = xp2[i].re; float ai2 = xp2[i].im; float ar4 = xp4[i].re; float ai4 = xp4[i].im; float ar6 = xp6[i].re; float ai6 = xp6[i].im; float cr0 = ar0 + ar4; float ci0 = ai0 + ai4; float cr2 = ar2 + ar6; float ci2 = ai2 + ai6; float cr4 = ar0 - ar4; float ci4 = ai0 - ai4; float cr6 = ar2 - ar6; float ci6 = ai2 - ai6; float dr0 = cr0 + cr2; float di0 = ci0 + ci2; float dr2 = cr0 - cr2; float di2 = ci0 - ci2; float dr4 = cr4 + ci6; float di4 = ci4 - cr6; float dr6 = cr4 - ci6; float di6 = ci4 + cr6; // // odd // float ar1 = xp1[i].re; float ai1 = xp1[i].im; float ar3 = xp3[i].re; float ai3 = xp3[i].im; float ar5 = xp5[i].re; float ai5 = xp5[i].im; float ar7 = xp7[i].re; float ai7 = xp7[i].im; float br1 = ar1 + ar5; float bi1 = ai1 + ai5; float br3 = ar3 + ar7; float bi3 = ai3 + ai7; float br5 = ar1 - ar5; float bi5 = ai1 - ai5; float br7 = ar3 - ar7; float bi7 = ai3 - ai7; float cr1 = br1; float ci1 = bi1;Lines 1–500 of 1129. Load more
// // AudioFOA.cpp // libraries/audio/src // // Created by Ken Cooke on 10/28/16. // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "AudioFOA.h" #include <string.h> #include <assert.h> #include "AudioFOAData.h" #if defined(_MSC_VER) #define ALIGN32 __declspec(align(32)) #elif defined(__GNUC__) #define ALIGN32 __attribute__((aligned(32))) #else #define ALIGN32 #endif // // Vectorized FFT based on radix 2/4/8 Stockham auto-sort // scalar reference version // typedef struct { float re; float im; } complex_t; static const float SQRT1_2 = 0.707106781f; // 1/sqrt(2) static const complex_t w_fft_256_0[] = { { 1.000000000e+00f, 0.000000000e+00f }, { 9.238795042e-01f, 3.826834261e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, { 0.000000000e+00f, 1.000000000e+00f }, {-3.826834261e-01f, 9.238795042e-01f }, {-7.071067691e-01f, 7.071067691e-01f }, {-9.238795042e-01f, 3.826834261e-01f }, }; static const complex_t w_fft_256_1[] = { { 1.000000000e+00f, 0.000000000e+00f }, { 1.000000000e+00f, 0.000000000e+00f }, { 1.000000000e+00f, 0.000000000e+00f }, { 9.951847196e-01f, 9.801714122e-02f }, { 9.807852507e-01f, 1.950903237e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 9.807852507e-01f, 1.950903237e-01f }, { 9.238795042e-01f, 3.826834261e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, { 9.238795042e-01f, 3.826834261e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, { 8.819212914e-01f, 4.713967443e-01f }, { 5.555702448e-01f, 8.314695954e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, {-1.950903237e-01f, 9.807852507e-01f }, { 7.730104327e-01f, 6.343932748e-01f }, { 1.950903237e-01f, 9.807852507e-01f }, {-4.713967443e-01f, 8.819212914e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 0.000000000e+00f, 1.000000000e+00f }, {-7.071067691e-01f, 7.071067691e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, {-1.950903237e-01f, 9.807852507e-01f }, {-8.819212914e-01f, 4.713967443e-01f }, { 5.555702448e-01f, 8.314695954e-01f }, {-3.826834261e-01f, 9.238795042e-01f }, {-9.807852507e-01f, 1.950903237e-01f }, { 4.713967443e-01f, 8.819212914e-01f }, {-5.555702448e-01f, 8.314695954e-01f }, {-9.951847196e-01f,-9.801714122e-02f }, { 3.826834261e-01f, 9.238795042e-01f }, {-7.071067691e-01f, 7.071067691e-01f }, {-9.238795042e-01f,-3.826834261e-01f }, { 2.902846634e-01f, 9.569403529e-01f }, {-8.314695954e-01f, 5.555702448e-01f }, {-7.730104327e-01f,-6.343932748e-01f }, { 1.950903237e-01f, 9.807852507e-01f }, {-9.238795042e-01f, 3.826834261e-01f }, {-5.555702448e-01f,-8.314695954e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, {-9.807852507e-01f, 1.950903237e-01f }, {-2.902846634e-01f,-9.569403529e-01f }, }; static const complex_t w_fft_256_2[] = { { 1.000000000e+00f, 0.000000000e+00f }, { 1.000000000e+00f, 0.000000000e+00f }, { 1.000000000e+00f, 0.000000000e+00f }, { 9.996988177e-01f, 2.454122901e-02f }, { 9.987954497e-01f, 4.906767607e-02f }, { 9.972904325e-01f, 7.356456667e-02f }, { 9.987954497e-01f, 4.906767607e-02f }, { 9.951847196e-01f, 9.801714122e-02f }, { 9.891765118e-01f, 1.467304677e-01f }, { 9.972904325e-01f, 7.356456667e-02f }, { 9.891765118e-01f, 1.467304677e-01f }, { 9.757021070e-01f, 2.191012353e-01f }, { 9.951847196e-01f, 9.801714122e-02f }, { 9.807852507e-01f, 1.950903237e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 9.924795628e-01f, 1.224106774e-01f }, { 9.700312614e-01f, 2.429801822e-01f }, { 9.329928160e-01f, 3.598950505e-01f }, { 9.891765118e-01f, 1.467304677e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 9.039893150e-01f, 4.275550842e-01f }, { 9.852776527e-01f, 1.709618866e-01f }, { 9.415440559e-01f, 3.368898630e-01f }, { 8.700869679e-01f, 4.928981960e-01f }, { 9.807852507e-01f, 1.950903237e-01f }, { 9.238795042e-01f, 3.826834261e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 9.757021070e-01f, 2.191012353e-01f }, { 9.039893150e-01f, 4.275550842e-01f }, { 7.883464098e-01f, 6.152315736e-01f }, { 9.700312614e-01f, 2.429801822e-01f }, { 8.819212914e-01f, 4.713967443e-01f }, { 7.409511209e-01f, 6.715589762e-01f }, { 9.637760520e-01f, 2.667127550e-01f }, { 8.577286005e-01f, 5.141027570e-01f }, { 6.895405650e-01f, 7.242470980e-01f }, { 9.569403529e-01f, 2.902846634e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, { 9.495281577e-01f, 3.136817515e-01f }, { 8.032075167e-01f, 5.956993103e-01f }, { 5.758081675e-01f, 8.175848126e-01f }, { 9.415440559e-01f, 3.368898630e-01f }, { 7.730104327e-01f, 6.343932748e-01f }, { 5.141027570e-01f, 8.577286005e-01f }, { 9.329928160e-01f, 3.598950505e-01f }, { 7.409511209e-01f, 6.715589762e-01f }, { 4.496113360e-01f, 8.932242990e-01f }, { 9.238795042e-01f, 3.826834261e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, { 9.142097831e-01f, 4.052413106e-01f }, { 6.715589762e-01f, 7.409511209e-01f }, { 3.136817515e-01f, 9.495281577e-01f }, { 9.039893150e-01f, 4.275550842e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, { 2.429801822e-01f, 9.700312614e-01f }, { 8.932242990e-01f, 4.496113360e-01f }, { 5.956993103e-01f, 8.032075167e-01f }, { 1.709618866e-01f, 9.852776527e-01f }, { 8.819212914e-01f, 4.713967443e-01f }, { 5.555702448e-01f, 8.314695954e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, { 8.700869679e-01f, 4.928981960e-01f }, { 5.141027570e-01f, 8.577286005e-01f }, { 2.454122901e-02f, 9.996988177e-01f }, { 8.577286005e-01f, 5.141027570e-01f }, { 4.713967443e-01f, 8.819212914e-01f }, {-4.906767607e-02f, 9.987954497e-01f }, { 8.448535800e-01f, 5.349976420e-01f }, { 4.275550842e-01f, 9.039893150e-01f }, {-1.224106774e-01f, 9.924795628e-01f }, { 8.314695954e-01f, 5.555702448e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, {-1.950903237e-01f, 9.807852507e-01f }, { 8.175848126e-01f, 5.758081675e-01f }, { 3.368898630e-01f, 9.415440559e-01f }, {-2.667127550e-01f, 9.637760520e-01f }, { 8.032075167e-01f, 5.956993103e-01f }, { 2.902846634e-01f, 9.569403529e-01f }, {-3.368898630e-01f, 9.415440559e-01f }, { 7.883464098e-01f, 6.152315736e-01f }, { 2.429801822e-01f, 9.700312614e-01f }, {-4.052413106e-01f, 9.142097831e-01f }, { 7.730104327e-01f, 6.343932748e-01f }, { 1.950903237e-01f, 9.807852507e-01f }, {-4.713967443e-01f, 8.819212914e-01f }, { 7.572088242e-01f, 6.531728506e-01f }, { 1.467304677e-01f, 9.891765118e-01f }, {-5.349976420e-01f, 8.448535800e-01f }, { 7.409511209e-01f, 6.715589762e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, {-5.956993103e-01f, 8.032075167e-01f }, { 7.242470980e-01f, 6.895405650e-01f }, { 4.906767607e-02f, 9.987954497e-01f }, {-6.531728506e-01f, 7.572088242e-01f }, { 7.071067691e-01f, 7.071067691e-01f }, { 0.000000000e+00f, 1.000000000e+00f }, {-7.071067691e-01f, 7.071067691e-01f }, { 6.895405650e-01f, 7.242470980e-01f }, {-4.906767607e-02f, 9.987954497e-01f }, {-7.572088242e-01f, 6.531728506e-01f }, { 6.715589762e-01f, 7.409511209e-01f }, {-9.801714122e-02f, 9.951847196e-01f }, {-8.032075167e-01f, 5.956993103e-01f }, { 6.531728506e-01f, 7.572088242e-01f }, {-1.467304677e-01f, 9.891765118e-01f }, {-8.448535800e-01f, 5.349976420e-01f }, { 6.343932748e-01f, 7.730104327e-01f }, {-1.950903237e-01f, 9.807852507e-01f }, {-8.819212914e-01f, 4.713967443e-01f }, { 6.152315736e-01f, 7.883464098e-01f }, {-2.429801822e-01f, 9.700312614e-01f }, {-9.142097831e-01f, 4.052413106e-01f }, { 5.956993103e-01f, 8.032075167e-01f }, {-2.902846634e-01f, 9.569403529e-01f }, {-9.415440559e-01f, 3.368898630e-01f }, { 5.758081675e-01f, 8.175848126e-01f }, {-3.368898630e-01f, 9.415440559e-01f }, {-9.637760520e-01f, 2.667127550e-01f }, { 5.555702448e-01f, 8.314695954e-01f }, {-3.826834261e-01f, 9.238795042e-01f }, {-9.807852507e-01f, 1.950903237e-01f }, { 5.349976420e-01f, 8.448535800e-01f }, {-4.275550842e-01f, 9.039893150e-01f }, {-9.924795628e-01f, 1.224106774e-01f }, { 5.141027570e-01f, 8.577286005e-01f }, {-4.713967443e-01f, 8.819212914e-01f }, {-9.987954497e-01f, 4.906767607e-02f }, { 4.928981960e-01f, 8.700869679e-01f }, {-5.141027570e-01f, 8.577286005e-01f }, {-9.996988177e-01f,-2.454122901e-02f }, { 4.713967443e-01f, 8.819212914e-01f }, {-5.555702448e-01f, 8.314695954e-01f }, {-9.951847196e-01f,-9.801714122e-02f }, { 4.496113360e-01f, 8.932242990e-01f }, {-5.956993103e-01f, 8.032075167e-01f }, {-9.852776527e-01f,-1.709618866e-01f }, { 4.275550842e-01f, 9.039893150e-01f }, {-6.343932748e-01f, 7.730104327e-01f }, {-9.700312614e-01f,-2.429801822e-01f }, { 4.052413106e-01f, 9.142097831e-01f }, {-6.715589762e-01f, 7.409511209e-01f }, {-9.495281577e-01f,-3.136817515e-01f }, { 3.826834261e-01f, 9.238795042e-01f }, {-7.071067691e-01f, 7.071067691e-01f }, {-9.238795042e-01f,-3.826834261e-01f }, { 3.598950505e-01f, 9.329928160e-01f }, {-7.409511209e-01f, 6.715589762e-01f }, {-8.932242990e-01f,-4.496113360e-01f }, { 3.368898630e-01f, 9.415440559e-01f }, {-7.730104327e-01f, 6.343932748e-01f }, {-8.577286005e-01f,-5.141027570e-01f }, { 3.136817515e-01f, 9.495281577e-01f }, {-8.032075167e-01f, 5.956993103e-01f }, {-8.175848126e-01f,-5.758081675e-01f }, { 2.902846634e-01f, 9.569403529e-01f }, {-8.314695954e-01f, 5.555702448e-01f }, {-7.730104327e-01f,-6.343932748e-01f }, { 2.667127550e-01f, 9.637760520e-01f }, {-8.577286005e-01f, 5.141027570e-01f }, {-7.242470980e-01f,-6.895405650e-01f }, { 2.429801822e-01f, 9.700312614e-01f }, {-8.819212914e-01f, 4.713967443e-01f }, {-6.715589762e-01f,-7.409511209e-01f }, { 2.191012353e-01f, 9.757021070e-01f }, {-9.039893150e-01f, 4.275550842e-01f }, {-6.152315736e-01f,-7.883464098e-01f }, { 1.950903237e-01f, 9.807852507e-01f }, {-9.238795042e-01f, 3.826834261e-01f }, {-5.555702448e-01f,-8.314695954e-01f }, { 1.709618866e-01f, 9.852776527e-01f }, {-9.415440559e-01f, 3.368898630e-01f }, {-4.928981960e-01f,-8.700869679e-01f }, { 1.467304677e-01f, 9.891765118e-01f }, {-9.569403529e-01f, 2.902846634e-01f }, {-4.275550842e-01f,-9.039893150e-01f }, { 1.224106774e-01f, 9.924795628e-01f }, {-9.700312614e-01f, 2.429801822e-01f }, {-3.598950505e-01f,-9.329928160e-01f }, { 9.801714122e-02f, 9.951847196e-01f }, {-9.807852507e-01f, 1.950903237e-01f }, {-2.902846634e-01f,-9.569403529e-01f }, { 7.356456667e-02f, 9.972904325e-01f }, {-9.891765118e-01f, 1.467304677e-01f }, {-2.191012353e-01f,-9.757021070e-01f }, { 4.906767607e-02f, 9.987954497e-01f }, {-9.951847196e-01f, 9.801714122e-02f }, {-1.467304677e-01f,-9.891765118e-01f }, { 2.454122901e-02f, 9.996988177e-01f }, {-9.987954497e-01f, 4.906767607e-02f }, {-7.356456667e-02f,-9.972904325e-01f }, }; static complex_t w_rfft_512[] = { {-4.999623597e-01f, 4.938642383e-01f }, {-4.998494089e-01f, 4.877293706e-01f }, {-4.996611774e-01f, 4.815963805e-01f }, {-4.993977249e-01f, 4.754661620e-01f }, {-4.990590513e-01f, 4.693396389e-01f }, {-4.986452162e-01f, 4.632177055e-01f }, {-4.981563091e-01f, 4.571013451e-01f }, {-4.975923598e-01f, 4.509914219e-01f }, {-4.969534874e-01f, 4.448888898e-01f }, {-4.962397814e-01f, 4.387946725e-01f }, {-4.954513311e-01f, 4.327096343e-01f }, {-4.945882559e-01f, 4.266347587e-01f }, {-4.936507046e-01f, 4.205709100e-01f }, {-4.926388264e-01f, 4.145190716e-01f }, {-4.915527403e-01f, 4.084800482e-01f }, {-4.903926253e-01f, 4.024548531e-01f }, {-4.891586900e-01f, 3.964443207e-01f }, {-4.878510535e-01f, 3.904493749e-01f }, {-4.864699841e-01f, 3.844709396e-01f }, {-4.850156307e-01f, 3.785099089e-01f }, {-4.834882319e-01f, 3.725671768e-01f }, {-4.818880260e-01f, 3.666436076e-01f }, {-4.802152514e-01f, 3.607401550e-01f }, {-4.784701765e-01f, 3.548576832e-01f }, {-4.766530097e-01f, 3.489970267e-01f }, {-4.747640789e-01f, 3.431591392e-01f }, {-4.728036523e-01f, 3.373448551e-01f }, {-4.707720280e-01f, 3.315550685e-01f }, {-4.686695039e-01f, 3.257906437e-01f }, {-4.664964080e-01f, 3.200524747e-01f }, {-4.642530382e-01f, 3.143413961e-01f }, {-4.619397521e-01f, 3.086583018e-01f }, {-4.595569372e-01f, 3.030039668e-01f }, {-4.571048915e-01f, 2.973793447e-01f }, {-4.545840025e-01f, 2.917852402e-01f }, {-4.519946575e-01f, 2.862224579e-01f }, {-4.493372440e-01f, 2.806918621e-01f }, {-4.466121495e-01f, 2.751943469e-01f }, {-4.438198209e-01f, 2.697306275e-01f }, {-4.409606457e-01f, 2.643016279e-01f }, {-4.380350411e-01f, 2.589080930e-01f }, {-4.350434840e-01f, 2.535508871e-01f }, {-4.319864213e-01f, 2.482308149e-01f }, {-4.288643003e-01f, 2.429486215e-01f }, {-4.256775975e-01f, 2.377051711e-01f }, {-4.224267900e-01f, 2.325011790e-01f }, {-4.191123545e-01f, 2.273375094e-01f }, {-4.157347977e-01f, 2.222148776e-01f }, {-4.122946560e-01f, 2.171340883e-01f }, {-4.087924063e-01f, 2.120959163e-01f }, {-4.052285850e-01f, 2.071010768e-01f }, {-4.016037583e-01f, 2.021503448e-01f }, {-3.979184628e-01f, 1.972444654e-01f }, {-3.941732049e-01f, 1.923842132e-01f }, {-3.903686106e-01f, 1.875702441e-01f }, {-3.865052164e-01f, 1.828033626e-01f }, {-3.825836182e-01f, 1.780842245e-01f }, {-3.786044121e-01f, 1.734135747e-01f }, {-3.745681942e-01f, 1.687920988e-01f }, {-3.704755604e-01f, 1.642205119e-01f }, {-3.663271368e-01f, 1.596994996e-01f }, {-3.621235490e-01f, 1.552297175e-01f }, {-3.578654230e-01f, 1.508118808e-01f }, {-3.535533845e-01f, 1.464466155e-01f }, {-3.491881192e-01f, 1.421345770e-01f }, {-3.447702825e-01f, 1.378764510e-01f }, {-3.403005004e-01f, 1.336728632e-01f }, {-3.357794881e-01f, 1.295244396e-01f }, {-3.312079012e-01f, 1.254318058e-01f }, {-3.265864253e-01f, 1.213955879e-01f }, {-3.219157755e-01f, 1.174163818e-01f }, {-3.171966374e-01f, 1.134947836e-01f }, {-3.124297559e-01f, 1.096313894e-01f }, {-3.076157868e-01f, 1.058267951e-01f }, {-3.027555346e-01f, 1.020815372e-01f }, {-2.978496552e-01f, 9.839624166e-02f }, {-2.928989232e-01f, 9.477141500e-02f }, {-2.879040837e-01f, 9.120759368e-02f }, {-2.828659117e-01f, 8.770534396e-02f }, {-2.777851224e-01f, 8.426520228e-02f }, {-2.726624906e-01f, 8.088764548e-02f }, {-2.674988210e-01f, 7.757321000e-02f }, {-2.622948289e-01f, 7.432240248e-02f }, {-2.570513785e-01f, 7.113569975e-02f }, {-2.517691851e-01f, 6.801357865e-02f }, {-2.464490980e-01f, 6.495651603e-02f }, {-2.410918921e-01f, 6.196495891e-02f }, {-2.356983721e-01f, 5.903935432e-02f }, {-2.302693576e-01f, 5.618017912e-02f }, {-2.248056680e-01f, 5.338785052e-02f }, {-2.193081230e-01f, 5.066275597e-02f }, {-2.137775421e-01f, 4.800534248e-02f }, {-2.082147747e-01f, 4.541599751e-02f }, {-2.026206553e-01f, 4.289510846e-02f }, {-1.969960183e-01f, 4.044306278e-02f }, {-1.913417131e-01f, 3.806024790e-02f }, {-1.856586039e-01f, 3.574696183e-02f }, {-1.799475253e-01f, 3.350359201e-02f }, {-1.742093414e-01f, 3.133049607e-02f }, {-1.684449315e-01f, 2.922797203e-02f }, {-1.626551449e-01f, 2.719634771e-02f }, {-1.568408757e-01f, 2.523592114e-02f }, {-1.510029733e-01f, 2.334699035e-02f }, {-1.451423317e-01f, 2.152982354e-02f }, {-1.392598450e-01f, 1.978474855e-02f }, {-1.333563775e-01f, 1.811197400e-02f }, {-1.274328232e-01f, 1.651176810e-02f }, {-1.214900911e-01f, 1.498436928e-02f }, {-1.155290529e-01f, 1.353001595e-02f }, {-1.095506176e-01f, 1.214894652e-02f }, {-1.035556868e-01f, 1.084131002e-02f }, {-9.754516184e-02f, 9.607374668e-03f }, {-9.151994437e-02f, 8.447259665e-03f }, {-8.548094332e-02f, 7.361173630e-03f }, {-7.942907512e-02f, 6.349295378e-03f }, {-7.336523384e-02f, 5.411744118e-03f }, {-6.729035079e-02f, 4.548668861e-03f }, {-6.120533869e-02f, 3.760218620e-03f }, {-5.511110276e-02f, 3.046512604e-03f }, {-4.900857061e-02f, 2.407640219e-03f }, {-4.289865494e-02f, 1.843690872e-03f }, {-3.678228334e-02f, 1.354783773e-03f }, {-3.066036850e-02f, 9.409487247e-04f }, {-2.453383803e-02f, 6.022751331e-04f }, {-1.840361208e-02f, 3.388226032e-04f }, {-1.227061450e-02f, 1.505911350e-04f }, {-6.135769188e-03f, 3.764033318e-05f }, {-0.000000000e+00f, 0.000000000e+00f }, }; // x[n] in interleaved order // y[n] in interleaved order // n >= 2 static void fft_radix2_pass(complex_t* x, complex_t* y, const complex_t* w, int n, int p) { size_t t = n/2; assert(n >= 1); assert(p >= 1); complex_t* xp0 = &x[0*t]; complex_t* xp1 = &x[1*t]; complex_t* yp0 = &y[0*p]; complex_t* yp1 = &y[1*p]; for (size_t i = 0; i < t; i++) { size_t k = i & (p-1); // twiddle index size_t j = 2*(i-k) + k; // output index float ar0 = xp0[i].re; float ai0 = xp0[i].im; float ar1 = xp1[i].re; float ai1 = xp1[i].im; float wr1 = w[k].re; float wi1 = w[k].im; float br1 = ar1 * wr1; float bi1 = ai1 * wr1; br1 += ai1 * wi1; bi1 -= ar1 * wi1; float cr0 = ar0 + br1; float ci0 = ai0 + bi1; float cr1 = ar0 - br1; float ci1 = ai0 - bi1; yp0[j].re = cr0; yp0[j].im = ci0; yp1[j].re = cr1; yp1[j].im = ci1; } } // x[n] in interleaved order // y[n] in interleaved order // n >= 4 static void fft_radix4_pass(complex_t* x, complex_t* y, const complex_t* w, int n, int p) { size_t t = n/4; assert(n >= 1); assert(p >= 1); complex_t* xp0 = &x[0*t]; complex_t* xp1 = &x[1*t]; complex_t* xp2 = &x[2*t]; complex_t* xp3 = &x[3*t]; complex_t* yp0 = &y[0*p]; complex_t* yp1 = &y[1*p]; complex_t* yp2 = &y[2*p]; complex_t* yp3 = &y[3*p]; for (size_t i = 0; i < t; i++) { size_t k = i & (p-1); // twiddle index size_t j = 4*(i-k) + k; // output index float ar1 = xp1[i].re; float ai1 = xp1[i].im; float ar2 = xp2[i].re; float ai2 = xp2[i].im; float ar3 = xp3[i].re; float ai3 = xp3[i].im; float wr1 = w[3*k+0].re; float wi1 = w[3*k+0].im; float wr2 = w[3*k+1].re; float wi2 = w[3*k+1].im; float wr3 = w[3*k+2].re; float wi3 = w[3*k+2].im; float br1 = ar1 * wr1; float bi1 = ai1 * wr1; float br2 = ar2 * wr2; float bi2 = ai2 * wr2; float br3 = ar3 * wr3; float bi3 = ai3 * wr3; br1 += ai1 * wi1; bi1 -= ar1 * wi1; br2 += ai2 * wi2; bi2 -= ar2 * wi2; br3 += ai3 * wi3; bi3 -= ar3 * wi3; float ar0 = xp0[i].re; float ai0 = xp0[i].im; float cr0 = ar0 + br2; float ci0 = ai0 + bi2; float cr2 = ar0 - br2; float ci2 = ai0 - bi2; float cr1 = br1 + br3; float ci1 = bi1 + bi3; float cr3 = br1 - br3; float ci3 = bi1 - bi3; float dr0 = cr0 + cr1; float di0 = ci0 + ci1; float dr1 = cr2 + ci3; float di1 = ci2 - cr3; float dr2 = cr0 - cr1; float di2 = ci0 - ci1; float dr3 = cr2 - ci3; float di3 = ci2 + cr3; yp0[j].re = dr0; yp0[j].im = di0; yp1[j].re = dr1; yp1[j].im = di1; yp2[j].re = dr2; yp2[j].im = di2; yp3[j].re = dr3; yp3[j].im = di3; } } static auto& fft_radix4_last = fft_radix4_pass; // x[n] in interleaved order // y[n] in interleaved order // n >= 4 static void ifft_radix4_last(complex_t* x, complex_t* y, const complex_t* w, int n, int p) { size_t t = n/4; assert(n >= 1); assert(p >= 1); complex_t* xp0 = &x[0*t]; complex_t* xp1 = &x[1*t]; complex_t* xp2 = &x[2*t]; complex_t* xp3 = &x[3*t]; complex_t* yp0 = &y[0*p]; complex_t* yp1 = &y[1*p]; complex_t* yp2 = &y[2*p]; complex_t* yp3 = &y[3*p]; for (size_t i = 0; i < t; i++) { size_t k = i & (p-1); // twiddle index size_t j = 4*(i-k) + k; // output index float ar1 = xp1[i].re; float ai1 = xp1[i].im; float ar2 = xp2[i].re; float ai2 = xp2[i].im; float ar3 = xp3[i].re; float ai3 = xp3[i].im; float wr1 = w[3*k+0].re; float wi1 = w[3*k+0].im; float wr2 = w[3*k+1].re; float wi2 = w[3*k+1].im; float wr3 = w[3*k+2].re; float wi3 = w[3*k+2].im; float br1 = ar1 * wr1; float bi1 = ai1 * wr1; float br2 = ar2 * wr2; float bi2 = ai2 * wr2; float br3 = ar3 * wr3; float bi3 = ai3 * wr3; br1 += ai1 * wi1; bi1 -= ar1 * wi1; br2 += ai2 * wi2; bi2 -= ar2 * wi2; br3 += ai3 * wi3; bi3 -= ar3 * wi3; float ar0 = xp0[i].re; float ai0 = xp0[i].im; float cr0 = ar0 + br2; float ci0 = ai0 + bi2; float cr2 = ar0 - br2; float ci2 = ai0 - bi2; float cr1 = br1 + br3; float ci1 = bi1 + bi3; float cr3 = br1 - br3; float ci3 = bi1 - bi3; float dr0 = cr0 + cr1; float di0 = ci0 + ci1; float dr1 = cr2 + ci3; float di1 = ci2 - cr3; float dr2 = cr0 - cr1; float di2 = ci0 - ci1; float dr3 = cr2 - ci3; float di3 = ci2 + cr3; float scale = 1.0f/n; // scaled by 1/n for ifft dr0 *= scale; di0 *= scale; dr1 *= scale; di1 *= scale; dr2 *= scale; di2 *= scale; dr3 *= scale; di3 *= scale; yp0[j].re = di0; // swapped re,im for ifft yp0[j].im = dr0; yp1[j].re = di1; yp1[j].im = dr1; yp2[j].re = di2; yp2[j].im = dr2; yp3[j].re = di3; yp3[j].im = dr3; } } // x[n] in interleaved order // y[n] in interleaved order // n >= 8 static void fft_radix8_first(complex_t* x, complex_t* y, int n, int p) { size_t t = n/8; assert(t >= 1); assert(p == 1); complex_t* xp0 = &x[0*t]; complex_t* xp1 = &x[1*t]; complex_t* xp2 = &x[2*t]; complex_t* xp3 = &x[3*t]; complex_t* xp4 = &x[4*t]; complex_t* xp5 = &x[5*t]; complex_t* xp6 = &x[6*t]; complex_t* xp7 = &x[7*t]; for (size_t i = 0; i < t; i++) { // // even // float ar0 = xp0[i].re; float ai0 = xp0[i].im; float ar2 = xp2[i].re; float ai2 = xp2[i].im; float ar4 = xp4[i].re; float ai4 = xp4[i].im; float ar6 = xp6[i].re; float ai6 = xp6[i].im; float cr0 = ar0 + ar4; float ci0 = ai0 + ai4; float cr2 = ar2 + ar6; float ci2 = ai2 + ai6; float cr4 = ar0 - ar4; float ci4 = ai0 - ai4; float cr6 = ar2 - ar6; float ci6 = ai2 - ai6; float dr0 = cr0 + cr2; float di0 = ci0 + ci2; float dr2 = cr0 - cr2; float di2 = ci0 - ci2; float dr4 = cr4 + ci6; float di4 = ci4 - cr6; float dr6 = cr4 - ci6; float di6 = ci4 + cr6; // // odd // float ar1 = xp1[i].re; float ai1 = xp1[i].im; float ar3 = xp3[i].re; float ai3 = xp3[i].im; float ar5 = xp5[i].re; float ai5 = xp5[i].im; float ar7 = xp7[i].re; float ai7 = xp7[i].im; float br1 = ar1 + ar5; float bi1 = ai1 + ai5; float br3 = ar3 + ar7; float bi3 = ai3 + ai7; float br5 = ar1 - ar5; float bi5 = ai1 - ai5; float br7 = ar3 - ar7; float bi7 = ai3 - ai7; float cr1 = br1; float ci1 = bi1;