在 C# 中,幅度到分贝总是返回 NaN
本文关键字:返回 NaN | 更新日期: 2023-09-27 18:19:08
所以我的问题已经从返回无穷大变成了返回NaN。 如果您的FFT总是返回无穷大,这可能会有所帮助(http://gerrybeauregard.wordpress.com/2011/04/01/an-fft-in-c/#comment-196(。 所以我认为它返回 NaN 是因为 C# 试图获取负数的平方根但是,根据下面的代码,该数字不应该是负数,因为我在获得平方根之前对两个数字进行平方(这应该使它们为正(。 但是,返回的数字为负数。 我已经尝试过使用多个变量来获取 re * re 和 im * im 以及两个结果加在一起的低效方法,但结果也是负数。 Math.Abs也不好。 我已经联系了FFT类的创建者(见我上面的链接(,正在等待他的下一个回复。 我从我之前做的 AS3 版本中获取了下面的一些代码。 如果我在这里得到答案之前从类创建者那里得到答案,那么我会发布它。 任何见解都是最有帮助的,感谢到目前为止在这方面帮助我的每个人。 我是一名 AS3 程序员,即将使用 C#(因为它的功能要强得多(,所以我可能错过了一些简单的东西。 我正在使用 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
谢谢!!
您定义了MIN_VALUE
是 System.Double.MinValue
,这是可能的最小双精度数。添加除System.Double.MaxValue
或正无穷大以外的任何内容都会得到负结果。取负数的对数返回NaN
。
我猜你希望MIN_VALUE
是最小的正数。在 C# 中,您可以使用System.Double.Epsilon
来实现此目的。(我知道...不应该这么称呼...
任何其他微小的值,如1e-100
,也可以工作。
for (int i = 0; i <tempRe.Length;>
乘法将始终为零,除非这是您想要的。
我找到了答案! 因此,事实证明,与C++、AS3 和其他一些语言不同,C# 具有负最小双精度值。
System.Double.MIN_VALUE = -1.7976931348623157E+308;
获取负数的平方根会导致 NaN 错误。 有关详细信息,请参阅 (http://www.codeproject.com/KB/cs/numprogrammingcs.aspx(。 我现在无法获得准确的 dB 读数,但我研究并看看我能找到什么。