Decibel的大小总是在C#中返回NaN

时间:2012-01-02 02:17:18

标签: c# fft unity3d nan infinity

所以我的问题已经从返回Infinity变为返回NaN。如果你的FFT总是返回Infinity,这可能会有所帮助(http://gerrybeauregard.wordpress.com/2011/04/01/an-fft-in-c/#comment-196)。所以我认为它正在返回NaN,因为C#试图得到负数的平方根,但是根据下面的代码,数字不应该是负数,因为我在得到平方根之前对两个数字进行平方(这应该是它们正)。但是,返回的数字是负数。我已经尝试过使用多个变量来获得re * re和im * im并将两个结果加在一起的效率低下,但结果也是负面的。 Math.Abs​​也不好。我联系了FFT类的创建者(参见上面的链接),我正在等待他的下一个回复。我从之前做过的AS3版本中获取了下面的一些代码。如果我在上课之前得到了班级创作者的答案,那么我会发布。任何见解都是最有帮助的,感谢所有迄今为止帮助过我的人。我是一名来到C#的AS3程序员(因为它的能力更强),所以我可能会错过一些简单的新东西。我正在使用Unity。

 private const uint LOGN = 11; // Log2 FFT Length

    private const uint N = 1 << (int)LOGN; // FFT Length

    private const uint BUF_LEN = N; // Audio buffer length

    public FFT2 fft; // FFT Object

    private double[] tempIm = new double[N]; // Temporary Imaginary Number array

    private double[] m_mag = new double[N/2]; // Magnitude array

    private double[] m_win = new double[N]; // Hanning Window 

    private int fftCount = 0; // How many times the FFT has been performed

    private double SCALE = (double)20/System.Math.Log(10); // used to convert magnitude from FFT to usable dB

    private double MIN_VALUE = (double)System.Double.MinValue;

...

    // Hanning analysis window
    for (int i = 0; i < N; i++) // for i < 2048
        m_win[i] = (4.0/N) * 0.5*(1-Mathf.Cos(2*Mathf.PI*i/N)); // Hanning Vector [1] = 1 / 4595889085.750801

...

// Perform FFT
fft.run(tempRe, tempIm);

fftCount++;

// Convert from Decibel to Magnitude
for (int i = 0; i < N/2; i++) {

double re = tempRe[i]; // get the Real FFT Number at position i
double im = tempIm[i]; // get the Imaginary FFT Number at position i

m_mag[i] = Math.Sqrt(re * re + im * im); // Convert magnitude to decibels

m_mag[i] = SCALE * Math.Log(m_mag[i] + MIN_VALUE);

if (fftCount == 50 && i == 400) print ("dB @ 399: " + m_mag[399]);
}

先前代码打印:

dB @ 400: NaN

-5.56725062513722E+33

谢谢!

2 个答案:

答案 0 :(得分:1)

您将MIN_VALUE定义为System.Double.MinValue,这是可能的最小双精度数。添加System.Double.MaxValue或正无穷大以外的任何内容都会产生负面结果。取负数的对数返回NaN

我猜你希望MIN_VALUE成为最小的正数。在C#中,您使用System.Double.Epsilon。 (我知道......不应该被称为......)

任何其他微小的值,例如1e-100,也会起作用。

答案 1 :(得分:0)

for(int i = 0; i&lt; tempRe.Length; i ++)tempRe [i] = m_win [i];

乘以它将始终为零,除非这是你想要的。