本文介绍了绘制实时数据on(qwt)Oscillocope的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我试图创建一个程序,使用Qt(c + +),它可以使用QAudioinput和QIODevice记录来自我的麦克风的音频。 现在,我想要显示我的信号 任何帮助将不胜感激。感谢 [Edit1] - 从您的评论(Spektre)复制。 每个通道只有一个缓冲区 我使用Qt,通道的值在缓冲区上交错 p>这是我如何分隔值 for(int i = 0,j = 0; i< countSamples; ++ j) { YVectorRight [j] = Samples [i ++]; YVectorLeft [j] = Samples [i ++];我绘制YvectorRight和YvectorLeft后,} 我不知道如何只触发一个频道 解决方案 hehe done这几年回来给学生上课。我希望你知道示波器是如何工作的,这里只是基本的: 时基 > fsmpl 是输入信号采样频率[Hz] 尝试使用尽可能大的(44100,48000,???),因此检测到的最大频率为 fsmpl / 2 这将给你的时基轴的顶部。下限由您的缓冲区长度确定 创建将从指定的起始地址(内部缓冲区)中提取采样缓冲区的函数: Y- li> Y偏移...垂直光束位置 X偏移...时移或水平位置 这可以通过修改起始地址或者通过X偏移曲线完成。 创建可模拟级别功能的函数。所以搜索缓冲区从起始地址开始,如果幅度交叉电平,则停止。您可以拥有更多模式,但这些是您应该实现的基础: amplitude:(< lvl) - > ; (> lvl) amplitude:(> lvl) - > (< lvl) 像这样:你有开始地址变量所以示例数据到一些缓冲区连续和定时调用 level 与开始地址(并更新它)。然后使用新的开始地址调用draw并将时基周期添加到开始地址(当然按照您的样品) 多渠道 我使用 Line IN,所以我有立体声输入(A,B =左,右),因此我可以添加一些其他的东西,如: 级别源( A,B ,none) 渲染模式(时基,Chebyshev曲线如果关闭)) Chebyshev = x axis A code> y axis是 B 这创建了着名的切比雪夫图像,它有利于依赖的正弦信号。通常会形成圆,椭圆,扭曲的圆环... 您可以为模拟电容或输入接地的通道添加过滤器 strong> 您需要许多设置,我喜欢模拟旋钮而不是像真实示波器上的按钮/滚动条/滑块 (半)模拟值:幅度,时基,电平,X偏移,Y偏移 离散值:电平模式 每个频道(A,B, 这里是我的示波器的一些截图: 以下是我的生成器的屏幕截图: 最后在添加一些FFT频谱分析仪之后 PS 我开始使用 DirectSound ,但由于有错误/非功能缓冲回调,它很吸引人。 我现在使用 WinAPI WaveIn / Out 在我的应用程序中的所有声音。与它的几个怪癖,是最好的我的需要,并有最好的延迟(Directsound太慢超过10倍),但对于示波器没有优点(我需要低延迟,主要是仿真器) Btw。我有这三个应用程序作为可链接的C + +子窗口类(Borland) 最后使用我的ATMega168模拟器的无传感器BLDC驱动程序调试 在这里,您可以尝试我的示波器,发生器和频谱分析仪如果您对下载感到困惑,请阅读此帖以下的评论 btw password is:swing [Edit1] trigger $ b 您同时触发所有通道,但触发条件通常只是从一个检查现在实现很简单,例如让触发条件为 A(左)通道上升: $ $ $ 首先进行连续播放, > for(int i = 0,j = 0; i { YVectorRight [j] = Samples [i ++]; YVectorLeft [j] = Samples [i ++]; } //此处绘制或FFT,绘制缓冲区YVectorRight,YVectorLeft 添加触发器 要添加触发条件,您只需找到符合条件的样品,然后从中开始绘制,即可将其更改为 //静态或全局变量 static int i0 = 0; //实际开始绘制 static bool _copy_data = true; //标志需要复制新样本 static int level = 35; //触发级别值的数据类型应该和你的样例一样... int i,j; for(;;) { //如果需要,将新样本复制到缓冲区 if(_copy_data) for(_copy_data = false,i = 0,j = 0; i { YVectorRight [j] = Samples [i ++]; YVectorLeft [j] = Samples [i ++]; } //现在搜索新的开始 for(i = i0 + 1; i 1; i ++) if(YVectorLeft [i-1] < level)//低于i 之前的级别if(YVectorLeft [i]> = level)//高于i 之后的级别{ i0 = i; break; } if(i0> =(countSamples>> 1)-view_samples){i0 = 0; _copy_data = true;继续; } break; } //这里绘制或FFT,绘制缓冲区YVectorRight,YVectorLeft从i0位置 view_samples 是查看/处理的数据大小(对于一个或多个屏幕),应小于(countSamples>> 1) 此代码可以在边框区域松开一个屏幕,以避免需要实现循环缓冲bot > I'm trying to create a program, using Qt (c++), which can record audio from my microphone using QAudioinput and QIODevice.Now, I want to visualize my signalAny help would be appreciated. Thanks[Edit1] - copied from your comment (by Spektre)I Have only one Buffer for both channelI use Qt , the value of channel are interlaced on bufferthis is how I separate valuesfor ( int i = 0, j = 0; i < countSamples ; ++j) { YVectorRight[j]=Samples[i++]; YVectorLeft[j] =Samples[i++]; }after I plot YvectorRight and YvectorLeft. I don't see how to trigger only one channel 解决方案 hehe done this few years back for students during class. I hope you know how oscilloscopes works so here are just the basics:timebasefsmpl is input signal sampling frequency [Hz]Try to use as big as possible (44100,48000, ???) so the max frequency detected is then fsmpl/2 this gives you the top of your timebase axis. The low limit is given by your buffer lengthdrawCreate function that will render your sampling buffer from specified start address (inside buffer) with:Y-scale ... amplitude settingY-offset ... Vertical beam positionX-offset ... Time shift or horizontal positionThis can be done by modification of start address or by just X-offsetting the curveLevelCreate function which will emulate Level functionality. So search buffer from start address and stop if amplitude cross Level. You can have more modes but these are basics you should implement:amplitude: ( < lvl ) -> ( > lvl )amplitude: ( > lvl ) -> ( < lvl )There are many other possibilities for level like glitch,relative edge,...PreviewYou can put all this together for example like this: you have start address variable so sample data to some buffer continuously and on timer call level with start address (and update it). Then call draw with new start address and add timebase period to start address (of course in term of your samples)multichannelI use Line IN so I have stereo input (A,B = left,right) therefore I can add some other stuff like:Level source (A,B,none)render mode (timebase,Chebyshev (Lissajous curve if closed))Chebyshev = x axis is A, y axis is B this creates famous Chebyshev images which are good for dependent sinusoidal signals. Usually forming circles,ellipses,distorted loops ...miscel stuffYou can add filters for channels emulating capacitance or grounding of input and much moreGUIYou need many settings I prefer analog knobs instead of buttons/scrollbars/sliders just like on real Oscilloscope(semi)Analog values: Amplitude,TimeBase,Level,X-offset,Y-offsetdiscrete values: level mode(/,),level source(A,B,-),each channel (direct on,ground,off,capacity on)Here are some screenshots of my oscilloscope:Here is screenshot of my generator:And finally after adding some FFT also Spectrum AnalyserPS.I started with DirectSound but it sucks a lot because of buggy/non-functional buffer callbacksI use WinAPI WaveIn/Out for all sound in my Apps now. After few quirks with it, is the best for my needs and has the best latency (Directsound is too slow more than 10 times) but for oscilloscope it has no merit (I need low latency mostly for emulators)Btw. I have these three apps as linkable C++ subwindow classes (Borland)and last used with my ATMega168 emulator for my sensor-less BLDC driver debugginghere you can try my Oscilloscope,generator and Spectrum analyser If you are confused with download read the comments below this post btw password is: "oscill"Hope it helps if you need help with anything just comment me[Edit1] triggerYou trigger all channels at once but the trigger condition is checked usually just from one Now the implementation is simple for example let the trigger condition be the A(left) channel rise above level so:first make continuous playback with no trigger you wrote it is like this:for ( int i = 0, j = 0; i < countSamples ; ++j) { YVectorRight[j]=Samples[i++]; YVectorLeft[j] =Samples[i++]; }// here draw or FFT,draw buffers YVectorRight,YVectorLeftAdd triggerTo add trigger condition you just find sample that meets it and start drawing from it so you change it to something like this// static or global variablesstatic int i0=0; // actual start for drawingstatic bool _copy_data=true; // flag that new samples need to be copiedstatic 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 positionthe view_samples is the viewed/processed size of data (for one or more screens) it should be few times less then the (countSamples>>1)this code can loose one screen on the border area to avoid that you need to implement cyclic buffers bot for starters is even this OKjust encode all trigger conditions through some if's or switch statement 这篇关于绘制实时数据on(qwt)Oscillocope的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-28 02:29