Поделиться через


События Time-Stamped

Большая картина времени синтезатора заключается в том, что вместо отправки заметки именно тогда, когда она должна воспроизводиться, каждая заметка имеет метку времени и помещается в буфер. Затем этот буфер обрабатывается и воспроизводится в течение двух миллисекунд времени, указанного меткой времени. (Хотя разрешение времени составляет сотни наносекунд, мы будем говорить в миллисекундах, которые являются более удобными единицами времени для этого обсуждения.)

Так как задержка известна системе по часам задержки, события с меткой времени могут ждать в буфере, чтобы воспроизвести в нужное время, а не просто сбрасывать события в очередь и надеяться, что задержка будет низкой.

Master часы реализуют интерфейс COM IReferenceClock (описан в документации по Microsoft Windows SDK). Все устройства в системе используют это эталонное время.

Реализация приемника волн Майкрософт создает поток, который просыпается каждые 20 миллисекунда. Задача потока — создать другой буфер и передать его в DirectSound. Чтобы создать этот буфер, он вызывает синтезатор и запрашивает отрисовку указанного объема музыкальных данных. Запрашиваемая сумма определяется фактическим временем пробуждения потока, которое вряд ли будет составлять ровно 20 миллисекундах.

Фактически в синтезатор передается просто указатель на расположение в памяти, с которого начинается запись данных в буфер PCM, и параметр длины, указывающий объем записываемых данных. Затем синтезатор может записать данные PCM в этот буфер и заполнить их до указанного объема. То есть он отрисовывается с начального адреса до достижения указанной длины. Этот блок памяти может быть DirectSoundBuffer (это вариант по умолчанию), но это также может быть граф DirectShow или какой-либо другой целевой объект, определенный приемником волны.

Буфер PCM является концептуально циклическим (то есть постоянно циклически). Синтезатор отрисовывает 16-разрядные числа, описывающие звук, в последовательные срезы буфера. Размер среза немного отличается при каждом пробуждении потока, так как приемник не может просыпаться ровно каждые 20 миллисекунда. Таким образом, каждый раз, когда поток просыпается, он играет догоняет, чтобы определить, как далеко он должен пройти через буфер, прежде чем вернуться в спящий режим.

С точки зрения приложения драйвер synth-порта сам имеет функцию IDirectMusicSynth::GetLatencyClock , которая получает часы из приемника волны. Итак, есть два часа:

  • Master часы, которые все, включая приемник волны, слушают.

  • Часы задержки, реализованные приемником волн, которые рассматриваются приложением как порт DirectMusic, предоставляющий часы задержки.

Другими словами, приложение запрашивает часы задержки, но видит часы как исходящие из абстракции портов DirectMusic, а не из приемника волны.

Время, возвращаемое данными часами задержки, — это самое раннее время, в которое буфер может быть отрисован, так как синтезатор уже отрисовывается до этой точки в буфере. Если синтезатор отрисовал меньший буфер при последней записи, задержка также была бы меньше.

Поэтому приемник волны вызывает метод IDirectMusicSynth::Render в синтезаторе, представляя буфер и запрашивая его заполнение отрисованными данными. Как показано на следующем рисунке, синтезатор принимает все события с метками времени, которые поступают в результате вызовов функции IDirectMusicSynth::P layBuffer .

Схема, иллюстрирующая процесс постановки в очередь сообщений с меткой времени в синтезаторе.

Каждый входной буфер содержит сообщения с метками времени. Каждое из этих сообщений помещается в очередь для отрисовки в буфер во время, указанное меткой времени.

Одна из важных особенностей этой модели заключается в том, что нет определенного порядка, кроме метки времени. Эти события передаются в потоке, поэтому их можно добавить в очередь в любое время перед отрисовкой. Все зависит от времени на событиях. Например, если время отсчета в настоящее время составляет 400 единиц времени, то все отметки времени происходит в момент 400. События с меткой времени, которые будут происходить 10 единиц, будут происходить в момент 410.