精确的信号发生器

时间:2013-07-16 10:12:43

标签: c++ qt signal-processing

我想在Qt中创建一个准确的信号发生器。

例如,10us(微秒)生成255和10ms(毫秒)的方波信号生成0.

我在我的线程中使用了usleep()但它睡了大约1ms !!当搜索它时,我发现它用于CPU上下文切换。

//fp:frequency of signal //t:time of generate high (amp) // n:generate n time

void Thread::rectGenerator(double fp, double t, double amp, double n)
{
    double result;
    double T=1000000/fp; //(us)
    for (double i=0,ii=0; i<n*T; i+=_Interval,ii+=_Interval)
    {
        if (ii>=T)
            ii=0;
        if (ii<=t)
            result=amp;
        else
            result=0;
        th.usleep(1);
        qDebug() << i << "\t" <<result;
    }
}

结果:rectGenerator(200,20,255,12)在12秒内执行但它应该在60(ms)内执行!

  

那么产生准确信号的最佳方法是什么?

4 个答案:

答案 0 :(得分:2)

通常你要做的是分配一个表示一定量实时的缓冲区,用你生成的信号填充这个缓冲区,然后安排它播放,保存或流式传输。 (你没有指定你正在对信号做什么,但既然你是用线程做的,我会假设它几乎是实时的。)

假设您的目标采样率为48kHz(专业音频的标准)。然后你将分配48000个浮点样本的缓冲区来存储1秒的音频。 (使用double几乎肯定是矫枉过正;高质量的音频是16位或24位,如果你掌握顶级系统,那么32位,所以浮点数足够精确;双倍浪费位)。 / p>

然后,您将使用与您上面粘贴的循环函数非常类似的循环函数用信号填充此缓冲区。但你不要使用睡眠或类似的东西;现在,你只准备稍后播放的数据。

因此,一旦准备好音频缓冲区,您需要安排它进行播放。这通常涉及您将缓冲区发送到系统以在特定时间播放。根据API或设备,当达到低水位标记时,您将获得回调以填充缓冲区等。

如果你的信号永远不会改变,你可以只生成一个缓冲区,并通过重新安排它来重复使用它。根据信号的周期,您可能需要调整缓冲区大小以保持正确的频率。

(请注意,您所描述的纯方波需要理论上无限带宽来重现,其砖墙边缘;您应该应用低通滤波器来限制信号,这取决于您的输出设备。)< / p>

答案 1 :(得分:0)

对于10 uS范围内的精度,我最好将信号生成卸载到专用硬件(具有实时或无操作系统的FPGA或微控制器)。

答案 2 :(得分:0)

由于您需要100 Khz信号,因此到目前为止最简单的解决方案是使用旨在创建该范围内信号的设备。一个很好的声卡will achieve this,很容易编程。只需加载样品并告诉它即可播放。它的内部硬件将完成所有时间。

答案 3 :(得分:-1)

您始终可以执行繁忙的循环并调整每个样本所需迭代量的估计值。

 // first align your start time of the signal to the edge of your timer
 //   - it can have even a resolution of a second or more
 int max_counter = 0;
 int start = get_time();
 while (((next=get_time()) - start) == 0);
 // measure the number of i++ operations between each timer interval 
 while (((start=get_time()) - next) == 0) max_counter++;
 int ticks_per_5useconds = max_counter * 5 / timer_interval_in_microseconds;
 while (((next=get_time()) - start) < one_hour) {
      if (counter++ >= ticks_per_5useconds) {
          counter=0; output(value); value^=255;
      }
      // check if timer has changed
      // and update the estimate of ticks_per_5useconds accordingly
 }