【问题标题】:Accurate POSIX thread timing using NDK使用 NDK 进行准确的 POSIX 线程计时
【发布时间】:2013-06-10 13:15:34
【问题描述】:

我正在编写一个简单的 NDK OpenSL ES 音频应用程序,该应用程序记录用户在虚拟钢琴键盘上的触摸,然后在设定的循环中永久播放它们。经过大量的实验和阅读,我决定使用单独的 POSIX 循环来实现这一点。正如您在代码中看到的,它从睡眠时间中减去任何处理时间,以使每个循环的间隔尽可能接近所需的睡眠间隔(在本例中为 5000000 纳秒。

void init_timing_loop() {
    pthread_t fade_in;
    pthread_create(&fade_in, NULL, timing_loop, (void*)NULL);
}

void* timing_loop(void* args) {

    while (1) {

        clock_gettime(CLOCK_MONOTONIC, &timing.start_time_s);

        tic_counter(); // simple logic gates that cycle the current tic
        play_all_parts(); // for-loops through all parts and plays any notes (From an OpenSL buffer) that fall on the current tic

        clock_gettime(CLOCK_MONOTONIC, &timing.finish_time_s);

        timing.diff_time_s.tv_nsec = (5000000 - (timing.finish_time_s.tv_nsec - timing.start_time_s.tv_nsec));

        nanosleep(&timing.diff_time_s, NULL);
    }

    return NULL;
}

问题是即使使用它,结果也会更好,但相当不一致。有时音符会一次延迟甚至 50 毫秒,这会导致播放非常不稳定。

有没有更好的方法来解决这个问题?为了调试,我运行了以下代码:

gettimeofday(&timing.curr_time, &timing.tzp);
__android_log_print(ANDROID_LOG_DEBUG, "timing_loop", "gettimeofday: %d %d",
    timing.curr_time.tv_sec, timing.curr_time.tv_usec);

这给出了相当一致的读数 - 这并不反映播放不准确。 Android 是否还有其他因素在阻止准确计时?还是 OpenSL ES 是一个潜在的问题?所有缓冲区数据都加载到内存中 - 那里可能存在瓶颈吗?

如果需要,很高兴发布更多 OpenSL 代码......但在这个阶段,我正在尝试确定这个线程循环是否准确,或者是否有更好的方法。

【问题讨论】:

  • 一个想法:始终保持音频缓冲区满。通过“播放”适当数量的静音样本来填充静音。这样,一切都通过音频时钟计时,可变延迟不会影响您(只要您保持缓冲区满)。
  • 感谢您的回复,这似乎是一个更好的方法。具有基于缓冲区的计时的问题是:对于复音,我需要一次加载多达 16 个缓冲区队列。如果我一直让它们充满 - 你认为它们会保持同步吗?无论如何我都会给它一个测试,但我想我会问你是否有这样做的经验。

标签: android c android-ndk opensl


【解决方案1】:

在使用clock_gettime 时也应该考虑秒数,timing.start_time_s.tv_nsec 可能比timing.finish_time_s.tv_nsec 更大。当tv_sec 增加时,tv_nsec 从零开始。

timing.diff_time_s.tv_nsec =
(5000000 - (timing.finish_time_s.tv_nsec - timing.start_time_s.tv_nsec));

试试类似的东西

#define NS_IN_SEC 1000000000
(timing.finish_time_s.tv_sec * NS_IN_SEC + timing.finish_time_s.tv_nsec) -
(timing.start_time_s.tv_nsec * NS_IN_SEC + timing.start_time_s.tv_nsec)

【讨论】:

  • 谢谢你,我会更新我的代码。我决定使用基于缓冲区的时间来播放声音,但仍会使用粗略的线程进行音量/平移等。
猜你喜欢
  • 1970-01-01
  • 2017-07-20
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多