Я пишу простое приложение NDK OpenSL ES, которое записывает, что пользователи касаются виртуальной клавиатуры пианино, а затем воспроизводят их навсегда в заданном цикле. После долгих экспериментов и чтения я решил использовать отдельный цикл POSIX для достижения этого. Как вы можете видеть в коде вычитает любое время обработки, взятое из времени сна, чтобы сделать интервал каждого цикла, как близко к желаемому интервалу сна, насколько это возможно (в данном случае это 5000000 наносекунд.Точная синхронизация потоков POSIX с использованием NDK
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, если это необходимо ... но на этом этапе я пытаюсь выяснить, является ли этот цикл потока точным или если есть лучший способ сделать это.
одна мысль: держать аудио буфер полон во все времена. Заполните молчание, «играя» соответствующее количество образцов молчания. Таким образом, все синхронизируется через звуковые часы, и переменные задержки не будут влиять на вас (пока вы не будете заполнять буферы). – fadden
Спасибо за ваш ответ, это кажется лучшим способом. Вопрос с учетом времени на основе буфера: для полифонии мне нужно будет загружать до 16 очередей буферов одновременно. Если я буду держать их в полном объеме - вы думаете, что они останутся в синхронизации? Я все равно дам ему тест, но подумал, что попрошу, если у вас есть опыт. –
[This] (http://stackoverflow.com/questions/4485072/accurate-timing-in-ios?lq=1) поток затрагивает аналогичную проблему, но с iOS, если кому-то это интересно. –