# &arts; en détail

## Architecture

structure de &arts;.

## Modules et ports

L'idée de &arts; est de réaliser la synthèse à l'aide de petits modules, qui ne font chacun qu'une tache, puis de les combiner en structures complexes. Les petits modules ont la plupart du temps des entrées, où ils acceptent des signaux ou des paramètres, et des sorties, où ils dirigent les signaux qu'ils produisent.

Par exemple, le module Synth&lowbar;ADD récupère simplement deux signaux à ses entrées, et les additionne. Le résultat forme le signal de sortie. Les emplacements où se situent les entrées et les sorties sont appelés ports.

## Structures

Une structure est une combinaison de modules connectés, certains d'entre eux peuvent avoir des paramètres codés directement sur leurs ports d'entrée, d'autres peuvent être connectés, et d'autres pas connectés du tout.

Ce que vous pouvez faire avec &artsbuilder; est de définir les structures. Vous choisissez quel module vous voulez connecter, avec quels autres. Lorsque vous avez terminé, vous pouvez enregistrer cette définition de structure dans un fichier, ou dire à &arts; de créer la structure que vous avez défini (Execute).

Vous entendrez probablement un son, si vous avez tout fait comme il le fallait.

## Temps de latence

### Qu'est-ce que le temps de latence ?

Supposons que vous avez une application appelée mousepling qui doit produire un pling si vous cliquez sur un bouton. Le temps de latence est la durée entre le moment ou votre doigt clique sur le bouton de la souris et le moment où vous entendez le son. Le temps de latence est dans ce cas composé d'autres temps de latence, qui ont des origines différentes.

### Temps de latence dans les applications simples

Dans cette simple application, un temps de latence est dû :

- au temps que met le noyau à notifier au serveur X11 qu'un bouton de la souris a été enfoncé

- au temps que met le serveur X11 à notifier à votre application qu'un bouton de la souris a été enfoncé

- au temps que met l'application mousepling à se rendre compte que ce bouton doit jouer un pling

- au temps que met l'application mousepling à dire au serveur sonore qu'il doit jouer un pling

- au temps que met le pling à passer par le tampon (après avoir été mélangé avec les autres sorties par le serveur sonore), et à être interprété par la carte son

- au temps que met le son de pling pour parcourir le chemin qui sépare les haut-parleurs de vos oreilles

Les trois premiers items sont indépendants de &arts;. Ils sont intéressants, mais n'entrent pas dans le cadre de ce document. Toutefois, sachez qu'ils existent, et même si vous avez optimisé tous les paramètres, vous n'obtiendez pas forcément le résultat escompté.

Ceci signifie que nous pouvons approximer cette durée à 1/9000 secondes, ce qui est inférieur à 0.15 ms. Nous verrons que ce n'est pas significatif.

Ensuite vient la durée entre le moment ou le serveur commence à jouer et la moment ou la carte son reçoit quelque chose. Le serveur doit utiliser un tampon, de telle sorte que lorsque d'autres applications fonctionnent, comme par exemple votre serveur X11 ou l'application mousepling, il n'y ait pas d'interruptions du son. Sous &Linux;, les choses se passent de la façon suivante :il y a un certains nombre de fragments de taille donnée. Le serveur remplit les fragments et la carte son les joue.

Supposons qu'il y ait trois fragments. Le serveur remplit le premier, la carte son commence à le jouer. Le serveur remplit le second, puis le troisième. Le serveur a terminé, d'autres applications peuvent faire d'autres choses maintenant.

Lorsque la carte son a terminé de jouer le premier fragment, elle commence à jouer le second et le serveur commende à remplir le premier à nouveau, et ainsi de suite.

Le temps de latence maximal est donné par (nombre de fragments)*(taille de chaque fragment)/(taux d'échantillonnage * (taille de chaque échantillon)). Si nous travaillons à 44 kHz, en stéréo, et avec 7 fragments de 1024 octets (valeurs par défaut de aRts), nous obtenons 40 ms.

Cette valeur peut être modifiée suivant vos besoins. Cependant, l'utilisation du processeur augmente avec des temps de latence plus courts, puisque le serveur sonore doit remplir les tampons plus souvent, et placer moins de données. Il est aussi la plupart du temps impossible d'atteindre de meilleurs valeurs sans donner au serveur sonore la priorité temps-réel, sinon vous aurez souvent des interruptions du son.

Cependant, il est plutôt réaliste d'utiliser quelque chose comme trois fragments de 256 octets chacuns, ce qui donne une valeur de 4,4 ms. Avec un tel retard, l'utilisation du CPU par &arts; serait d'environ 7,5%. Avec un retard de 40 :ms, il serait de 3% (sur un PII-350, et cette valeur dépend de la carte son, de la version du noyau et d'autres choses encore).

Il y a ensuite le temps que met le son de pling à atteindre vos oreilles depuis les haut-parleurs. Supposons que vous voyez à une distance de deux mètres de vos haut-parleurs. La vitesse du son est d'environ 300 mètres par seconde. Nous pouvons approximer cette durée à 6 :ms.

### Temps de latence dans les applications de streaming

Les applications de streaming sont des applications qui produisent leur son elles-mêmes. Considérons un jeu, qui fournit un flux constant d'échantillons, et qui doit être adapté pour rejouer certaines choses avec &arts;. Pour donner un exemple, si j'appuie sur une touche, la figure avec laquelle je joue saute, et un son de boing est joué.

Tout d'abord, vous devez savoir que &arts; gère le streaming. C'est très similaire aux entrées/sorties de la carte son. Le jeu envoie des paquets d'échantillons vers le serveur sonore. Disons trois paquets. Dès que le serveur sonore a terminé avec le premier paquet, il envoie confirmation au jeu qu'il en a fini avec ce paquet.

Le jeu crée un autre paquet de son et l'envoie au serveur. Pendant ce temps, le serveur commence à traiter le deuxième paquet, et ainsi de suite. Le temps de latence est similaire au cas simple :

- la durée que met le serveur à notifier au serveur X11 qu'une touche a été appuyée

- la durée que met le serveur X11 pour notifier au jeu qu'une touche a été appuyée

- la durée que met le jeu à décider que cette touche doit déclencher un boing

- la durée que met le paquet sonore dans lequel le jeu a commencé à placer le son de boing à atteindre le serveur sonore

- la durée que met le boing (que le serveur sonore commence à mélanger avec les autres sorties) pour aller dans le tampon, jusqu'à ce qu'il atteigne réellement la position où il sera joué par la carte son.

- la durée que met le son de boing pour parcourir la distance qui vous sépare des haut-parleurs.

D'autres temps de latence, comme précédemments, sortent du cadre de cette documentation.

Évidemment, le temps de latence du streaming dépend du temps qu'il faut pour que tous les paquets qui sont utilisés pour le streaming soit joués une fois. Cette durée est donnée par (nombre de paquets)*(taille de chaque paquet)/(taux d'échantillonnage * (taille de chaque échantillon))

Comme vous pouvez le voir, la formule est la même que pour les fragments. Cependant, pour les jeux, ce n'est pas la peine d'avoir des retards aussi faibles que précédemment. Je dirais qu'une configuration réaliste pour les jeux serait 2048 octets par paquet, et 3 paquets utilisés. Le temps de latence est alors de 35 ms.

Ceci est basé sur la chose suivante : supposons que le jeu affiche 25 images par seconde (pour affichage). Il est probable que vous ne verrez pas la différence si le son est décalé d'une image. Ainsi, 1/25 ieme de seconde pour le streaming est acceptable, soit 40 ms.

La plupart des personnes n'exécuteront pas leur jeux avec la priorité temps-réel, et le risque d'interruptions du son ne peut pas être écarté. Du streaming avec 3 paquets de 256 octets est possible (j'ai testé) - mais entraîne une forte utilisation du CPU.

### Remarques sur l'utilisation du CPU

Il y a beaucoup de facteurs qui influent sur l'utilisation du processeur dans des structures complexes, avec des applications de streaming et d'autres choses encore, des modules externes sur le serveur etc. Pour en nommer quelques-uns :

    convert_mono_8_float: 14
    convert_stereo_i8_2float: 28
    convert_mono_16le_float: 40
    interpolate_mono_16le_float: 200
    convert_stereo_i16le_2float: 80
    convert_mono_float_16le: 80

Ce qui signifie 1% d'utilisation du processeur pour la conversion, et 5% pour l'interpolation sur ce processeur à 350 MHz.

Chaque paquet de donnée transféré par streaming peut être considéré comme une invocation &MCOP;. Bien sûr, avec de grands paquets, le débit est inférieur à 9000 paquets/s, mais l'idée est là.

Supposons que vous utilisez des paquets de 1024 octets. Ainsi, pour transférer un flux à 44 KHz, stéréo, vous devez transférer 44100*4/1024 = 172 packets par seconde. Supposons que vous puissiez, avec une utilisation du processeur de 100%, transférer 9000 paquets, alors vous auriez une utilisation du processeur de (172*100)/9000 = 2% due au streaming avec des paquets de 1024 octets.

utilisation du processeur par le streaming en pourcents = 1960/(taille du paquet)

ce qui nous donne une utilisation du CPU de 0.5% lorsque le streaming se fait par paquets de 4096 octets.

###

     4974 stefan    20   0  2360 2360  1784 S       0 17.7  1.8   0:21 artsd
     5016 stefan    20   0  2208 2208  1684 S       0  7.2  1.7   0:02 streamsound
     5002 stefan    20   0  2208 2208  1684 S       0  6.8  1.7   0:07 streamsound
     4997 stefan    20   0  2208 2208  1684 S       0  6.6  1.7   0:07 streamsound

     5548 stefan    12   0  2364 2364  1752 R       0  4.9  1.8   0:03 artsd
     5554 stefan     3   0   752  752   572 R       0  0.7  0.5   0:00 top
     5550 stefan     2   0  2280 2280  1696 S       0  0.5  1.7   0:00 artscat

## Bus

Les bus sont des connexions construites de façon dynamique qui transfèrent le signal audio. Fondamentalement, il y a des uplinks (NdT : canal sur lequel on envoie des données) et des downlinks (NdT : canal sur lequel on reçoit des données). Tous les signaux des uplinks sont additionnées et envoyées vers les downlinks.

Les bus sont actuellement implantés pour travailler en stéréo, donc vous ne pouvez transférer que des données stéréo par les bus. Si vous voulez des données mono, transférez les sur un seul canal et laissez l'autre à zéro. Ce que vous avez à faire est de créer un ou plusieurs objets Synth&lowbar;BUS&lowbar;UPLINK, et donnez leur le nom d'un bus, avec lequel ils communiquent (&pex; audio ou percussions). Envoyez simplement les données là-dedans.

Vous aurez alors besoin de créer un ou plusieurs objets Synth&lowbar;BUS&lowbar;DOWNLINK, et donnez leur le nom d'un bus (audio ou percussions ... si ça correspond, les données transiterons dedans), et les données mixées sortiront de nouveau.

Les uplinks et downlinks peuvent résider dans différentes structures, vous pouvez même avoir différents &artsbuilder; en cours et démarrer un uplink dans un et reçevoir les données d'un autre avec une liaison downlink.

Ce qui est sympathique avec les bus, c'est qu'ils sont totalement dynamiques. Vous pouvez brancher et débrancher en temps réel. Il ne devrait alors pas y avoir de clics ou de bruit.

Bien sûr, vous ne devriez pas débrancher un client qui joue un signal, puisque son niveau ne sera probablement pas à zéro lorsque vous le débrancherez, vous entendrez alors un clic.

##

##

### Introduction

###

###

##

###

###

- ``

- ``

- ``

###

##

###

###

###

##

Les éléments de l'interface graphique sont actuellement au stade expérimental. Cependant, cette section décrit ce qui est supposé se passer, donc si vous êtes développeur, vous serez en mesure de comprendre comment &arts; gèrera les interfaces graphiques dans le futur. Il y a aussi du code ici.

Les éléments de l'interface graphique sont utilisés pour permettre aux structures de synthèse d'interagir avec l'utilisateur. Dans le cas le plus simple, l'utilisateur peut modifier directement les paramètres d'une structure (comme un facteur de gain qui est utilisé avant le module de lecture final).

Dans des réglages plus complexes, on pourrait imaginer que l'utilisateur modifie les paramètres d'un groupe de structures et/ou de structures ne fonctionnant pas encore, comme par exemple modifier l'enveloppe ADSR de l'instrument &MIDI; actif. Une autre chose serait le réglage du nom de fichier d'instrument basés sur des échantillons.

D'un autre côté, l'utilisateur aimerait peut être visualiser ce que fait le synthétiseur. Cela pourrait être des oscilloscopes, des analyseurs de spectre, des potentiomètres de volume et quelques visualisateurs expérimentaux qui calculent les fonctions de transfert de certains modules de filtrage.

Enfin, les éléments de l'interfage graphique devraient pouvoir contrôler l'ensemble de la structure de ce qui fonctionne à l'intérieur de &arts; et la façon dont ça fonctionne. L'utilisateur devrait pouvoir assigner des instruments à des canaux midi, démarrer de nouveaux processeurs d'effets, configurer la sortie principale du mixeur (qui est lui-même construit à partir de structures de &arts;) pour ajouter un canal et utiliser une autre stratégie pour ses égaliseurs.

Vous voyez, les éléments de l'interface graphique devraient apporter toutes les possibilités des studios virtuels que &arts; devrait simuler pour l'utilisateur. Bien sûr, ils doivent aussi interagir avec élégance avec les entrées midi (par exemple les potentiomètres qui bougent s'ils reçoivent des messages &MIDI; qui ne changent qu'un paramètre), et probablement générer eux-même des événements &MIDI; pour permettre d'enregistrer les mouvements que l'utilisateur donne aux potentiomètres via un séquenceur.

Techniquement, l'idée est de disposer d'une classe de base &IDL; pour tous les widgets (`Arts::Widget`), et de dériver plusieurs widgets souvent utilisés depuis ceci (comme `Arts::Poti`, `Arts::Panel`, `Arts::Window`, ...).

Ensuite, on peut implanter ces widgets en utilisant un toolkit, par exemple &Qt; ou gtk. Finallement, les effets devraient construire leurs propres interfaces graphiques en dehors des widgets existants. Par exemple, un effet freeverb devrait construire sa propre interface graphique en dehors de cinq machins `Arts::Poti` et un `Arts::Window`. Donc s'il y a une implantation &Qt; de ces widgets de base, l'effet sera en mesure de s'afficher en utilisant &Qt;. S'il y a une implantation Gtk, il fonctionnera aussi avec Gtk (et aura plus ou moins la même apparence etle même comportement).

Finalement, comme nous utilisons &IDL; ici, &artsbuilder; (ou d'autres outils) pourront connecter des interfaces graphiques ensemble de manière visuelle, pour autogénérer des interfaces graphiques à partir de conseils pour les paramètres, simplement basé sur les interfaces. Il devrait être relativement honnête d'écrire une classe créer l'interface graphique à partir de la description, qui prend la description d'une interface graphique (contenant les divers paramètres et widgets), et crée un objet de type inteface graphique en dehors.

Basé sur &IDL; et sur le modèle de composant &arts;/&MCOP;, il devrait être facile d'étendre les objets possibles qui peuvent être utilisés pour les interfaces graphiques aussi facilement que d'ajouter une implantation de type module externe d'un nouveau filtre à &arts;.