其他分享
首页 > 其他分享> > c – 在(qwt)Oscillocope上绘制实时数据

c – 在(qwt)Oscillocope上绘制实时数据

作者:互联网

我正在尝试使用Qt(c)创建一个程序,它可以使用QAudioinput和QIODevice从我的麦克风录制音频.
现在,我想要想象我的信号

任何帮助,将不胜感激.谢谢

[Edit1] – 从您的评论中复制(由Spektre提供)

>我对这两个频道只有一个缓冲区
>我使用Qt,通道的值在缓冲区上交错
>这就是我如何分离价值观

for ( int i = 0, j = 0; i < countSamples ; ++j) 
 {
 YVectorRight[j]=Samples[i++];
 YVectorLeft[j] =Samples[i++];
 }

>在我绘制YvectorRight和YvectorLeft之后.我不知道如何只触发一个频道

解决方法:

嘿嘿几年前他们在课堂上为学生们做了这件事.我希望你知道示波器是如何工作的,所以这里只是基础知识:

>时基

> fsmpl是输入信号采样频率[Hz]

尽量使用尽可能大的(44100,48000,???),这样检测到的最大频率就是fsmpl / 2,这就是你的时基轴的顶部.下限由缓冲区长度给出
>画画

创建将从指定的起始地址(内部缓冲区)渲染采样缓冲区的函数:

> Y尺度……幅度设定
> Y偏移…垂直光束位置
> X偏移…时移或水平位置

这可以通过修改起始地址或仅通过X偏移曲线来完成
>等级

创建将模拟Level功能的函数.因此从起始地址搜索缓冲区,如果幅度跨越等级则停止.您可以拥有更多模式,但这些是您应该实现的基础知识:

>幅度:(< lvl) - > (> lvl)
>幅度:(> lvl) – > (< lvl)
还有许多其他可能性,如毛刺,相对边缘,……
>预览

您可以将所有这些组合在一起,例如:您有起始地址变量,因此将数据连续采样到某个缓冲区,并在计时器调用级别上使用起始地址(并更新它).然后使用新的起始地址调用draw并将时基周期添加到起始地址(当然是在样本中)
>多渠道

我使用Line IN所以我有立体声输入(A,B =左,右)因此我可以添加一些其他的东西,如:

>等级源(A,B,无)
>渲染模式(时基,切比雪夫(Lissajous曲线,如果关闭))
> Chebyshev = x轴是A,y轴是B,这创造了着名的Chebyshev图像,这对于相关的正弦信号是有益的.通常形成圆形,椭圆形,扭曲的环……

>杂乱的东西

您可以为模拟电容或输入接地的通道添加滤波器等等
> GUI

您需要许多设置我更喜欢模拟旋钮而不是按钮/滚动条/滑块,就像真正的示波器一样

>(半)模拟值:幅度,时基,电平,X偏移,Y偏移
>离散值:电平模式(/,),电平源(A,B, – ),每个通道(直接接通,接地,断开,容量接通)

以下是我的示波器的一些屏幕截图:

这是我的生成器的屏幕截图:

最后加入一些FFT后还有频谱分析仪

PS.

>我从DirectSound开始,但由于有缺陷/无功能的缓冲区回调,它很糟糕
>我现在在我的应用程序中使用WinAPI WaveIn / Out来获取所有声音.经过几次诡计之后,对我的需求是最好的,并且具有最佳延迟(Directsound太慢超过10次)但是对于示波器它没有任何优点(我需要低延迟,主要是模拟器)

顺便说一句.我将这三个应用程序作为可链接的C子窗口类(Borland)

>并且最后用于我的ATMega168仿真器,用于无传感器BLDC驱动程序调试
>在这里你可以尝试我的Oscilloscope,generator and Spectrum analyser如果你对下载感到困惑阅读下面的评论这篇文章btw密码是:“oscill”

希望如果您需要任何帮助,只需对我发表评论即可

[Edit1]触发器

您可以立即触发所有通道,但通常仅从1检查触发条件.现在实现很简单,例如让触发条件为A(左)通道上升到水平以上:

>首先连续播放没有你写的触发器是这样的:

for ( int i = 0, j = 0; i < countSamples ; ++j) 
 {
 YVectorRight[j]=Samples[i++];
 YVectorLeft[j] =Samples[i++];
 }
// here draw or FFT,draw  buffers YVectorRight,YVectorLeft

>添加触发器

要添加触发条件,您只需找到符合它的样本并从中开始绘制,以便将其更改为类似的内容

// static or global variables
static int i0=0; // actual start for drawing
static bool _copy_data=true; // flag that new samples need to be copied
static int level=35; // trigger level value datatype should be the same as your samples...

int i,j;
for (;;)
 {
 // copy new samples to buffer if needed
 if (_copy_data)
  for (_copy_data=false,i=0,j=0;i<countSamples;++j) 
  {
  YVectorRight[j]=Samples[i++];
  YVectorLeft[j] =Samples[i++];
  }
 // now search for new start
 for (i=i0+1;i<countSamples>>1;i++) 
  if (YVectorLeft[i-1]<level) // lower then level before i
   if (YVectorLeft[i]>=level) // higher then level after i
    {
    i0=i;
    break;
    }
 if (i0>=(countSamples>>1)-view_samples) { i0=0; _copy_data=true; continue; }
 break;
 }
// here draw or FFT,draw  buffers YVectorRight,YVectorLeft from i0 position

> view_samples是查看/处理的数据大小(对于一个或多个屏幕),它应该比(countSamples>> 1)少几倍
>这个代码可以松开边框区域的一个屏幕,以避免你需要为启动器实现循环缓冲机器人甚至可以
>只需通过if或switch语句对所有触发条件进行编码

标签:c,plot,qwt,real-time-data
来源: https://codeday.me/bug/20190916/1807911.html