Relojes de latencia
El modelo de controlador de minipuerto del sintetizador está diseñado para permitir la sincronización de la salida de audio entre varios dispositivos. Por lo tanto, contiene un modelo de control de tiempo más complejo que el proporcionado por un dispositivo UART puro.
Los eventos se entregan a (y capturan desde) el controlador de minipuerto con una marca de tiempo asociada. Esta marca de tiempo es relativa a un reloj maestro. El reloj maestro es el mismo reloj utilizado por toda la secuenciación en todo el sistema. El tiempo del reloj maestro se mide en unidades de tics de 100 nanosegundos.
El controlador de minipuerto obtiene la hora actual del reloj maestro llamando a IMasterClock::GetTime. En el momento de la creación de patillas, el controlador de puerto pasa la interfaz IMasterClock del modo kernel al controlador de miniporte como uno de los parámetros de entrada al método IMiniportDMus::NewStream . Actualmente, el reloj maestro ajusta el reloj en tiempo real del sistema. El reloj maestro nunca cambia cuando hay patillas que requieren que esté en estado de ejecución . Es un reloj de velocidad constante que nunca se pausa.
Todos los dispositivos de representación tienen cierta latencia entre el momento en que aceptan un evento y el momento en que se puede escuchar el evento. Esta latencia puede ser constante o variable (como en el caso de un sintetizador de software, donde la latencia depende de la posición de reproducción actual del búfer de audio). Esta latencia se compensa por:
Permitir que el controlador de miniporte DMus reciba eventos lo suficientemente de antemano para que se puedan reproducir a tiempo, a pesar de la latencia del dispositivo. Los eventos se secuencian para el controlador de minipuerto mediante un motor de secuenciador en el controlador de puerto DMus.
En el momento de la creación de patillas, el controlador de puerto consulta el controlador de minipuerto durante un tiempo delta en unidades de 100 nanosegundos. Esta hora diferencial es el tiempo de presentación de cada evento que el controlador de miniporte quiere recibir el evento. El controlador de puerto hace su mejor esfuerzo para entregar eventos de antemano. Si se especifica un valor muy grande para este delta (especificado por el parámetro SchedulePreFetch de IMiniportDMus::NewStream), el controlador de puerto pasa los eventos al controlador de miniporte en cuanto se entregan al controlador de puerto desde el modo de usuario.
Informar a las aplicaciones de qué tan lejos se programan los eventos. El uso de la latencia máxima no es deseable en este caso. Dado que los eventos no se pueden cancelar una vez enviados, cuanto más cerca se puedan enviar los eventos a su tiempo de presentación, la aplicación y la síntesis pueden interactuar con mayor capacidad de respuesta. Para controlar este requisito, DirectMusic ha introducido el concepto de un reloj de latencia.
El reloj de latencia proporciona la hora más cercana en el futuro que se puede programar un evento para jugar y seguir jugando a tiempo. En otras palabras, si la aplicación programa un evento que se va a reproducir antes de la hora actual según el reloj de latencia, el evento se reproduce tarde. Los controladores de minipuerto del sintetizador proporcionan un reloj de latencia respondiendo al elemento de propiedad KSPROPERTY_SYNTH_LATENCYCLOCK .
El controlador de minipuerto se consulta para KSPROPSETID_Synth y KSPROPERTY_SYNTH_LATENCYCLOCK. El controlador de propiedades del controlador de miniport debe devolver un reloj de latencia que especifique, en términos del reloj maestro, la próxima vez que se puedan representar los datos a tiempo. Por ejemplo, si el reloj maestro lee actualmente 50 y actualmente hay 25 unidades de latencia, el reloj de latencia lee 75. La razón por la que el reloj se implementa de esta manera es que la latencia no necesita ser constante, y el valor devuelto es de más uso para las aplicaciones que solo el delta.