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