3

我正在创建一个允许通过高频声波进行非常低带宽通信的应用程序。我已经到了可以创建频率并进行傅立叶变换的地步(借助 Moonblink 的 Audalyzer 开源代码

但这是我的问题:我无法让代码以正确的时间运行。假设我希望每 10 毫秒执行一段代码,我该怎么做呢?

我尝试过使用 TimerTask,但在代码实际执行之前有一个巨大的延迟,比如长达 100 毫秒。

我也尝试了这种方法,只需 ping 当前时间并仅在该时间过去时执行。但是仍然存在延迟问题。你们有什么想法吗?

Thread analysis = new Thread(new Runnable()
{
    @Override
    public void run()
    {
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);

        long executeTime = System.currentTimeMillis();

        manualAnalyzer.measureStart();
        while (FFTransforming) 
        {          
            if(System.currentTimeMillis() >= executeTime)
            {
                //Reset the timer to execute again in 10ms
                executeTime+=10;

                //Perform Fourier Transform
                manualAnalyzer.doUpdate(0);

                //TODO: Analyze the results of the transform here...

            }
        }
        manualAnalyzer.measureStop();
    }
});
analysis.start();
4

3 回答 3

2

我会推荐一种非常不同的方法:不要尝试实时运行您的代码。

相反,仅依靠实时运行的低级音频代码,通过在一段时间内连续录制(或播放)包含感兴趣的事件。

然后,您的代码与此有些异步运行,与音频缓冲区分离。您的代码的时间感不是由执行时的系统时钟决定的,而是由您使用的音频数据的定义的采样间间隔决定的。(即,如果您使用 48 Ksps,则 10 毫秒后是 480 个样本)

您可能需要修改控制设备之间交互的协议,以扩大预计发生传输的时间窗口。即,您可以对“数据包”中的实际调制和符号进行精确计时,但您不应期望在确定何时发送或接收数据包时具有几乎相同的精度顺序 - 您必须“找到”它在包含噪音的较长录音中。

于 2012-04-27T19:31:56.010 回答
1

您的线程/循环策略可能大致与您将要获得的一样接近。但是,10ms 并不是很多时间,大多数 Android 设备都不是超级强大的,而且傅里叶变换需要做很多工作。我发现你不太可能在 10 毫秒内完成这么多的工作。我怀疑你将不得不增加这个时间。

于 2012-04-25T20:37:11.977 回答
1

我更改了您的代码,以便将 doUpdate 的执行时间考虑在内。System.nanoTime() 的使用也应该提高准确性。

    public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);

long executeTime=0;        
long nextTime = System.nanoTime();

manualAnalyzer.measureStart();
while (FFTransforming) 
{          
    if(System.nanoTime() >= nextTime)
    {
        executeTime = System.nanoTime();
        //Perform Fourier Transform
        manualAnalyzer.doUpdate(0);
        //TODO: Analyze the results of the transform here...
        executeTime = System.nanoTime() - executeTime;
        //guard against the case that doUpdate took longer than 10ms
        final long i = executeTime/10000000;
        //set the timer to execute again at the next full 10ms intervall
        nextTime+= 10000000+ i*10000000 
    }
}
manualAnalyzer.measureStop();
    }

你还能做什么?

  • 消除垃圾收集
  • 使用 NDK 原生化(只是一个想法,这也可能没有任何好处)
于 2012-04-27T19:25:21.103 回答