0

我正在编写一个简单的 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 代码......但在这个阶段,我正在尝试弄清楚这个线程循环是否准确,或者是否有更好的方法来做到这一点。

4

1 回答 1

0

使用 clock_gettime 时也应该考虑秒数,可能会timing.start_time_s.tv_nsec大于timing.finish_time_s.tv_nsec. tv_nsec增加时从零开始tv_sec

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)
于 2013-06-14T09:36:00.343 回答