Android - 安排每10毫秒发生一次事件?

时间:2012-04-25 20:23:19

标签: android performance audio timer timedelay

我正在努力创建一个允许通过高频声波进行极低带宽通信的应用。我已经达到了可以创建频率并进行傅里叶变换的程度(借助Moonblink的Audalyzer开源代码)。

但是这是我的问题:我无法让代码以正确的时序运行。假设我想要每10ms执行一段代码,我将如何进行此操作?

我尝试过使用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();

3 个答案:

答案 0 :(得分:2)

我建议采用一种截然不同的方法:不要试图实时运行 代码。

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

然后,您的代码与此异步运行,并通过音频缓冲区解耦。您的代码的时间感不是由执行时的系统时钟决定的,而是由您使用的音频数据的定义的采样间间隔决定的。 (即,如果你使用48 Ksps,那么10 mS之后是480个样本)

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

答案 1 :(得分:1)

您的线程/循环策略可能与您将获得的大致相同。但是,10ms并不是很多时间,大多数Android设备都不是超级强大,而傅立叶变换则需要做很多工作。我发现你不可能在10ms内完成那么多工作。我怀疑你将不得不增加那段时间。

答案 2 :(得分: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一起生活(只是一个想法,这可能没有任何好处)