2011-07-07 08:21:25 +00:00
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "common_audio/signal_processing/complex_fft_tables.h"
|
|
|
|
|
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
2018-07-25 16:05:48 +02:00
|
|
|
#include "rtc_base/system/arch.h"
|
2011-07-07 08:21:25 +00:00
|
|
|
|
|
|
|
|
#define CFFTSFT 14
|
|
|
|
|
#define CFFTRND 1
|
|
|
|
|
#define CFFTRND2 16384
|
|
|
|
|
|
2011-12-01 15:40:50 +00:00
|
|
|
#define CIFFTSFT 14
|
|
|
|
|
#define CIFFTRND 1
|
|
|
|
|
|
|
|
|
|
|
2013-04-09 16:40:28 +00:00
|
|
|
int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode)
|
2011-07-07 08:21:25 +00:00
|
|
|
{
|
|
|
|
|
int i, j, l, k, istep, n, m;
|
2013-04-09 16:40:28 +00:00
|
|
|
int16_t wr, wi;
|
|
|
|
|
int32_t tr32, ti32, qr32, qi32;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2011-12-01 15:40:50 +00:00
|
|
|
/* The 1024-value is a constant given from the size of kSinTable1024[],
|
2011-07-07 08:21:25 +00:00
|
|
|
* and should not be changed depending on the input parameter 'stages'
|
|
|
|
|
*/
|
|
|
|
|
n = 1 << stages;
|
|
|
|
|
if (n > 1024)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
l = 1;
|
2011-12-01 15:40:50 +00:00
|
|
|
k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change
|
2011-07-07 08:21:25 +00:00
|
|
|
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
|
2011-12-01 15:40:50 +00:00
|
|
|
* kSinTable1024[], and should not be changed depending on the input
|
2011-07-07 08:21:25 +00:00
|
|
|
* parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
|
|
|
|
|
*/
|
2011-12-01 15:40:50 +00:00
|
|
|
wr = kSinTable1024[j + 256];
|
|
|
|
|
wi = -kSinTable1024[j];
|
2011-07-07 08:21:25 +00:00
|
|
|
|
|
|
|
|
for (i = m; i < n; i += istep)
|
|
|
|
|
{
|
|
|
|
|
j = i + l;
|
|
|
|
|
|
2014-10-29 10:29:16 +00:00
|
|
|
tr32 = (wr * frfi[2 * j] - wi * frfi[2 * j + 1]) >> 15;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2014-10-29 10:29:16 +00:00
|
|
|
ti32 = (wr * frfi[2 * j + 1] + wi * frfi[2 * j]) >> 15;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2013-04-09 16:40:28 +00:00
|
|
|
qr32 = (int32_t)frfi[2 * i];
|
|
|
|
|
qi32 = (int32_t)frfi[2 * i + 1];
|
2014-10-29 10:29:16 +00:00
|
|
|
frfi[2 * j] = (int16_t)((qr32 - tr32) >> 1);
|
|
|
|
|
frfi[2 * j + 1] = (int16_t)((qi32 - ti32) >> 1);
|
|
|
|
|
frfi[2 * i] = (int16_t)((qr32 + tr32) >> 1);
|
|
|
|
|
frfi[2 * i + 1] = (int16_t)((qi32 + ti32) >> 1);
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--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
|
2011-12-01 15:40:50 +00:00
|
|
|
* kSinTable1024[], and should not be changed depending on the input
|
2011-07-07 08:21:25 +00:00
|
|
|
* parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
|
|
|
|
|
*/
|
2011-12-01 15:40:50 +00:00
|
|
|
wr = kSinTable1024[j + 256];
|
|
|
|
|
wi = -kSinTable1024[j];
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2012-08-28 04:09:50 +00:00
|
|
|
#ifdef WEBRTC_ARCH_ARM_V7
|
2013-04-09 16:40:28 +00:00
|
|
|
int32_t wri = 0;
|
2013-03-01 23:01:14 +00:00
|
|
|
__asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
|
2013-04-09 16:40:28 +00:00
|
|
|
"r"((int32_t)wr), "r"((int32_t)wi));
|
2011-08-16 20:00:18 +00:00
|
|
|
#endif
|
|
|
|
|
|
2011-07-07 08:21:25 +00:00
|
|
|
for (i = m; i < n; i += istep)
|
|
|
|
|
{
|
|
|
|
|
j = i + l;
|
|
|
|
|
|
2012-08-28 04:09:50 +00:00
|
|
|
#ifdef WEBRTC_ARCH_ARM_V7
|
2014-06-05 08:53:51 +00:00
|
|
|
register int32_t frfi_r;
|
|
|
|
|
__asm __volatile(
|
|
|
|
|
"pkhbt %[frfi_r], %[frfi_even], %[frfi_odd],"
|
|
|
|
|
" lsl #16\n\t"
|
|
|
|
|
"smlsd %[tr32], %[wri], %[frfi_r], %[cfftrnd]\n\t"
|
|
|
|
|
"smladx %[ti32], %[wri], %[frfi_r], %[cfftrnd]\n\t"
|
|
|
|
|
:[frfi_r]"=&r"(frfi_r),
|
|
|
|
|
[tr32]"=&r"(tr32),
|
|
|
|
|
[ti32]"=r"(ti32)
|
|
|
|
|
:[frfi_even]"r"((int32_t)frfi[2*j]),
|
|
|
|
|
[frfi_odd]"r"((int32_t)frfi[2*j +1]),
|
|
|
|
|
[wri]"r"(wri),
|
|
|
|
|
[cfftrnd]"r"(CFFTRND));
|
2011-08-16 20:00:18 +00:00
|
|
|
#else
|
2015-04-24 08:12:07 +02:00
|
|
|
tr32 = wr * frfi[2 * j] - wi * frfi[2 * j + 1] + CFFTRND;
|
2011-08-16 20:00:18 +00:00
|
|
|
|
2015-04-24 08:12:07 +02:00
|
|
|
ti32 = wr * frfi[2 * j + 1] + wi * frfi[2 * j] + CFFTRND;
|
2011-08-16 20:00:18 +00:00
|
|
|
#endif
|
|
|
|
|
|
2014-10-29 10:29:16 +00:00
|
|
|
tr32 >>= 15 - CFFTSFT;
|
|
|
|
|
ti32 >>= 15 - CFFTSFT;
|
2011-07-07 08:21:25 +00:00
|
|
|
|
2018-01-12 13:48:06 +01:00
|
|
|
qr32 = ((int32_t)frfi[2 * i]) * (1 << CFFTSFT);
|
|
|
|
|
qi32 = ((int32_t)frfi[2 * i + 1]) * (1 << CFFTSFT);
|
2011-08-16 20:00:18 +00:00
|
|
|
|
2014-10-29 10:29:16 +00:00
|
|
|
frfi[2 * j] = (int16_t)(
|
|
|
|
|
(qr32 - tr32 + CFFTRND2) >> (1 + CFFTSFT));
|
|
|
|
|
frfi[2 * j + 1] = (int16_t)(
|
|
|
|
|
(qi32 - ti32 + CFFTRND2) >> (1 + CFFTSFT));
|
|
|
|
|
frfi[2 * i] = (int16_t)(
|
|
|
|
|
(qr32 + tr32 + CFFTRND2) >> (1 + CFFTSFT));
|
|
|
|
|
frfi[2 * i + 1] = (int16_t)(
|
|
|
|
|
(qi32 + ti32 + CFFTRND2) >> (1 + CFFTSFT));
|
2011-07-07 08:21:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--k;
|
|
|
|
|
l = istep;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2011-12-01 15:40:50 +00:00
|
|
|
|
2013-04-09 16:40:28 +00:00
|
|
|
int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode)
|
2011-12-01 15:40:50 +00:00
|
|
|
{
|
Update a ton of audio code to use size_t more correctly and in general reduce
use of int16_t/uint16_t.
This is the upshot of a recommendation by henrik.lundin and kwiberg on an original small change ( https://webrtc-codereview.appspot.com/42569004/#ps1 ) to stop using int16_t just because values could fit in it, and is similar in nature to a previous "mass change to use size_t more" ( https://webrtc-codereview.appspot.com/23129004/ ) which also needed to be split up for review but to land all at once, since, like adding "const", such changes tend to cause a lot of transitive effects.
This was be reviewed and approved in pieces:
https://codereview.webrtc.org/1224093003
https://codereview.webrtc.org/1224123002
https://codereview.webrtc.org/1224163002
https://codereview.webrtc.org/1225133003
https://codereview.webrtc.org/1225173002
https://codereview.webrtc.org/1227163003
https://codereview.webrtc.org/1227203003
https://codereview.webrtc.org/1227213002
https://codereview.webrtc.org/1227893002
https://codereview.webrtc.org/1228793004
https://codereview.webrtc.org/1228803003
https://codereview.webrtc.org/1228823002
https://codereview.webrtc.org/1228823003
https://codereview.webrtc.org/1228843002
https://codereview.webrtc.org/1230693002
https://codereview.webrtc.org/1231713002
The change is being landed as TBR to all the folks who reviewed the above.
BUG=chromium:81439
TEST=none
R=andrew@webrtc.org, pbos@webrtc.org
TBR=aluebs, andrew, asapersson, henrika, hlundin, jan.skoglund, kwiberg, minyue, pbos, pthatcher
Review URL: https://codereview.webrtc.org/1230503003 .
Cr-Commit-Position: refs/heads/master@{#9768}
2015-08-24 14:52:23 -07:00
|
|
|
size_t i, j, l, istep, n, m;
|
|
|
|
|
int k, scale, shift;
|
2013-04-09 16:40:28 +00:00
|
|
|
int16_t wr, wi;
|
|
|
|
|
int32_t tr32, ti32, qr32, qi32;
|
|
|
|
|
int32_t tmp32, round2;
|
2011-12-01 15:40:50 +00:00
|
|
|
|
|
|
|
|
/* The 1024-value is a constant given from the size of kSinTable1024[],
|
|
|
|
|
* and should not be changed depending on the input parameter 'stages'
|
|
|
|
|
*/
|
2018-07-04 11:47:33 +02:00
|
|
|
n = ((size_t)1) << stages;
|
2011-12-01 15:40:50 +00:00
|
|
|
if (n > 1024)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
scale = 0;
|
|
|
|
|
|
|
|
|
|
l = 1;
|
|
|
|
|
k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change
|
|
|
|
|
depending on the input parameter 'stages' */
|
|
|
|
|
|
|
|
|
|
while (l < n)
|
|
|
|
|
{
|
|
|
|
|
// variable scaling, depending upon data
|
|
|
|
|
shift = 0;
|
|
|
|
|
round2 = 8192;
|
|
|
|
|
|
Match existing type usage better.
This makes a variety of small changes to synchronize bits of code using different types, remove useless code or casts, and add explicit casts in some places previously doing implicit ones. For example:
* Change a few type declarations to better match how the majority of code uses those objects.
* Eliminate "< 0" check for unsigned values.
* Replace "(float)sin(x)", where |x| is also a float, with "sinf(x)", and similar.
* Add casts to uint32_t in many places timestamps were used and the existing code stored signed values into the unsigned objects.
* Remove downcasts when the results would be passed to a larger type, e.g. calling "foo((int16_t)x)" with an int |x| when foo() takes an int instead of an int16_t.
* Similarly, add casts when passing a larger type to a function taking a smaller one.
* Add casts to int16_t when doing something like "int16_t = int16_t + int16_t" as the "+" operation would implicitly upconvert to int, and similar.
* Use "false" instead of "0" for setting a bool.
* Shift a few temp types when doing a multi-stage calculation involving typecasts, so as to put the most logical/semantically correct type possible into the temps. For example, when doing "int foo = int + int; size_t bar = (size_t)foo + size_t;", we might change |foo| to a size_t and move the cast if it makes more sense for |foo| to be represented as a size_t.
BUG=none
R=andrew@webrtc.org, asapersson@webrtc.org, henrika@webrtc.org, juberti@webrtc.org, kwiberg@webrtc.org
TBR=andrew, asapersson, henrika
Review URL: https://codereview.webrtc.org/1168753002
Cr-Commit-Position: refs/heads/master@{#9419}
2015-06-11 12:55:50 -07:00
|
|
|
tmp32 = WebRtcSpl_MaxAbsValueW16(frfi, 2 * n);
|
2011-12-01 15:40:50 +00:00
|
|
|
if (tmp32 > 13573)
|
|
|
|
|
{
|
|
|
|
|
shift++;
|
|
|
|
|
scale++;
|
|
|
|
|
round2 <<= 1;
|
|
|
|
|
}
|
|
|
|
|
if (tmp32 > 27146)
|
|
|
|
|
{
|
|
|
|
|
shift++;
|
|
|
|
|
scale++;
|
|
|
|
|
round2 <<= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
istep = l << 1;
|
|
|
|
|
|
|
|
|
|
if (mode == 0)
|
|
|
|
|
{
|
|
|
|
|
// mode==0: Low-complexity and Low-accuracy mode
|
|
|
|
|
for (m = 0; m < l; ++m)
|
|
|
|
|
{
|
|
|
|
|
j = m << k;
|
|
|
|
|
|
|
|
|
|
/* The 256-value is a constant given as 1/4 of the size of
|
|
|
|
|
* kSinTable1024[], and should not be changed depending on the input
|
|
|
|
|
* parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
|
|
|
|
|
*/
|
|
|
|
|
wr = kSinTable1024[j + 256];
|
|
|
|
|
wi = kSinTable1024[j];
|
|
|
|
|
|
|
|
|
|
for (i = m; i < n; i += istep)
|
|
|
|
|
{
|
|
|
|
|
j = i + l;
|
|
|
|
|
|
2014-10-29 10:29:16 +00:00
|
|
|
tr32 = (wr * frfi[2 * j] - wi * frfi[2 * j + 1]) >> 15;
|
2011-12-01 15:40:50 +00:00
|
|
|
|
2014-10-29 10:29:16 +00:00
|
|
|
ti32 = (wr * frfi[2 * j + 1] + wi * frfi[2 * j]) >> 15;
|
2011-12-01 15:40:50 +00:00
|
|
|
|
2013-04-09 16:40:28 +00:00
|
|
|
qr32 = (int32_t)frfi[2 * i];
|
|
|
|
|
qi32 = (int32_t)frfi[2 * i + 1];
|
2014-10-29 10:29:16 +00:00
|
|
|
frfi[2 * j] = (int16_t)((qr32 - tr32) >> shift);
|
|
|
|
|
frfi[2 * j + 1] = (int16_t)((qi32 - ti32) >> shift);
|
|
|
|
|
frfi[2 * i] = (int16_t)((qr32 + tr32) >> shift);
|
|
|
|
|
frfi[2 * i + 1] = (int16_t)((qi32 + ti32) >> shift);
|
2011-12-01 15:40:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
{
|
|
|
|
|
// mode==1: High-complexity and High-accuracy mode
|
|
|
|
|
|
|
|
|
|
for (m = 0; m < l; ++m)
|
|
|
|
|
{
|
|
|
|
|
j = m << k;
|
|
|
|
|
|
|
|
|
|
/* The 256-value is a constant given as 1/4 of the size of
|
|
|
|
|
* kSinTable1024[], and should not be changed depending on the input
|
|
|
|
|
* parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
|
|
|
|
|
*/
|
|
|
|
|
wr = kSinTable1024[j + 256];
|
|
|
|
|
wi = kSinTable1024[j];
|
|
|
|
|
|
2012-08-28 04:09:50 +00:00
|
|
|
#ifdef WEBRTC_ARCH_ARM_V7
|
2013-04-09 16:40:28 +00:00
|
|
|
int32_t wri = 0;
|
2013-03-01 23:01:14 +00:00
|
|
|
__asm __volatile("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
|
2013-04-09 16:40:28 +00:00
|
|
|
"r"((int32_t)wr), "r"((int32_t)wi));
|
2011-12-01 15:40:50 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
for (i = m; i < n; i += istep)
|
|
|
|
|
{
|
|
|
|
|
j = i + l;
|
|
|
|
|
|
2012-08-28 04:09:50 +00:00
|
|
|
#ifdef WEBRTC_ARCH_ARM_V7
|
2014-06-05 08:53:51 +00:00
|
|
|
register int32_t frfi_r;
|
2013-03-01 23:01:14 +00:00
|
|
|
__asm __volatile(
|
|
|
|
|
"pkhbt %[frfi_r], %[frfi_even], %[frfi_odd], lsl #16\n\t"
|
|
|
|
|
"smlsd %[tr32], %[wri], %[frfi_r], %[cifftrnd]\n\t"
|
|
|
|
|
"smladx %[ti32], %[wri], %[frfi_r], %[cifftrnd]\n\t"
|
2014-06-05 08:53:51 +00:00
|
|
|
:[frfi_r]"=&r"(frfi_r),
|
|
|
|
|
[tr32]"=&r"(tr32),
|
2013-03-01 23:01:14 +00:00
|
|
|
[ti32]"=r"(ti32)
|
2013-04-09 16:40:28 +00:00
|
|
|
:[frfi_even]"r"((int32_t)frfi[2*j]),
|
|
|
|
|
[frfi_odd]"r"((int32_t)frfi[2*j +1]),
|
2013-03-01 23:01:14 +00:00
|
|
|
[wri]"r"(wri),
|
|
|
|
|
[cifftrnd]"r"(CIFFTRND)
|
|
|
|
|
);
|
2011-12-01 15:40:50 +00:00
|
|
|
#else
|
|
|
|
|
|
2015-04-24 08:12:07 +02:00
|
|
|
tr32 = wr * frfi[2 * j] - wi * frfi[2 * j + 1] + CIFFTRND;
|
2011-12-01 15:40:50 +00:00
|
|
|
|
2015-04-24 08:12:07 +02:00
|
|
|
ti32 = wr * frfi[2 * j + 1] + wi * frfi[2 * j] + CIFFTRND;
|
2011-12-01 15:40:50 +00:00
|
|
|
#endif
|
2014-10-29 10:29:16 +00:00
|
|
|
tr32 >>= 15 - CIFFTSFT;
|
|
|
|
|
ti32 >>= 15 - CIFFTSFT;
|
2011-12-01 15:40:50 +00:00
|
|
|
|
2018-01-12 13:48:06 +01:00
|
|
|
qr32 = ((int32_t)frfi[2 * i]) * (1 << CIFFTSFT);
|
|
|
|
|
qi32 = ((int32_t)frfi[2 * i + 1]) * (1 << CIFFTSFT);
|
2011-12-01 15:40:50 +00:00
|
|
|
|
2014-10-29 10:29:16 +00:00
|
|
|
frfi[2 * j] = (int16_t)(
|
|
|
|
|
(qr32 - tr32 + round2) >> (shift + CIFFTSFT));
|
|
|
|
|
frfi[2 * j + 1] = (int16_t)(
|
|
|
|
|
(qi32 - ti32 + round2) >> (shift + CIFFTSFT));
|
|
|
|
|
frfi[2 * i] = (int16_t)(
|
|
|
|
|
(qr32 + tr32 + round2) >> (shift + CIFFTSFT));
|
|
|
|
|
frfi[2 * i + 1] = (int16_t)(
|
|
|
|
|
(qi32 + ti32 + round2) >> (shift + CIFFTSFT));
|
2011-12-01 15:40:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
--k;
|
|
|
|
|
l = istep;
|
|
|
|
|
}
|
|
|
|
|
return scale;
|
|
|
|
|
}
|