diff options
Diffstat (limited to 'src/common_audio/signal_processing_library/main/source/complex_fft.c')
-rw-r--r-- | src/common_audio/signal_processing_library/main/source/complex_fft.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/common_audio/signal_processing_library/main/source/complex_fft.c b/src/common_audio/signal_processing_library/main/source/complex_fft.c new file mode 100644 index 0000000000..b6f0c4e1bb --- /dev/null +++ b/src/common_audio/signal_processing_library/main/source/complex_fft.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +/* + * This file contains the function WebRtcSpl_ComplexFFT(). + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +#define CFFTSFT 14 +#define CFFTRND 1 +#define CFFTRND2 16384 + +#if (defined ARM9E_GCC) || (defined ARM_WINM) || (defined ANDROID_AECOPT) +extern "C" int FFT_4OFQ14(void *src, void *dest, int NC, int shift); + +// For detailed description of the fft functions, check the readme files in fft_ARM9E folder. +int WebRtcSpl_ComplexFFT2(WebRtc_Word16 frfi[], WebRtc_Word16 frfiOut[], int stages, int mode) +{ + return FFT_4OFQ14(frfi, frfiOut, 1 << stages, 0); +} +#endif + +int WebRtcSpl_ComplexFFT(WebRtc_Word16 frfi[], int stages, int mode) +{ + int i, j, l, k, istep, n, m; + WebRtc_Word16 wr, wi; + WebRtc_Word32 tr32, ti32, qr32, qi32; + + /* The 1024-value is a constant given from the size of WebRtcSpl_kSinTable1024[], + * and should not be changed depending on the input parameter 'stages' + */ + n = 1 << stages; + if (n > 1024) + return -1; + + l = 1; + k = 10 - 1; /* Constant for given WebRtcSpl_kSinTable1024[]. Do not change + depending on the input parameter 'stages' */ + + if (mode == 0) + { + // mode==0: Low-complexity and Low-accuracy mode + while (l < n) + { + istep = l << 1; + + for (m = 0; m < l; ++m) + { + j = m << k; + + /* The 256-value is a constant given as 1/4 of the size of + * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input + * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 + */ + wr = WebRtcSpl_kSinTable1024[j + 256]; + wi = -WebRtcSpl_kSinTable1024[j]; + + for (i = m; i < n; i += istep) + { + j = i + l; + + tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) + - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1])), 15); + + ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) + + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j])), 15); + + qr32 = (WebRtc_Word32)frfi[2 * i]; + qi32 = (WebRtc_Word32)frfi[2 * i + 1]; + frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, 1); + frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, 1); + frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, 1); + frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, 1); + } + } + + --k; + l = istep; + + } + + } else + { + // mode==1: High-complexity and High-accuracy mode + while (l < n) + { + istep = l << 1; + + for (m = 0; m < l; ++m) + { + j = m << k; + + /* The 256-value is a constant given as 1/4 of the size of + * WebRtcSpl_kSinTable1024[], and should not be changed depending on the input + * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2 + */ + wr = WebRtcSpl_kSinTable1024[j + 256]; + wi = -WebRtcSpl_kSinTable1024[j]; + + for (i = m; i < n; i += istep) + { + j = i + l; + + tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j]) + - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CFFTRND), + 15 - CFFTSFT); + + ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1]) + + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND), 15 - CFFTSFT); + + qr32 = ((WebRtc_Word32)frfi[2 * i]) << CFFTSFT; + qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CFFTSFT; + frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( + (qr32 - tr32 + CFFTRND2), 1 + CFFTSFT); + frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( + (qi32 - ti32 + CFFTRND2), 1 + CFFTSFT); + frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( + (qr32 + tr32 + CFFTRND2), 1 + CFFTSFT); + frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( + (qi32 + ti32 + CFFTRND2), 1 + CFFTSFT); + } + } + + --k; + l = istep; + } + } + return 0; +} |