Partager via


événements Time-Stamped

La vue d’ensemble du minutage du synthétiseur est qu’au lieu d’envoyer une note exactement quand elle doit être lue, chaque note est horodatée et placée dans une mémoire tampon. Cette mémoire tampon est ensuite traitée et lue dans les deux millisecondes de la durée spécifiée par l’horodatage. (Bien que la résolution temporelle soit en centaines de nanosecondes, nous allons parler en termes de millisecondes, qui sont des unités de temps plus pratiques pour cette discussion.)

Étant donné que la latence est connue du système par le biais de l’horloge de latence, les événements horodatés peuvent attendre dans une mémoire tampon de lire à leur heure appropriée, au lieu de simplement déposer les événements dans une file d’attente et d’espérer que la latence est faible.

Une horloge master implémente une interface COM IReferenceClock (décrite dans la documentation Microsoft Windows SDK). Tous les appareils sur le système utilisent cette heure de référence.

L’implémentation du récepteur d’ondes de Microsoft génère un thread qui se réveille toutes les 20 millisecondes. Le travail du thread consiste à créer une autre mémoire tampon et à la remettre à DirectSound. Pour créer cette mémoire tampon, il appelle le synthétiseur et lui demande de restituer une quantité spécifiée de données musicales. La quantité qu’il demande est déterminée par l’heure réelle à laquelle le thread se réveille, qui est peu susceptible d’être exactement 20 millisecondes.

Ce qui est en fait passé dans le synthétiseur est simplement un pointeur vers l’emplacement en mémoire à partir duquel commencer à écrire des données dans la mémoire tampon PCM, et un paramètre de longueur qui spécifie la quantité de données à écrire. Le synthé peut ensuite écrire des données PCM dans cette mémoire tampon et les remplir jusqu’à la quantité spécifiée. Autrement dit, il s’affiche à partir de l’adresse de début jusqu’à ce qu’il atteigne la longueur spécifiée. Ce bloc de mémoire peut être un DirectSoundBuffer (ce qui est le cas par défaut), mais il peut également s’agir d’un graphique DirectShow ou d’une autre cible définie par le récepteur d’ondes.

La mémoire tampon PCM est conceptuellement cyclique (c’est-à-dire qu’elle est en boucle constante). Le synthétiseur restitue les nombres 16 bits qui décrivent le son en tranches successives de la mémoire tampon. La taille de la tranche est légèrement différente chaque fois que le thread se réveille, car le récepteur ne peut pas se réveiller exactement toutes les 20 millisecondes. Ainsi, chaque fois que le thread se réveille, il joue de rattrapage pour déterminer dans quelle mesure il doit progresser dans la mémoire tampon avant de revenir en veille.

Du point de vue de l’application, le pilote de port de synthèse lui-même a une fonction IDirectMusicSynth ::GetLatencyClock qui obtient l’horloge du récepteur d’ondes. Il y a donc deux horloges :

  • Le master horloge que tout le monde, y compris le récepteur de vague, écoute.

  • Horloge de latence implémentée par le récepteur d’ondes, qui est considérée par l’application comme un port DirectMusic fournissant l’horloge de latence.

En d’autres termes, l’application demande l’horloge de latence, mais considère que l’horloge provient de l’abstraction de port DirectMusic plutôt que du récepteur d’ondes.

L’heure retournée par cette horloge de latence est l’heure la plus ancienne à laquelle la mémoire tampon peut être rendue, car le synthé a déjà rendu jusqu’à ce point dans la mémoire tampon. Si le synthé avait rendu une mémoire tampon plus petite lors de sa dernière écriture, la latence serait également inférieure.

Par conséquent, le récepteur d’ondes appelle IDirectMusicSynth ::Render sur le synthé, en présentant la mémoire tampon et en demandant qu’elle soit remplie avec les données rendues. Comme le montre l’illustration suivante, le synthé prend tous les événements horodatés qui apparaissent à la suite des appels de fonction IDirectMusicSynth ::P layBuffer .

Diagramme illustrant le processus de mise en file d’attente de messages horodatés dans un synthétiseur.

Chaque mémoire tampon d’entrée contient des messages horodatés. Chacun de ces messages est placé dans une file d’attente pour être restitué dans une mémoire tampon à l’heure spécifiée par son horodatage.

L’une des choses importantes de ce modèle est qu’il n’y a pas d’ordre particulier autre que l’horodatage. Ces événements sont diffusés en continu, de sorte qu’ils peuvent être ajoutés à la file d’attente à tout moment avant le rendu. Tout est basé sur les événements par rapport au temps. Par exemple, si l’heure de référence est actuellement à 400 unités de temps, tout ce qui est horodaté pour se produire à l’heure 400 se produit maintenant. Les événements horodatés pour se produire 10 unités à partir de maintenant se produisent à l’heure 410.