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

Posted

技术标签:

【中文标题】分贝的大小总是在 C# 中返回 NaN【英文标题】:Magnitude to Decibel always returns NaN in C# 【发布时间】:2012-01-31 14:05:30 【问题描述】:

所以我的问题已经从返回 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

谢谢!!

【问题讨论】:

看看this sample 同时检查调试器这一行m_mag[i] = 10 * Mathf.Log10(Mathf.Sqrt((float)((re * re) + (im * im)))); real 和 imaginary 的值是多少? 谢谢!我现在正在研究那个框架。那里没有任何指向实际傅立叶源的链接,只是应用程序的图片。由于某种原因,在网站的下载部分,或者在托管其他一些东西的 CodeProject 上没有运气。调试后, re 和 im 都返回每个索引中两个数组的可用数字。我一直在检查这个数学,但它基本上正是我在 AS3 版本中使用的,分贝公式的大小是我检查的每个来源所推荐的。 FFT前tempRe数组的取值范围是多少? @Jake 链接确实似乎已经死了。尝试从 Softpedia 下载它。我现在记得你首先需要安装提供基本库的AForge.NET,然后是Accord.NET。第二次安装时应提供样品。 【参考方案1】:

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

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

任何其他微小的值,例如1e-100,也可以使用。

【讨论】:

谢谢!我想我们同时找到了答案:p 我现在遇到了另一个问题,但我认为它与 FFT 类本身有关。【参考方案2】:

for (int i = 0; i

乘以它总是为零,除非那是你想要的。

【讨论】:

我刚刚将 Hanning Window 代码添加到顶部。我需要将它相乘才能应用 Window。如果我将它设置为窗口,那么我不会对实际样本进行 FFT。调试显示 tempRe 在 FFT 之前包含可用数据。 我已经解决了另一个问题,但是有一个与此相关的新问题。感谢你的帮助。我已经更新了上面的问题。【参考方案3】:

我找到了答案!所以事实证明,与 C++、AS3 和其他一些语言不同,C# 具有负的最小双精度值。

System.Double.MIN_VALUE = -1.7976931348623157E+308;

获取负数的平方根会导致 NaN 错误。有关详细信息,请参阅 (http://www.codeproject.com/KB/cs/numprogrammingcs.aspx)。我现在无法获得准确的 dB 读数,但我研究了一下,看看能找到什么。

【讨论】:

以上是关于分贝的大小总是在 C# 中返回 NaN的主要内容,如果未能解决你的问题,请参考以下文章

笔记:错误记录- gdal读取哨兵1雷达数据分贝化数据极值为nan

笔记:错误记录- gdal读取哨兵1雷达数据分贝化数据极值为nan

返回文件大小总是得到 0

笔记:错误记录- gdal读取哨兵1雷达数据分贝化数据归一化计算极值为nan,输出相同错误结果

C#:锚定面板不会正确调整大小

分贝(dB)