首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用快速傅立叶变换库C++计算快速傅立叶变换和快速傅立叶变换

用快速傅立叶变换库C++计算快速傅立叶变换和快速傅立叶变换
EN

Stack Overflow用户
提问于 2011-04-16 18:02:56
回答 4查看 24.2K关注 0票数 9

我正在尝试计算FFT和IFFT,只是为了尝试是否可以得到相同的信号,但我不确定如何实现。这就是我做FFT的方法:

代码语言:javascript
复制
    plan = fftw_plan_r2r_1d(blockSize, datas, out, FFTW_R2HC, FFTW_ESTIMATE);
    fftw_execute(plan);
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-04-16 18:29:30

您是否至少尝试阅读了更多像样的文档?

他们为你想出了一个完整的教程来了解FFTW:

http://fftw.org/fftw3_doc/Tutorial.html#Tutorial

更新:我假设您知道如何使用C数组,因为C数组是用作输入和输出的。

This page提供了快速傅立叶变换与快速傅立叶变换所需的信息(参见参数->符号)。文档还说输入->FFT->IFFT->n*input。因此,您必须小心正确地缩放数据。

票数 1
EN

Stack Overflow用户

发布于 2014-02-27 13:31:09

下面是一个例子。它做了两件事。首先,它将输入阵列in[N]准备为余弦波,其频率为3,幅度为1.0,并对其进行傅立叶变换。因此,在输出中,您应该在out[3]out[N-3]处看到一个峰值。由于余弦波的幅度为1.0,因此在out[3]out[N-3]处得到N/2。

其次,它将阵列out[N]反傅立叶变换回in2[N]。经过适当的规范化之后,您可以看到in2[N]in[N]是相同的。

代码语言:javascript
复制
#include <stdlib.h>
#include <math.h>
#include <fftw3.h>
#define N 16
int main(void) {
  fftw_complex in[N], out[N], in2[N]; /* double [2] */
  fftw_plan p, q;
  int i;

  /* prepare a cosine wave */
  for (i = 0; i < N; i++) {
    in[i][0] = cos(3 * 2*M_PI*i/N);
    in[i][1] = 0;
  }

  /* forward Fourier transform, save the result in 'out' */
  p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
  fftw_execute(p);
  for (i = 0; i < N; i++)
    printf("freq: %3d %+9.5f %+9.5f I\n", i, out[i][0], out[i][1]);
  fftw_destroy_plan(p);

  /* backward Fourier transform, save the result in 'in2' */
  printf("\nInverse transform:\n");
  q = fftw_plan_dft_1d(N, out, in2, FFTW_BACKWARD, FFTW_ESTIMATE);
  fftw_execute(q);
  /* normalize */
  for (i = 0; i < N; i++) {
    in2[i][0] *= 1./N;
    in2[i][1] *= 1./N;
  }
  for (i = 0; i < N; i++)
    printf("recover: %3d %+9.5f %+9.5f I vs. %+9.5f %+9.5f I\n",
        i, in[i][0], in[i][1], in2[i][0], in2[i][1]);
  fftw_destroy_plan(q);

  fftw_cleanup();
  return 0;
}

这是输出:

代码语言:javascript
复制
freq:   0  -0.00000  +0.00000 I
freq:   1  +0.00000  +0.00000 I
freq:   2  -0.00000  +0.00000 I
freq:   3  +8.00000  -0.00000 I
freq:   4  +0.00000  +0.00000 I
freq:   5  -0.00000  +0.00000 I
freq:   6  +0.00000  -0.00000 I
freq:   7  -0.00000  +0.00000 I
freq:   8  +0.00000  +0.00000 I
freq:   9  -0.00000  -0.00000 I
freq:  10  +0.00000  +0.00000 I
freq:  11  -0.00000  -0.00000 I
freq:  12  +0.00000  -0.00000 I
freq:  13  +8.00000  +0.00000 I
freq:  14  -0.00000  -0.00000 I
freq:  15  +0.00000  -0.00000 I

Inverse transform:
recover:   0  +1.00000  +0.00000 I vs.  +1.00000  +0.00000 I
recover:   1  +0.38268  +0.00000 I vs.  +0.38268  +0.00000 I
recover:   2  -0.70711  +0.00000 I vs.  -0.70711  +0.00000 I
recover:   3  -0.92388  +0.00000 I vs.  -0.92388  +0.00000 I
recover:   4  -0.00000  +0.00000 I vs.  -0.00000  +0.00000 I
recover:   5  +0.92388  +0.00000 I vs.  +0.92388  +0.00000 I
recover:   6  +0.70711  +0.00000 I vs.  +0.70711  +0.00000 I
recover:   7  -0.38268  +0.00000 I vs.  -0.38268  +0.00000 I
recover:   8  -1.00000  +0.00000 I vs.  -1.00000  +0.00000 I
recover:   9  -0.38268  +0.00000 I vs.  -0.38268  +0.00000 I
recover:  10  +0.70711  +0.00000 I vs.  +0.70711  +0.00000 I
recover:  11  +0.92388  +0.00000 I vs.  +0.92388  +0.00000 I
recover:  12  +0.00000  +0.00000 I vs.  +0.00000  +0.00000 I
recover:  13  -0.92388  +0.00000 I vs.  -0.92388  +0.00000 I
recover:  14  -0.70711  +0.00000 I vs.  -0.70711  +0.00000 I
recover:  15  +0.38268  +0.00000 I vs.  +0.38268  +0.00000 I
票数 25
EN

Stack Overflow用户

发布于 2016-09-27 22:59:23

这是我做的。我的设计是专门为了给出与Matlab相同的输出。这只适用于列矩阵(您可以用std::vector替换AMatrix )。

代码语言:javascript
复制
AMatrix<complex<double>> FastFourierTransform::Forward1d(const AMatrix<double> &inMat)
{
    AMatrix<complex<double>> outMat{ inMat.NumRows(), inMat.NumCols() };
    size_t N = inMat.NumElements();
    bool isOdd = N % 2 == 1;
    size_t outSize = (isOdd) ? ceil(N / 2 + 1) : N / 2;
    fftw_plan plan = fftw_plan_dft_r2c_1d(
        inMat.NumRows(),
        reinterpret_cast<double*>(&inMat.mutData()[0]), // mutData here is as same v.data() for std::vector
        reinterpret_cast<fftw_complex*>(&outMat.mutData()[0]),
        FFTW_ESTIMATE);
    fftw_execute(plan);

    // mirror
    auto halfWayPoint = outMat.begin() + (outMat.NumRows() / 2) + 1;
    auto startCopyDest = (isOdd) ? halfWayPoint : halfWayPoint - 1;
    std::reverse_copy(outMat.begin() + 1, halfWayPoint, startCopyDest); // skip DC (+1)
    std::for_each(halfWayPoint, outMat.end(), [](auto &c) { return c = std::conj(c);});

    return std::move(outMat);
}

AMatrix<complex<double>> FastFourierTransform::Forward1d(const AMatrix<double> &inMat, size_t points)
{
    // append zeros to matrix until it's the same size as points
    AMatrix<double> sig = inMat;
    sig.Resize(points, sig.NumCols());
    for (size_t i = inMat.NumRows(); i < points; i++)
    {
        sig(i, 0) = 0;
    }
    return Forward1d(sig);
}

AMatrix<complex<double>> FastFourierTransform::Inverse1d(const AMatrix<complex<double>> &inMat)
{
    AMatrix<complex<double>> outMat{ inMat.NumRows(), inMat.NumCols() };
    size_t N = inMat.NumElements();

    fftw_plan plan = fftw_plan_dft_1d(
        inMat.NumRows(), 
        reinterpret_cast<fftw_complex*>(&inMat.mutData()[0]),
        reinterpret_cast<fftw_complex*>(&outMat.mutData()[0]),
        FFTW_BACKWARD, 
        FFTW_ESTIMATE);
    fftw_execute(plan);

    // Matlab normalizes
    auto normalize = [=](auto &c) { return c *= 1. / N; };
    std::for_each(outMat.begin(), outMat.end(), normalize);

    fftw_destroy_plan(plan);
    return std::move(outMat);
}

// From Matlab documentation: "ifft tests X to see whether vectors in X along the active dimension 
// are conjugate symmetric. If so, the computation is faster and the output is real. 
// An N-element vector x is conjugate symmetric if x(i) = conj(x(mod(N-i+1,N)+1)) for each element of x."
// http://uk.mathworks.com/help/matlab/ref/ifft.html
AMatrix<double> FastFourierTransform::Inverse1dConjSym(const AMatrix<complex<double>> &inMat)
{
    AMatrix<double> outMat{ inMat.NumRows(), inMat.NumCols() };
    size_t N = inMat.NumElements();

    fftw_plan plan = fftw_plan_dft_c2r_1d(
        inMat.NumRows(), 
        reinterpret_cast<fftw_complex*>(&inMat.mutData()[0]),
        reinterpret_cast<double*>(&outMat.mutData()[0]),
        FFTW_BACKWARD | FFTW_ESTIMATE);
    fftw_execute(plan);

    auto normalize = [=](auto &c) { return c *= 1. / N; };
    std::for_each(outMat.begin(), outMat.end(), normalize);

    fftw_destroy_plan(plan);
    return std::move(outMat);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5685765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档