IfeSpectCtrl.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. using System;
  2. using System.ComponentModel;
  3. using System.Windows.Forms;
  4. using System.Runtime.InteropServices;
  5. using System.IO;
  6. using DevExpress.XtraEditors;
  7. namespace Ips.Sps.IfeSpects
  8. {
  9. public partial class IfeSpectCtrl : XtraUserControl
  10. {
  11. IntPtr speView = IntPtr.Zero;
  12. public IfeSpectCtrl()
  13. {
  14. InitializeComponent();
  15. }
  16. static IfeSpectCtrl()
  17. {
  18. IfeQTSpect.Init();
  19. }
  20. /// <summary>
  21. /// 重写 DesignMode
  22. /// </summary>
  23. protected new bool DesignMode
  24. {
  25. get
  26. {
  27. bool flag = false;
  28. if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
  29. {
  30. flag = true;
  31. }
  32. else if (System.Diagnostics.Process.GetCurrentProcess().ProcessName.ToUpper().Equals("DEVENV"))
  33. {
  34. flag = true;
  35. }
  36. return flag;
  37. }
  38. }
  39. /// <summary>
  40. /// 频谱窗口大小发生改变
  41. /// </summary>
  42. /// <param name="sender"></param>
  43. /// <param name="e"></param>
  44. private void spePanel_Resize(object sender, EventArgs e)
  45. {
  46. if (DesignMode)
  47. return;
  48. if (speView != IntPtr.Zero)
  49. {
  50. IfeQTSpect.ResizeView(speView, this.spePanel.Width, this.spePanel.Height);
  51. }
  52. }
  53. /// <summary>
  54. ///
  55. /// </summary>
  56. /// <param name="fun"></param>
  57. public void RegisterSelectIndexChanged(IfeQTSpect.SelectIndexChanged fun)
  58. {
  59. if (speView != IntPtr.Zero)
  60. {
  61. IfeQTSpect.RegisterSelectIndexChanged(speView, fun);
  62. }
  63. }
  64. /// <summary>
  65. /// 清空信号展示页面
  66. /// </summary>
  67. public void Clear()
  68. {
  69. if (speView != IntPtr.Zero)
  70. {
  71. IfeQTSpect.Clear(speView);
  72. }
  73. }
  74. /// <summary>
  75. /// 选中指定频率
  76. /// </summary>
  77. /// <param name="freq"></param>
  78. public void HitFrequence(double freq)
  79. {
  80. if (speView != IntPtr.Zero)
  81. {
  82. IfeQTSpect.SelectFrequence(speView, freq);
  83. }
  84. }
  85. /// <summary>
  86. /// 空间初始化
  87. /// </summary>
  88. /// <param name="sender"></param>
  89. /// <param name="e"></param>
  90. private void ItcSpectrum_Load(object sender, EventArgs e)
  91. {
  92. if (DesignMode)
  93. return;
  94. //频谱绘制
  95. speView = IfeQTSpect.CreateView(this.spePanel.Handle, this.spePanel.Width, this.spePanel.Height);
  96. //test
  97. //SetSource(@"E:\1.dat", 100000000, false, 1031000000, 13, 40, false, 100, 1500000, 5);
  98. }
  99. private double[] SetRealSource(String fileName, int fsample, UInt64 midFreq, int fftOrder, int smoothCount
  100. , bool autodoor, double doorline, int detectBw, double detectSnr)
  101. {
  102. double[] ret = null;
  103. if (speView != IntPtr.Zero)
  104. {
  105. IntPtr fft = IfeQTSpect.CalcFFT(fileName, false, fftOrder, smoothCount);
  106. int len = (int)Math.Pow(2, fftOrder - 1);
  107. float[] ckfft = new float[len];
  108. Marshal.Copy(fft, ckfft, 0, len);
  109. int sigCount = 1000;
  110. double[] tmp = new double[sigCount * 3];
  111. float fFreqReso = (float)(fsample / 2.0 / len);
  112. //IfeQTSpect.SignalDetecting(ckfft, len, fFreqReso, 1.0f, tmp, ref sigCount);
  113. IfeQTSpect.SignalDetecting(ckfft, len, fFreqReso, detectSnr, tmp, ref sigCount);
  114. double[] sigs = null;
  115. if (sigCount > 0)
  116. {
  117. ret = new double[sigCount * 3];
  118. sigs = new double[sigCount * 3];
  119. for (int idx = 0; idx < sigCount; ++idx)
  120. {
  121. sigs[3 * idx] = tmp[3 * idx];
  122. sigs[3 * idx + 1] = tmp[3 * idx + 1];
  123. sigs[3 * idx + 2] = tmp[3 * idx + 2];
  124. ret[3 * idx] = tmp[3 * idx] + midFreq - 20000000;
  125. ret[3 * idx + 1] = tmp[3 * idx + 1];
  126. ret[3 * idx + 2] = tmp[3 * idx + 2];
  127. }
  128. }
  129. IfeQTSpect.ShowFFT(speView, fft, len, false, fsample, midFreq - 20000000, sigs, sigCount);
  130. IfeQTSpect.freeBuffer(fft);
  131. }
  132. return ret;
  133. }
  134. private double[] SetIQSource(String fileName, int fsample, UInt64 midFreq, int fftOrder, int smoothCount
  135. , bool autodoor, double doorline, int detectBw, double detectSnr)
  136. {
  137. double[] ret = null;
  138. if (speView != IntPtr.Zero)
  139. {
  140. IntPtr fft = IfeQTSpect.CalcFFT(fileName, true, fftOrder, smoothCount);
  141. int len = (int)Math.Pow(2, fftOrder);
  142. IntPtr tmpFFT = IntPtr.Add(fft, (int)(len * 0.1) * sizeof(float));
  143. float[] ckfft = new float[(int)(len * 0.8)];
  144. Marshal.Copy(tmpFFT, ckfft, 0, (int)(len * 0.8));
  145. int sigCount = 1000;
  146. double[] tmp = new double[sigCount * 3];
  147. float fFreqReso = (float)(fsample * 1.0 / len);
  148. //IfeQTSpect.SignalDetecting(ckfft, (int)(len * 0.8), fFreqReso, 1.0f, tmp, ref sigCount);
  149. IfeQTSpect.SignalDetecting(ckfft, (int)(len * 0.8), fFreqReso, detectSnr, tmp, ref sigCount);
  150. double[] sigs = null;
  151. if (sigCount > 0)
  152. {
  153. ret = new double[sigCount * 3];
  154. sigs = new double[sigCount * 3];
  155. for (int idx = 0; idx < sigCount; ++idx)
  156. {
  157. sigs[3 * idx] = tmp[3 * idx] + fsample * 0.1 /*+ (midFreq - (UInt64)fsample / 2)*/;
  158. sigs[3 * idx + 1] = tmp[3 * idx + 1];
  159. sigs[3 * idx + 2] = tmp[3 * idx + 2];
  160. ret[3 * idx] = tmp[3 * idx] + fsample * 0.1 + (midFreq - (UInt64)fsample / 2);
  161. ret[3 * idx + 1] = tmp[3 * idx + 1];
  162. ret[3 * idx + 2] = tmp[3 * idx + 2];
  163. }
  164. }
  165. IfeQTSpect.ShowFFT(speView, fft, len, true, fsample, (midFreq - (UInt64)fsample / 2), sigs, sigCount);
  166. IfeQTSpect.freeBuffer(fft);
  167. }
  168. return ret;
  169. }
  170. /// <summary>
  171. /// 设置数据源
  172. /// </summary>
  173. /// <param name="fileName">原始文件</param>
  174. /// <param name="fsample">采样率 Hz</param>
  175. /// <param name="beIQ">是否IQ数据</param>
  176. /// <param name="minFreq">显示的最小频率</param>
  177. /// <param name="fftOrder">fft阶数</param>
  178. /// <param name="smoothCount">平滑次数</param>
  179. /// <param name="autodoor"></param>
  180. /// <param name="doorline"></param>
  181. /// <param name="detectBw"></param>
  182. /// <param name="detectSnr"></param>
  183. public double[] SetSource(String fileName, int fsample, bool beIQ, UInt64 midFreq, int fftOrder, int smoothCount
  184. , bool autodoor, double doorline, int detectBw, double detectSnr)
  185. {
  186. double[] ret = null;
  187. if (!beIQ)
  188. {
  189. ret = SetRealSource(fileName, fsample, midFreq, fftOrder, smoothCount, autodoor, doorline, detectBw, detectSnr);
  190. }
  191. else
  192. {
  193. ret = SetIQSource(fileName, fsample, midFreq, fftOrder, smoothCount, autodoor, doorline, detectBw, detectSnr);
  194. }
  195. return ret;
  196. }
  197. }
  198. public class IfeQTSpect
  199. {
  200. //动态库位置
  201. public const string dllName = @"IfeSpect\IfeSpect.dll";
  202. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)]
  203. public static extern bool SignalDetecting(float[] Spectrum, int SpecLen, double freqReso, double snrThreshold, double[] Sig, ref int SigNum);
  204. /// <summary>
  205. /// 界面当前选择改变
  206. /// </summary>
  207. /// <param name="index"></param>
  208. public delegate void SelectIndexChanged(int index);
  209. /// <summary>
  210. /// 初始化 必须在Main函数中提前调用
  211. /// </summary>
  212. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  213. public static extern void Init();
  214. /// <summary>
  215. /// 创建一个频谱展示控件
  216. /// </summary>
  217. /// <param name="parent"></param>
  218. /// <returns></returns>
  219. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  220. public static extern IntPtr CreateView(IntPtr parent, int w, int h);
  221. /// <summary>
  222. /// 销毁控件
  223. /// </summary>
  224. /// <param name="view"></param>
  225. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  226. public static extern void DestoryView(IntPtr view);
  227. /// <summary>
  228. /// 计算频谱
  229. /// </summary>
  230. /// <param name="fileName"></param>
  231. /// <param name="beIQ"></param>
  232. /// <param name="fftOrder"></param>
  233. /// <param name="smoothCount"></param>
  234. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  235. public static extern IntPtr CalcFFT(String fileName, bool beIQ, int fftOrder, int smoothCount);
  236. /// <summary>
  237. /// 释放C++申请的内存空间
  238. /// </summary>
  239. /// <param name="ptr"></param>
  240. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  241. public static extern void freeBuffer(IntPtr ptr);
  242. /// <summary>
  243. /// 显示频谱数据
  244. /// </summary>
  245. /// <param name="ptr"></param>
  246. /// <param name="buffer"></param>
  247. /// <param name="len"></param>
  248. /// <param name="beIQ"></param>
  249. /// <param name="fsample"></param>
  250. /// <param name="minFreq"></param>
  251. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  252. public static extern void ShowFFT(IntPtr ptr, IntPtr buffer, int len, bool beIQ
  253. , int fsample, UInt64 minFreq
  254. , double[] sig, int siglen);
  255. /// <summary>
  256. /// 输入频谱检测信号
  257. /// </summary>
  258. /// <param name="fftbuffer"></param>
  259. /// <param name="len"></param>
  260. /// <param name="reslen"></param>
  261. /// <param name="sf"></param>
  262. /// <param name="ef"></param>
  263. /// <param name="bw"></param>
  264. /// <param name="autodoor"></param>
  265. /// <param name="doorline"></param>
  266. /// <param name="detectBw"></param>
  267. /// <param name="detectSnr"></param>
  268. /// <returns></returns>
  269. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  270. public static extern IntPtr fftCheck(IntPtr fftbuffer, int len, ref int reslen
  271. , double sf, double ef, double bw
  272. , bool autodoor, double doorline, int detectBw, double detectSnr);
  273. /// <summary>
  274. /// 注册界面信号变动
  275. /// </summary>
  276. /// <param name="ptr"></param>
  277. /// <param name="fun"></param>
  278. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  279. public static extern void RegisterSelectIndexChanged(IntPtr ptr, SelectIndexChanged fun);
  280. /// <summary>
  281. /// 创建一个频谱展示控件
  282. /// </summary>
  283. /// <param name="parent"></param>
  284. /// <returns></returns>
  285. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  286. public static extern void ResizeView(IntPtr ptr, int w, int h);
  287. /// <summary>
  288. /// 清空页面展示
  289. /// </summary>
  290. /// <param name="parent"></param>
  291. /// <returns></returns>
  292. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  293. public static extern void Clear(IntPtr ptr);
  294. /// <summary>
  295. /// 设置显示范围
  296. /// </summary>
  297. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  298. public static extern void SetShowRangeX(IntPtr ptr, double vMin, double vMax);
  299. /// <summary>
  300. /// 选中一个信号
  301. /// </summary>
  302. /// <param name="freq">信号中心频率</param>
  303. [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
  304. public static extern void SelectFrequence(IntPtr ptr, double freq);
  305. }
  306. }