gpt4 book ai didi

c++ - 在(qwt)示波器上绘制实时数据

转载 作者:太空宇宙 更新时间:2023-11-04 11:40:19 25 4
gpt4 key购买 nike

我正在尝试使用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 )

  • 关卡还有许多其他可能性,例如毛刺,相对边缘,...
  • 预览

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

    我使用 IN,所以我有立体声输入(A,B =左,右),因此我可以添加一些其他内容,例如:
  • 级别来源(A,B,无)
  • 渲染模式(时基,Chebyshev(如果关闭则为李沙育曲线))
  • Chebyshev = x轴为Ay轴为B,这将创建著名的Chebyshev图像,这些图像非常适合于相关的正弦信号。通常形成圆,椭圆,扭曲的循环...
  • 其他东西

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

    您需要进行许多设置,我更喜欢模拟旋钮,而不是像真正的示波器那样使用按钮/滚动条/滑块
  • (半)模拟值:幅度,时基,电平,X偏移,Y偏移
  • 离散值:电平模式(/,),电平源(A,B,-),每个通道(直接开,地面,关,容量开)

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


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

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

    PS。
  • 我从 DirectSound 开始,但是由于 buggy /非功能性缓冲区回调
  • ,它很烂
  • 我现在对我的Apps中的所有声音使用 WinAPI WaveIn / Out 。经过几次怪癖之后,它是满足我的需求的最佳选择,并且具有最佳的延迟(Directsound的速度太慢超过10倍),但是对于示波器却没有任何好处(对于模拟器,我通常需要低延迟)

  • 顺便说一句。我将这三个应用程序作为可链接的C++子窗口类(Borland)
  • ,最后一次与我的ATMega168仿真器一起用于无传感器BLDC驱动程序调试
  • 在这里您可以尝试我的Oscilloscope,generator and Spectrum analyser如果您对下载感到困惑,请阅读此帖子下方的评论 btw密码是:“oscill”

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

    [Edit1]触发

    您一次触发所有通道,但通常仅从一个通道检查触发条件。现在实现很简单,例如,让 触发条件 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++ - 在(qwt)示波器上绘制实时数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21656397/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com