/// <summary> /// <para>Computes the power spectrum of input time-domain signal.</para> /// <para>Chinese Simplified: 计算输入信号的功率频谱。</para> /// </summary> /// <param name="waveform"> /// <para>input time-domain signal.</para> /// <para>Chinese Simplified: 输入的时域波形。</para> /// </param> /// <param name="samplingRate"> /// <para>sampling rate of the input time-domain signal, in samples per second.</para> /// <para>Chinese Simplified: 输入信号的采样率,以S/s为单位。</para> /// </param> /// <param name="spectrum"> /// <para>output sequence containing the power spectrum.</para> /// <para>Chinese Simplified: 输出功率谱。</para> /// </param> /// <param name="df"> /// <para>the frequency resolution of the spectrum, in hertz.</para> /// <para>Chinese Simplified: 功率谱的频谱间隔,以Hz为单位。</para> /// </param> /// <param name="unitSettings"> /// <para>unit settings of the output power spectrum</para> /// <para>Chinese Simplified: 设置功率谱的单位。</para> /// </param> /// <param name="windowType"> /// <para>the time-domain window to apply to the time signal.</para> /// <para>Chinese Simplified: 窗类型。</para> /// </param> /// <param name="windowPara"> /// <para>parameter for a Kaiser/Gaussian/Dolph-Chebyshev window, If window is any other window, this parameter is ignored</para> /// <para>Chinese Simplified: 窗调整系数,仅用于Kaiser/Gaussian/Dolph-Chebyshev窗。</para> /// </param> public static void PowerSpectrum(double[] waveform, double samplingRate, ref double[] spectrum, out double df, UnitConvSetting unitSettings, WindowType windowType, double windowPara) { int spectralLines = spectrum.Length; //谱线数是输出数组的大小 SpectralInfo spectralInfo = new SpectralInfo(); AdvanceComplexFFT(waveform, spectralLines, windowType, spectrum, ref spectralInfo); double scale = 1.0 / spectralInfo.FFTSize; CBLASNative.cblas_dscal(spectralLines, scale, spectrum, 1); df = 0.5 * samplingRate / spectralInfo.spectralLines; //计算频率间隔 //Unit Conversion UnitConversion(spectrum, df, SpectrumType.Amplitude, unitSettings, Window.WindowENBWFactor[(int)windowType]); }
/// <summary> /// <para>Computes the power spectrum of input time-domain signal.</para> /// <para>Chinese Simplified: 计算输入信号的功率频谱。</para> /// </summary> /// <param name="waveform"> /// <para>input time-domain signal.</para> /// <para>Chinese Simplified: 输入的时域波形。</para> /// </param> /// <param name="samplingRate"> /// <para>sampling rate of the input time-domain signal, in samples per second.</para> /// <para>Chinese Simplified: 输入信号的采样率,以S/s为单位。</para> /// </param> /// <param name="spectrum"> /// <para>output sequence containing the power spectrum.</para> /// <para>Chinese Simplified: 输出功率谱。</para> /// </param> /// <param name="df"> /// <para>the frequency resolution of the spectrum, in hertz.</para> /// <para>Chinese Simplified: 功率谱的频谱间隔,以Hz为单位。</para> /// </param> /// <param name="unit"> /// <para>unit of the output power spectrum</para> /// <para>Chinese Simplified: 设置功率谱的单位。</para> /// </param> /// <param name="windowType"> /// <para>the time-domain window to apply to the time signal.</para> /// <para>Chinese Simplified: 窗类型。</para> /// </param> /// <param name="windowPara"> /// <para>parameter for a Kaiser/Gaussian/Dolph-Chebyshev window, If window is any other window, this parameter is ignored</para> /// <para>Chinese Simplified: 窗调整系数,仅用于Kaiser/Gaussian/Dolph-Chebyshev窗。</para> /// </param> /// <param name="PSD"> /// <para>specifies whether the output power spectrum is converted to power spectral density.</para> /// <para>Chinese Simplified: 输出的频谱是否为功率谱密度。</para> /// </param> public static void PowerSpectrum(double[] waveform, double samplingRate, ref double[] spectrum, out double df, SpectrumUnits unit = SpectrumUnits.V2, WindowType windowType = WindowType.Hanning, double windowPara = double.NaN, bool PSD = false) { int spectralLines = spectrum.Length; //谱线数是输出数组的大小 SpectralInfo spectralInfo = new SpectralInfo(); AdvanceComplexFFT(waveform, spectralLines, windowType, spectrum, ref spectralInfo); double scale = 1.0 / spectralInfo.FFTSize; CBLASNative.cblas_dscal(spectralLines, scale, spectrum, 1); df = 0.5 * samplingRate / spectralInfo.spectralLines; //计算频率间隔 //Unit Conversion UnitConvSetting unitSettings = new UnitConvSetting(unit, PeakScaling.Rms, 50.00, PSD); UnitConversion(spectrum, df, SpectrumType.Amplitude, unitSettings, Window.WindowENBWFactor[(int)windowType]); }
/// <summary> /// 频谱单位转换函数 /// </summary> /// <param name="spectrum">输入频谱,单位转换后返回的序列也保存在里面</param> /// <param name="spectrumType">输入频谱类型,功率谱或者幅度谱</param> /// <param name="df">频谱间隔</param> /// <param name="unitSetting">单位转换设置</param> /// <param name="equivalentNoiseBw">计算频谱时,加窗所用窗函数的等效噪声带宽</param> /// <returns></returns> private static void UnitConversion(double[] spectrum, double df, SpectrumType spectrumType, UnitConvSetting unitSetting, double equivalentNoiseBw) { double scale = 1.0; int freq0Idx = 0, N = spectrum.Length; //VMLNative.vdSqr(N, spectrum, spectrum); if (unitSetting.PeakScaling == PeakScaling.Peak) //峰峰值要乘以2 { switch (spectrumType) { case SpectrumType.Amplitude: // Sqrt2 scale *= Sqrt2; break; case SpectrumType.Power: // 2 scale *= 2; break; default: throw new ArgumentOutOfRangeException(nameof(spectrumType), spectrumType, null); } CBLASNative.cblas_dscal(N, scale, spectrum, 1); spectrum[0] /= scale; //零频不用 } //根据设置的转换单位进行转换 switch (unitSetting.Unit) { case SpectrumUnits.V: { if (SpectrumType.Power == spectrumType) { VMLNative.vdSqrt(N, spectrum, spectrum); } break; } case SpectrumUnits.dBV: { if (SpectrumType.Power == spectrumType) { VMLNative.vdSqrt(N, spectrum, spectrum); } //lg VMLNative.vdLog10(N, spectrum, spectrum); scale = 20; //20*lg CBLASNative.cblas_dscal(N, scale, spectrum, 1); break; } case SpectrumUnits.dBmV: { if (SpectrumType.Power == spectrumType) { VMLNative.vdSqrt(N, spectrum, spectrum); } CBLASNative.cblas_dscal(N, 1e3, spectrum, 1); //V To mV VMLNative.vdLog10(N, spectrum, spectrum); //To Lg scale = 20; CBLASNative.cblas_dscal(N, scale, spectrum, 1); //To 20*Lg break; } case SpectrumUnits.dBuV: { if (SpectrumType.Power == spectrumType) { VMLNative.vdSqrt(N, spectrum, spectrum); } CBLASNative.cblas_dscal(N, 1e6, spectrum, 1); //V To uV VMLNative.vdLog10(N, spectrum, spectrum); //To Lg scale = 20; CBLASNative.cblas_dscal(N, scale, spectrum, 1); //To 20*Lg break; } case SpectrumUnits.V2: { if (SpectrumType.Amplitude == spectrumType) { VMLNative.vdSqr(N, spectrum, spectrum); } break; } case SpectrumUnits.W: case SpectrumUnits.dBW: case SpectrumUnits.dBm: { if (SpectrumType.Amplitude == spectrumType) { VMLNative.vdSqr(N, spectrum, spectrum); } scale = 1.0 / unitSetting.Impedance; //1/R CBLASNative.cblas_dscal(N, scale, spectrum, 1); //W = V^2/R if (unitSetting.Unit == SpectrumUnits.dBW) //dBW = 20lgW { //lg VMLNative.vdLog10(N, spectrum, spectrum); scale = 20; //20*lg CBLASNative.cblas_dscal(N, scale, spectrum, 1); } else if (unitSetting.Unit == SpectrumUnits.dBm) // dBm = 10lg(W/1mW) { CBLASNative.cblas_dscal(N, 1e3, spectrum, 1); // W/1mW //lg VMLNative.vdLog10(N, spectrum, spectrum); scale = 10; //10*lg CBLASNative.cblas_dscal(N, scale, spectrum, 1); } break; } default: { break; } } if (!unitSetting.PSD) { return; } //谱密度计算 scale = 1.0 / (equivalentNoiseBw * df); CBLASNative.cblas_dscal(N, scale, spectrum, 1); }