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