为了账号安全,请及时绑定邮箱和手机立即绑定

在(qwt)示波图上绘制实时数据

/ 猿问

在(qwt)示波图上绘制实时数据

C++
一只名叫tom的猫 2019-12-06 15:32:55

我正在尝试使用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之后。我看不到如何仅触发一个频道


查看完整描述

3 回答

?
白衣非少年

呵呵这几年在上课时为学生做过。我希望您知道示波器的工作原理,因此这里只是基础知识:


时基


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

尝试使用尽可能大(44100,48000, ???)的频率,以使检测到的最大频率fsmpl/2成为时基轴的顶部。下限由您的缓冲区长度确定



创建函数,该函数将从指定的起始地址(内部缓冲区)中呈现采样缓冲区,方法如下:


Y刻度...振幅设置

Y偏移...垂直光束位置

X偏移...时移或水平位置

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


水平


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


振幅: ( < lvl ) -> ( > lvl )

振幅: ( > lvl ) -> ( < lvl )

水平还有许多其他可能性,例如毛刺,相对边缘,...


预习


例如,您可以将所有这些放在一起:您有start address变量,因此可以将数据连续采样到某个缓冲区,并在计时器调用时level进行start address(并更新)。然后使用new调用draw start address并将其添加timebase period到start address(当然是根据您的示例)


多通道


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


电平源(A,B,无)

渲染模式(时基,Chebyshev(如果关闭,则为Lissajous曲线))

Chebyshev = x轴为A,y轴为,B这将创建著名的Chebyshev图像,这对于相关的正弦信号非常有用。通常形成圆,椭圆,扭曲的圈...

杂物


您可以为模拟电容或输入接地的通道添加滤波器,甚至更多


图形用户界面


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


(半)模拟值:振幅,时基,电平,X偏移,Y偏移

离散值:电平模式(/,),电平源(A,B,-),每个通道(直接开,地面,关,容量开)

这是示波器的一些屏幕截图:


示波器 示波器


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


发电机


最后,在添加一些FFT之后,频谱分析仪


频谱分析仪


PS。


我从DirectSound开始,但是由于bug /非功能性的缓冲区回调,它吸了很多东西

我现在将WinAPI WaveIn / Out用于应用程序中的所有声音。经过几次怪癖之后,它是满足我的需求的最佳选择,并且具有最佳的延迟(Directsound的速度太慢超过10倍),但是对于示波器却没有任何好处(对于模拟器,我需要低延迟)

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


最后与我的ATMega168仿真器一起用于无传感器BLDC驱动程序调试

在这里您可以尝试使用我的示波器,发生器和频谱分析仪。如果您对下载感到困惑,请阅读此博文下方的评论btw密码为:“ oscill”

希望它对您有所帮助,只是在评论我时


[Edit1]触发器


您一次触发所有通道,但通常仅从一个通道检查触发条件。现在实现很简单,例如,让触发条件为A(left)通道上升到水平以上,因此:


首先使连续播放而没有触发,您写的是这样的:


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语句对所有触发条件进行编码


查看完整回答
反对 回复 2019-12-06
?
元芳怎么了

您可以将代码发布到问题中,以便其他人也可以看到并获得帮助(只是不要忘记选择它并单击代码格式按钮,这样它将在灰色区域中以语法突出显示和代码行格式显示)。在项目符号下添加代码,在每行中添加n * 4空格,直到其变为灰色为止。对于子问题,也将它们添加到您的问题中(例如,为其编号Q1,Q2,...),我们将尝试回答它们(我相信会有其他人添加到该问题中)。顺便说一句,我的代码大多是在bds2006 C ++ win32中编写的,因此与Qwt或其他平台有关的问题无论如何都必须回答其他人。

查看完整回答
反对 回复 2019-12-06
?
holdtom

我两个通道都只有一个缓冲区,我使用Qt,通道的值在缓冲区上交错。这就是我如何为(int i = 0,j = 0; i <countSamples; ++ j)分离值的方法{YVectorRight [j] = Samples [i ++]; YVectorLeft [j] =样本[i ++];在绘制YvectorRight和YvectorLeft之后。我不知道如何触发只有一个通道 

查看完整回答
反对 回复 2019-12-06

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信