Scopri come trovare un fabbro esperto e qualificato per le tue esigenze. Questa guida pratica ti fornirà consigli utili su come valutare le competenze, le certificazioni e le recensioni. Scegli un professionista affidabile per garantire lavori di qualità e soddisfazione duratura.
Trova professionisti vicino a te
Trova professionisti
/*
* 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 LOG_OUT_OF_MEMORY -100
#define LOG_SIZE_TOO_LARGE -101
// Helper functions
static int WebRtcSpl_ComplexIFFTInt(WebRtc_Word16 frfi[], int stages, int mode);
static int WebRtcSpl_ComplexFFTInt(WebRtc_Word16 frfi[], int stages, int mode);
int WebRtcSpl_ComplexFFT(WebRtc_Word16 frfi[], int stages, int mode)
{
// Check that stages is a reasonable number
if (stages < 0)
{
return LOG_OUT_OF_MEMORY;
}
if (stages > 10)
{
return LOG_SIZE_TOO_LARGE;
}
// Mode 0: forward FFT
if (mode == 0)
{
return WebRtcSpl_ComplexFFTInt(frfi, stages, mode);
}
// Mode 1: inverse FFT
else
{
return WebRtcSpl_ComplexIFFTInt(frfi, stages, mode);
}
}
// Forward FFT
static int WebRtcSpl_ComplexFFTInt(WebRtc_Word16 frfi[], int stages, int mode)
{
int i, j, k, m;
int l1, l2;
int ik, m2;
WebRtc_Word16 wr, wi, tawr, tawi;
WebRtc_Word32 temp;
WebRtc_Word16 *pfrfi;
if (stages == 0)
{
return 0;
}
// Bit reverse
j = 0;
pfrfi = &frfi[0];
m2 = 1 << (stages - 1);
for (i = 0; i < (m2 - 1); i++)
{
if (i < j)
{
temp = (WebRtc_Word32)pfrfi[2 * i];
pfrfi[2 * i] = pfrfi[2 * j];
pfrfi[2 * j] = (WebRtc_Word16)temp;
temp = (WebRtc_Word32)pfrfi[2 * i + 1];
pfrfi[2 * i + 1] = pfrfi[2 * j + 1];
pfrfi[2 * j + 1] = (WebRtc_Word16)temp;
}
k = m2;
while (k <= j)
{
j -= k;
k >>= 1;
}
j += k;
}
// Loop for each stage
l1 = 1;
l2 = 2;
for (i = 0; i < stages; i++)
{
pfrfi = &frfi[0];
m2 = l2 >> 1;
for (j = 0; j < l1; j++)
{
wr = WEBRTC_SPL_WORD16_MAX;
wi = 0;
m = 0;
ik = 0;
// Loop through first set of butterfly
for (k = j; k < (2 * l2); k += l2)
{
// Butterfly calculations
temp = WEBRTC_SPL_MUL_16_16(wr, pfrfi[2 * m2 + ik]) +
WEBRTC_SPL_MUL_16_16(wi, pfrfi[2 * m2 + ik + 1]);
tawi = (WebRtc_Word16)((temp + 0x4000) >> 15);
temp = WEBRTC_SPL_MUL_16_16(wr, pfrfi[2 * m2 + ik + 1]) -
WEBRTC_SPL_MUL_16_16(wi, pfrfi[2 * m2 + ik]);
tawr = (WebRtc_Word16)((temp + 0x4000) >> 15);
temp = WEBRTC_SPL_MUL_16_16(pfrfi[ik], wr) +
WEBRTC_SPL_MUL_16_16(pfrfi[ik + 1], wi);
pfrfi[2 * m2 + ik + 1] = (WebRtc_Word16)((temp + 0x4000) >> 15);
temp = WEBRTC_SPL_MUL_16_16(pfrfi[ik + 1], wr) -
WEBRTC_SPL_MUL_16_16(pfrfi[ik], wi);
pfrfi[2 * m2 + ik] = (WebRtc_Word16)((temp + 0x4000) >> 15);
pfrfi[ik] = (WebRtc_Word16)((WEBRTC_SPL_ADD_SAT_W16(pfrfi[ik],
tawr) + 0x1) >> 1);
pfrfi[ik + 1] = (WebRtc_Word16)((WEBRTC_SPL_ADD_SAT_W16(pfrfi[ik + 1],
tawi) + 0x1) >> 1);
// Update trigonometric recurrence
tawr = wr;
wr = (WebRtc_Word16)((WEBRTC_SPL_ADD_SAT_W16(wr, wr) + 0x1) >> 1);
wi = (WebRtc_Word16)((WEBRTC_SPL_SUB_SAT_W16(wi, wi) + 0x1) >> 1);
tawi = wi;
wi = (WebRtc_Word16)((WEBRTC_SPL_SUB_SAT_W16(tawr, tawi) + 0x1) >> 1);
m++;
ik += 2;
}
pfrfi += 2;
}
l1 = l2;
l2 <<= 1;
}
return 0;
}
// Inverse FFT
static int WebRtcSpl_ComplexIFFTInt(WebRtc_Word16 frfi[], int stages, int mode)
{
int i, j, k, m;
int l1, l2;
int ik, m2;
WebRtc_Word16 wr, wi, tawr, tawi;
WebRtc_Word32 temp;
WebRtc_Word16 *pfrfi;
if (stages == 0)
{
return 0;
}
// Bit reverse
j = 0;
pfrfi = &frfi[0];
m2 = 1 << (stages - 1);
for (i = 0; i < (m2 - 1); i++)
{
if (i < j)
{
temp = (WebRtc_Word32)pfrfi[2 * i];
pfrfi[2 * i] = pfrfi[2 * j];
pfrfi[2 * j] = (WebRtc_Word16)temp;
temp = (WebRtc_Word32)pfrfi[2 * i + 1];
pfrfi[2 * i + 1] = pfrfi[2 * j + 1];
pfrfi[2 * j + 1] = (WebRtc_Word16)temp;
}
k = m2;
while (k <= j)
{
j -= k;
k >>= 1;
}
j += k;
}
// Loop for each stage
l1 = 1;
l2 = 2;
for (i = 0; i < stages; i++)
{
pfrfi = &frfi[0];
m2 = l2 >> 1;
for (j = 0; j < l1; j++)
{
wr = WEBRTC_SPL_WORD16_MAX;
wi = 0;
m = 0;
ik = 0;
// Loop through first set of butterfly
for (k = j; k < (2 * l2); k += l2)
{
// Butterfly calculations
temp = WEBRTC_SPL_MUL_16_16(wr, pfrfi[2 * m2 + ik]) +
WEBRTC_SPL_MUL_16_16(wi, pfrfi[2 * m2 + ik + 1]);
tawi = (WebRtc_Word16)((temp + 0x4000) >> 15);
temp = WEBRTC_SPL_MUL_16_16(wr, pfrfi[2 * m2 + ik + 1]) -
WEBRTC_SPL_MUL_16_16(wi, pfrfi[2 * m2 + ik]);
tawr = (WebRtc_Word16)((temp + 0x4000) >> 15);
temp = WEBRTC_SPL_MUL_16_16(pfrfi[ik], wr) +
WEBRTC_SPL_MUL_16_16(pfrfi[ik + 1], wi);
pfrfi[2 * m2 + ik + 1] = (WebRtc_Word16)((temp + 0x4000) >> 15);
temp = WEBRTC_SPL_MUL_16_16(pfrfi[ik + 1], wr) -
WEBRTC_SPL_MUL_16_16(pfrfi[ik], wi);
pfrfi[2 * m2 + ik] = (WebRtc_Word16)((temp + 0x4000) >> 15);
pfrfi[ik] = (WebRtc_Word16)((WEBRTC_SPL_SUB_SAT_W16(pfrfi[ik],
tawr) + 0x1) >> 1);
pfrfi[ik + 1] = (WebRtc_Word16)((WEBRTC_SPL_SUB_SAT_W16(pfrfi[ik + 1],
tawi) + 0x1) >> 1);
// Update trigonometric recurrence
tawr = wr;
wr = (WebRtc_Word16)((WEBRTC_SPL_ADD_SAT_W16(wr, wr) + 0x1) >> 1);
wi = (WebRtc_Word16)((WEBRTC_SPL_SUB_SAT_W16(wi, wi) + 0x1) >> 1);
tawi = wi;
wi = (WebRtc_Word16)((WEBRTC_SPL_SUB_SAT_W16(tawr, tawi) + 0x1) >> 1);
m++;
ik += 2;
}
pfrfi += 2;
}
l1 = l2;
l2 <<= 1;
}
return 0;
}