Каково время задержки (или задержки) для обратных вызовов из метода waveOutWrite API?
У меня есть спор с некоторыми разработчиками на другом форуме о точной генерации событий MIDI (примечание о сообщениях и т. Д.). Человеческое ухо довольно чувствительно к небольшим временным неточностям, и я думаю, что их основная проблема заключается в использовании таймеров с относительно низким разрешением, которые квантовывают свои события с интервалами в 15 миллисекунд (что достаточно велико, чтобы вызвать ощутимые неточности).
Около 10 лет назад я написал пример приложения (Visual Basic 5 для Windows 95), в котором использовался программный синтезатор и проигрыватель MIDI. Основным условием была система воспроизведения с подпрыгивающим буфером, где каждый буфер представлял собой длительность шестнадцатой ноты (пример: при 120 четвертных нотах в минуту каждая четвертная нота составляла 500 мс, и, следовательно, каждая шестнадцатая нота составляла 125 мс, поэтому каждая буфер 5513 образцов). Каждый буфер воспроизводился с помощью метода waveOutWrite, а функция обратного вызова из этого метода использовалась для постановки в очередь следующего буфера, а также для отправки MIDI-сообщений. Это обеспечивало синхронизацию звука на основе WAV и звука MIDI.
На мой взгляд, этот метод работал отлично - ноты MIDI не звучали даже немного не в ногу (тогда как если вы используете обычный таймер с точностью до 15 мс для воспроизведения ноты MIDI, они будут звучать заметно не в ногу).
Теоретически, этот метод будет производить синхронизацию MIDI с точностью до сэмпла, или 0,0227 миллисекунд (так как на миллисекунду приходится 44,1 сэмпла). Я сомневаюсь, что это истинная задержка этого подхода, поскольку, вероятно, существует небольшая задержка между завершением буфера и уведомлением обратного вызова waveOutWrite. Кто-нибудь знает, насколько велика эта задержка?
3 ответа
Планировщик Windows работает с интервалами 10 или 16 мс по умолчанию в зависимости от процессора. Если вы используете API timeBeginPeriod (), вы можете изменить этот интервал (при довольно значительной стоимости энергопотребления).
В Windows XP и Windows 7 волновые API работают с задержкой около 30 мс, для Windows Vista волновые API имеют задержку около 50 мс. Затем вам нужно добавить в аудио движок задержки.
К сожалению, у меня нет цифр для задержки двигателя в одном направлении, но у нас есть некоторые цифры, касающиеся задержки двигателя - мы запустили тест, который воспроизводил тональный сигнал, возвращенный через аудиоустройство USB, и измерили задержку приема-передачи (захватить). На Vista задержка прохождения туда и обратно составляла около 80 мс с вариацией около 10 мс. На Win7 задержка в оба конца составляла около 40 мс с вариацией около 5 мс. Однако, YMMV, поскольку величина задержки, вносимая аудиооборудованием, различна для каждого компонента оборудования.
Я абсолютно не знаю, какова была задержка для звукового движка XP или звукового стека Win9x.
Чтобы добавить к отличным ответам выше.
Ваш вопрос о латентности Windows ни пообещал, ни позаботился. И, как таковая, она может сильно отличаться в зависимости от версии ОС, аппаратного обеспечения и других факторов. WaveOut API и DirectSound тоже (не уверен насчет WASAPI, но я полагаю, что это верно и для этого последнего Vista+ аудио API) - все они настроены для буферизованного вывода звука. Определенная точность обратного вызова не требуется, если вы вовремя ставите в очередь следующий буфер, пока текущий еще воспроизводится.
Когда вы начинаете воспроизведение аудио, у вас есть несколько допущений, таких как отсутствие потерь во время воспроизведения, и все выходные данные являются непрерывными, а тактовая частота звука точно соответствует ожидаемой, например, 44100 Гц. Затем вы делаете простую математику, чтобы запланировать выход волны во времени, преобразовав время в сэмплы, а затем в байты.
К сожалению, эффективная скорость воспроизведения не является точной, например, представьте, что реальная аппаратная частота дискретизации может составлять 44100 Гц -3%, и в долгосрочной перспективе математика времени до байта может вас подвести. Была предпринята попытка компенсировать этот эффект, например, сделать аудиоаппаратуру тактовой частотой воспроизведения и синхронизировать видео с ней (так работают плееры), а также использовать метод согласования скорости для согласования скорости входящих данных с фактической скоростью воспроизведения на аппаратном уровне. И то, и другое делает измерения абсолютного времени и задержки весьма спекулятивным знанием.
Более того, задержки API 20 мс, 30 мс, 50 мс и так далее. С давних пор waveOut API - это слой поверх других API. Это означает, что некоторая обработка выполняется до того, как данные действительно достигают аппаратного обеспечения, и эта обработка требует, чтобы вы заблаговременно убрали руки с очередей, иначе данные не достигнут аппаратного обеспечения. Допустим, если вы попытаетесь поставить свои данные в буферы по 10 мс непосредственно перед временем воспроизведения, API примет эти данные, но сам опоздает с передачей этих данных в нисходящем направлении, и на динамиках будет тихий или комфортный шум.
Теперь это также связано с обратными вызовами, которые вы получаете. Можно сказать, что вас не волнует задержка буферов, и для вас важно точное время обратного вызова. Однако, поскольку API является многоуровневым, вы получаете обратный вызов с точностью синхронизации внутреннего уровня, такой второй внутренний уровень уведомляет о свободном буфере, а первый внутренний уровень обновляет свои записи и проверяет, может ли он также освободить ваш буфер (эй, эти буферы не не должно совпадать). Это делает ожидания точности обратного вызова действительно слабыми и ненадежными.
При условии, что я не касался API waveOut в течение достаточно долгого времени, если бы возник такой вопрос о точности синхронизации, я бы, вероятно, прежде всего подумал о двух вещах:
Windows обеспечивает доступ к звуковым аппаратным часам (я знаю об интерфейсе IReferenceClock, доступном через DirectShow, и, вероятно, это происходит от другой вещи более низкого уровня, которая также доступна), и, имея такую возможность, я попытался бы синхронизироваться с ней
Новейший аудио API от Microsoft, WASAPI, предоставляет специальную поддержку для аудио с малой задержкой, благодаря новым интересным вещам, таким как улучшенное планирование потоков мультимедиа, потоки в эксклюзивном режиме и задержка <10 мс для PCM - вот где нужно искать лучшую синхронизацию
На самом базовом уровне Windows - многопоточная ОС. И это планирует потоки с отрезками времени 100 мс. Это означает, что при отсутствии конфликта ЦП задержка между концом буфера и обратным вызовом waveOutWrite может быть сколь угодно короткой. Или, если есть другие занятые потоки, вы должны ждать до 100 мс на поток. В лучшем случае, однако... Процессор теперь работает на частоте ГГц. Это ставит абсолютную нижнюю границу того, как быстро может быть вызван обратный вызов с точностью до 0,000,000,000,1 второго порядка.
Если вы не можете определить максимальное количество обратных вызовов waveOutWrite, которое вы можете обработать за одну секунду, что может означать задержку каждого вызова, я думаю, что на самом деле задержка будет на порядок ниже предустановки большую часть времени, если только Есть слишком много занятых потоков, и в этом случае все будет идти ужасно, ужасно неправильно.