乘法定义的符号..某处

时间:2017-03-26 05:32:13

标签: c++ visual-studio signal-processing llvm-clang

我使用名为KFR的DSP库来编写一些执行各种操作的相当简单的命令行程序。不幸的是,这个库需要在VS中使用LLVM平台工具集(或者不使用VS),因为它与标准MSVC不兼容。这有点打破了智能感知,因此调试有点棘手。

无论如何,我目前遇到了这个问题,我的构建失败并返回链接错误,说我有多个定义和定义在别处的符号。 apparently I define this somewhere?

我担心这可能与命名空间冲突有关,但现在我确定它不可能,而且我真的不知道定义冲突在哪里。我查看了所有依赖项,无法找到任何看起来像重新定义此错误返回的内容。

如果有人能帮我解决问题,我真的很感激。

代码如下。请原谅这个烂摊子,我没有长时间处理它并且远未完成(我也只使用了几个月的c ++)。

在预编译的标题中:

#pragma once

#define _USE_MATH_DEFINES

#include "targetver.h"
#include <getopt.h>
#include <stdio.h>
#include <tchar.h>
#include <all.hpp>    //kfr header
#include <math.h>
#include <complex>

主要项目:

#include "stdafx.h"


/*forward declarations*/
void usage(void);
int parse_args(int, char**);
double damping();
int n_factorial(int);
double ERB(double);
std::vector<std::complex<double>> expand_poly(std::vector<std::complex<double>>);
std::vector<std::complex<double>> formSOS(std::vector<std::complex<double>>, std::vector<std::complex<double>>);
std::vector<std::complex<double>> sosfun(int, int, std::vector<std::complex<double>>, std::complex<double>, int);
std::vector<std::complex<double>> zp2tf(std::vector<std::complex<double>>, std::vector<std::complex<double>>, std::vector<std::complex<double>>);


/*global variables*/
double fc = NULL;
unsigned long fs = NULL;
int order = NULL;                                                   
int type = NULL;
char* types[] = { "classic", "allpole", "onediff", "twodiff" };
const std::complex<double> i(0.0, 1.0);                                 

/* parse input arguments*/
int parse_args(int argc, char **argv)
{
int c, i;
char* p;
int tmp;

struct option longopts[] = 
    {
        { "SamplingRate",   required_argument,  NULL,   'fs' },         // makes sense to put fs first because it establishes a reasonable range for fc
        { "frequency",      required_argument,  NULL,   'fc' },
        { "Order",          required_argument,  NULL,   'n'  },
        { "type",           required_argument,  NULL,   't'  }
};

opterr = 0;
optopt = '!';

while ((c = getopt_long(argc, argv, "fs:fc:n:t", longopts, &i)) != -1)
{
    switch (c)
    {
    case 'fs':
        if (optarg == NULL)
            throw std::invalid_argument("After -fs, the filter frequency should be provided.");
        atoi(optarg) <= 0 ?
            throw std::invalid_argument("fs cannot be negative") :
            fs = atoi(optarg);
        break;

    case 'fc':
        if (optarg == NULL)
            throw std::invalid_argument("After -fc, the sampling rate should be provided.");
        (atof(optarg) <= 0 || atof(optarg) > fs / 2) ?
            throw std::invalid_argument("the filter centre frequency may not be negative or more than half the sampling rate.") :
            fc = atof(optarg);
        break;

    case 'n':
        if (optarg == NULL)
            throw std::invalid_argument("After -n, the filter order should be provided");
        atoi(optarg) <= 0 || atoi(optarg) % 2 != 0 ?
            throw std::invalid_argument("Order cannot must be a positive number that is divisible by two.") :
            order = atoi(optarg);
        break;

    case 't':
        if (optarg == NULL)
            throw std::invalid_argument("After -t, the filter type should be provided");

        for (int ii = 0; ii < 4; ++ii)
        {
            if (!strcmp(optarg, types[ii]))             // check if type optarg matches any of the given types
            {
                type = ii;
                break;
            }
        }
        if (type == NULL)                               // if still null, optarg is not a type, throw error
            throw std::invalid_argument("Unknown type argument given, see usage.");
        break;

    default:
        throw std::invalid_argument("The command line contains unknown arguments.");
    }
}
return 1;

}


int main(int argc, char** argv)
{
/* arguments - fc, fs, order, type*/

if (!parse_args(argc, argv))
    throw std::invalid_argument("Unknown arguments provided, see usage.");      // parse_args should throw an error before this, but whatever

if (order == NULL)
{
    std::cout << "No order argument (-n) was provided - the default value will be used.";
    order = 4;
}

if (type == NULL)
{
    std::cout << "No type argument (-t) was provided - the default value will be used.";
    type = 0;
}

/* Initialise type invariants */

double b = damping();                       // determines filter bandwidth
double t_theta = 2 * M_PI*fc / fs;          // theoretical pole angle

switch(type)
{
    case 0:                         // implement classic gammatone
    {
        std::complex<double> c_theta = log(exp(-b * exp(t_theta * i))) * i;                 // corrected pole angle         

        std::complex<double> pole = exp(-b - i*c_theta);
        double zero = pole.real();

        std::vector<std::complex<double>> poles = { pole, conj(pole) };

        std::complex<double> a0 = pow(abs(
            ((cos(t_theta) + i*sin(t_theta)) - exp(-b)*cos(c_theta)) /
            ((cos(t_theta) + i*sin(t_theta) - exp(-b)*cos(c_theta) + exp(-b)*i*sin(c_theta)) *
            (cos(t_theta) + i*sin(t_theta) - exp(-b) * cos(c_theta) - exp(-b) * i * sin(c_theta)))), -1);           // gain for unity at fc


    }
    case 1:                         // implement allpole gammatone
    {
        std::complex<double> c_theta = acos(2 * exp(b)*cos(t_theta) / (exp(2 * b) + 1));        // corrected pole angle

        std::vector<std::complex<double>> poles = { exp(-b - i*c_theta), conj(exp(-b - i*c_theta)) };

        std::complex<double> a0 = abs(
            1. + (2. * (-exp(-b)*cos(c_theta)))* cos(t_theta) 
               - i * (2. * (-exp(-b)*cos(c_theta))) * sin(t_theta) 
               + exp(-2 * b) * cos(2 * t_theta) 
               - i * exp(-2 * b) * sin(2 * t_theta));
    }
    case 2:                         // implement onediff gammatone
    {
        std::complex<double> c_theta = acos(2 * exp(b)*cos(t_theta) / (exp(2 * b) + 1));        // corrected pole angle for allpole stages
        std::complex<double> d_theta = acos(exp(-b) / 2 + exp(i * t_theta) / (double)2 + exp(i * t_theta) / (double)2 + exp(b) / 2 - (double)1);
                                                                                        // corrected pole angle for one-zero stages

        std::vector<std::complex<double>> a_poles = { exp(-b - i * c_theta), conj(exp(-b - i * c_theta)) };
        std::vector<std::complex<double>> d_poles = { exp(-b - i * d_theta), conj(exp(-b - i * d_theta)) };

        std::complex<double> d_zero = { 1.0, 0.0 };

        std::complex<double> a0_a = abs(
            1. + (2. * (-exp(-b)*cos(c_theta)))* cos(t_theta)
            - i * (2. * (-exp(-b)*cos(c_theta))) * sin(t_theta)
            + exp(-2 * b) * cos(2 * t_theta)
            - i * exp(-2 * b) * sin(2 * t_theta));

        std::complex<double> a0_d = abs(
            (1. + (2. * (-exp(-b) * cos(d_theta))) * cos(t_theta)
            - i * (2. * (-exp(-b) * cos(d_theta))) * sin(t_theta)
            + exp(-2 * b) * cos(2 * t_theta)
            - i* exp(-2 * b) * sin(2 * t_theta))
            / (1 + -1 * cos(t_theta) - i * (-1 * sin(t_theta))));
    }
    case 3:                         // implement twodiff gammatones
    {
        std::complex<double> c_theta = acos(2 * exp(b)*cos(t_theta) / (exp(2 * b) + 1));        // corrected pole angle for allpole stages
        std::complex<double> d_theta = acos(exp(-b) / 2 + exp(i * t_theta) / (double)2 + exp(i * t_theta) / (double)2 + exp(b) / 2 - (double)1);
                                                                                        // corrected pole angle for one-zero stages
        /*std::complex<double> a_pole = exp(-b - i * c_theta);
        std::complex<double> d_pole = exp(-b - i * d_theta);*/

        std::vector<std::complex<double>> a_poles = { exp(-b - i * c_theta), conj(exp(-b - i * c_theta))};
        std::vector<std::complex<double>> d_poles = { exp(-b - i * d_theta), conj(exp(-b - i * d_theta))};

        std::complex<double> d_zero = { 1.0, 0.0 };

        std::complex<double> a0_a = abs(
            1. + (2. * (-exp(-b)*cos(c_theta)))* cos(t_theta)
            - i * (2. * (-exp(-b)*cos(c_theta))) * sin(t_theta)
            + exp(-2 * b) * cos(2 * t_theta)
            - i * exp(-2 * b) * sin(2 * t_theta));

        std::complex<double> a0_d = abs(
            (1. + (2. * (-exp(-b) * cos(d_theta))) * cos(t_theta)
                - i * (2. * (-exp(-b) * cos(d_theta))) * sin(t_theta)
                + exp(-2 * b) * cos(2 * t_theta)
                - i* exp(-2 * b) * sin(2 * t_theta))
                / (1 + -1 * cos(t_theta) - i * (-1 * sin(t_theta))));

    }
}



return 0;
}

double damping()
{
double factor = pow(n_factorial(order - 1), 2) / (M_PI*n_factorial(2 * order - 2) * pow(2, -(2 * order - 2)));
return 2 * M_PI * factor * ERB(fc) / fs;

}

int n_factorial(int n)
{
return (n == 1 || n == 0) ? 1 : n_factorial(n - 1)*n;
}

double ERB(double f)
{
return 24.7 + f / 9.265;            
}

std::vector<std::complex<double>> expand_poly(std::vector<std::complex<double>> roots)
{
std::vector<std::complex<double>> result{1};

for (int ii = 0; ii < roots.size(); ++ii)
{
    std::vector <std::complex<double>> tmp{ result.begin(), result.end() };

    for (auto &item : tmp)
        item *= (-roots[ii]);

    result.push_back(0);
    for( int jj = 1; jj < result.size(); ++jj)
    {
        result[jj] += tmp[jj - 1];
    }
}
return result;
}


/* below is pretty much a copy of zp2sos from matlab but with all the impossible cases removed */
std::vector<std::complex<double>> formSOS(std::vector<std::complex<double>> poles, std::vector<std::complex<double>> zeroes)
{
int lz = zeroes.size();
int lp = poles.size();

std::vector<std::complex<double>> sos;

if(!lz)                     // no zeroes (all-pole)
{
    sos; // sosfun
    return sos;
}

if(!(lz % 2))               // even number of zeroes
{
    sos; // sosfun2
    sos; // sosfun
    return sos;
}

sos; // sosfun2

if (lz == lp)               // equal zeroes and poles
{
    sos; // last pole
    return sos;
}

// get num den using zp2tf
// assign sos


sos; // sosfun
return sos;

}

std::vector<std::complex<double>> sosfun(int start, int stop, std::vector<std::complex<double>> poles, std::vector<std::complex<double>> sos, int version)
{
/*switch (version)
    case 1:
    case 2:*/

std::vector<std::complex<double>> placeholder{0};
return placeholder; 
}

std::vector<std::complex<double>> zp2tf(std::vector<std::complex<double>> z, std::vector<std::complex<double>> p, std::complex<double> k)
{

std::vector<std::complex<double>> den;
std::vector<std::complex<double>> num;

std::vector<std::complex<double>> p_coeff = expand_poly(p);

for (int ii = 0; ii<p_coeff.size(); ++ii)
{
    den[ii] = p_coeff[ii].real();
}

if(!z.size())
{
    num = { {0.0, 0.0}, {0.0, 0.0}, k };
    num.insert(num.end(), den.begin(), den.end());
    // add num, den to same std::vector, return
}

std::vector<std::complex<double>> z_coeff = expand_poly(z);

for(int ii = 0; ii<z_coeff.size(); ++ii)
{
    num[ii] = (z_coeff[ii] * k).real();
}   

num.insert(num.end(), den.begin(), den.end());
return num;
}

2 个答案:

答案 0 :(得分:0)

鉴于即使没有cpp代码,关于kfr模块如何导致错误的评论,也许kfr与您正在使用的其他标头兼容。试试这个:

  • 使用 kfr标头编译一个空的cpp文件。
  • 也许它会丢失其他标题中的一些内容,根据需要添加这些内容,找到使其正常工作所需的最少功能
  • 如果可行,则在该cpp文件中创建函数,该文件从kfr。
  • 调用所需的函数
  • 然后,以外部函数或头文件的形式访问这些函数。

这样你就会有一个单独的模块(cpp文件),提供与kfr相关的资源。然后编写自己的自定义界面来访问它,但kfr的所有细节都没有暴露给其他模块。

BTW最小化共享标头可以避免混淆命名空间,并且有助于最大限度地减少大型程序的编译时间。理想情况下,尽可能多的#includes只包含cpp文件中的#c;需要知道&#34;基础。如果您只使用特定cpp文件中共享标头中的一个函数,请考虑直接在使用cpp文件中将该函数声明为&#34; extern&#34;,它会被抬起来查看链接时间,但如果更改标题,则不会导致重新编译。这也是每个标头有一个类的好理由,标题中只有类方法声明,而不是代码本身。然后,您只需要#include cpp文件中所需的简单内容,以了解哪个类是哪个类,并且更改实现不会导致整个程序被重新编译。

答案 1 :(得分:0)

也许您使用过期版本的KFR。

类似问题已于2016年9月6日修复: https://github.com/kfrlib/kfr/commit/8340aaa1bf6fd31b4f8c5c868de3025fc0e4e5c5

尝试更新到最新的主版本并再次检查。

原生Visual Studio支持计划于下周发布。然后,LLVM将不需要与Visual Studio一起使用。