复数......唉

时间:2012-09-20 20:02:12

标签: c++ signal-processing dft

我正在开展一个项目,要求我接受输入,执行DFT(离散傅立叶变换),然后从这些值中获取过零点数。

我编写了一个算法,但是,它使用了复数,我不知道如何对它们进行操作/执行计算。这是代码:

#include <iostream>
#include <complex>
#include <vector>

using namespace std;

const double PI = 3.14159265358979323846;

vector< complex<double> > DFT(vector< complex<double> >& theData)
{
    // Define the Size of the read in vector
    const int S = theData.size();

    // Initalise new vector with size of S
    vector< complex<double> > out(S, 0);
    for(unsigned i=0; (i < S); i++)
    {
        out[i] = complex<double>(0.0, 0.0);
        for(unsigned j=0; (j < S); j++)
        {
            out[i] += theData[j] * polar<double>(2, (-2 * PI * i * j / S));
        }
    }

    return out;
}

int main(int argc, char *argv[]) {
    vector< complex<double> > numbers;

    numbers.push_back(128);
    numbers.push_back(127);

    vector< complex<double> > testing = DFT(numbers);

    for(unsigned i=0; (i < testing.size()); i++)
    {
        cout << testing[i] << endl;
    }
}

现在,如果我想表演,例如:

if(testing[i] >= 0)
{
    // blah blah
}

然后它将返回错误。有什么想法或建议吗?是否可以在不使用复数的情况下创建DFT?

4 个答案:

答案 0 :(得分:2)

无论谁向你发出指示,都没有告诉你算上DFT / FFT结果的过零点。那将毫无意义。 (如果他们告诉你这样做,他们就会毫无头绪。你允许我嘲笑他们给你这么荒谬的指示)。相反,他们告诉你计算原始数据的过零点,并查看数据的FFT。

然而,

  • 零交叉率是语音识别的一个非常糟糕的起点。也许你可以在某个地方找到它。只有轻微的夸张,我可以说过零是你可以做的最不稳健的DSP分析。然而,它也很简单,语音识别研究已经进行了很长时间,所以也许有一些研究。更新/更正:这有点夸张。实际上我相信很多语音识别技术都会使用过零,但你应该先知道自己在做什么,因为它对八度误差等多种错误并不是非常强大和敏感。当你使用过零时,首先低通(可能是积极的)是个好主意。绝对考虑其他因素。

  • 了解FFT的输出是我在这里经常被问到的一个博客条目。通常人们试图跟踪音调,你应该这样做,实际上,你可以通过FFT得到其他东西,如频率质心,以及在语音中重要的不同频率的相对强度。从这里开始:http://blog.bjornroche.com/2012/07/frequency-detection-using-fft-aka-pitch.html

  • 您可能还想考虑简单地过滤重要的语音频率(找出它们是什么,从"manner of articulation"上的维基百科条目开始。例如,通过链接到Sibilant,您将学习“[s]在8,000 Hz附近具有最大的声学强度。”Neeto!)您可以通过FFT或过滤获得该信息。每个都有优点和缺点。您可能需要查看语音识别文献以了解它们的用途。

答案 1 :(得分:0)

Fourier transformations,例如DFT返回complex numbers,因此您无法真正绕过它们。

根据您的应用程序,可能能够安全地忽略复数的虚部,并将DFT的输出视为实数序列。

您可以对复杂数字执行大量操作。有些可能与您的应用程序有关,有些则不然。值得花一些时间来更好地理解复数。

最后,,如果不使用复数,则无法创建DFT。您可以获取DFT的复杂输出并将其转换为实数,但您将在此过程中丢失信息。您需要了解复杂数字以及如何在应用程序中使用DFT,以确定是否适合执行任何此类转换。

答案 2 :(得分:0)

我遇到了类似的问题,我放弃了使用矢量容器来处理c ++复数的双数字,因为FFT库不能很好地支持它,最后使用普通的旧数组。你会发现你尝试做的大部分工作都会很好。

 std::complex<double>*  in=new std::complex<double> [N];

所有关节运算都可以像使用任何其他数组一样工作{例如abs(in[i])in[i] *pi,只需确保使用数学库的C ++版本

对于您的具体问题,您必须检查C++ reference是否有真实和图像功能可以用来查看它是否大于零

然后确保(如果你使用fftw)

使用重新解释强制转换所有复数(输入和输出,如果它们很复杂)

    p = fftw_plan_dft_c2r_1d(N, reinterpret_cast<fftw_complex*>(in), out,FFTW_ESTIMATE);  

   fftw_execute(p);

答案 3 :(得分:0)

DFT将始终使用复数,至少为其输出。如果输入随时间描述某些信号,则输出根据频率描述信号。每个复数可以写在polar form中,然后分成绝对值,表示幅度和表示相位的角度。也许这是你感兴趣的幅度;如果是这样,你会想要计算绝对值,但它们也都是非负的。

variations个DFT可用于实数。在这方面,discrete cosine transformation出现在我的脑海中。不确定这是否适用于您的应用程序。

注意有像FFTW这样的库可以比你的代码更快地计算DFT。即使是自编的FFT也可能值得考虑,只要你的输入大小是2的幂。但所有这些都与你的实际问题有点不同。