[OpenBSD]

Portage des applications audio sur OpenBSD

Ce document ne traite actuellement que des sons echantillonés. Les contributions abordant les synthétiseurs et les tables de mixage sont les bienvenues.

Les applications audio sont en général difficiles à porter, le son étant un domaine dans lequel les interfaces ne sont pas du tout standardisées, même si l'approche ne varie que très peu en fonction des systèmes d'exploitation.

Utilisation de ossaudio

L'émulation ossaudio est peut-être le moyen le plus simple, mais elle ne fonctionne pas toujours, et ce n'est pas forcément un bon choix.

Utilisation de code NetBSD ou FreeBSD

Depuis que nous partageons une partie de l'interface audio avec NetBSD et FreeBSD, partir d'un port NetBSD est chose raisonnable. Pensez que certains fichiers changent de place, et que certaines entrées dans sys/audioio.h sont obsolètes. De plus, de nombreux ports ne sont pas idéalement programmés, et ne fonctionnent réellement que sur un seul type de machine. Certains changements deviennent ainsi nécessaires. Lisez la partie suivante.

Ecriture de code OpenBSD

Dépendances Matérielles

VOUS NE DEVRIEZ PARTIR SUR AUCUN PRESUPPOSES CONCERNANT LE MATERIEL AUDIO UTILISE.
Du code éronné se caractérise par une simple vérification du champ a_info.play.precision, comportant 8 ou 16 bits, et par le fait qu'il suppose que les échantillons sont signés ou non-signés en fonction du comportement de soundblaster. Vous devriez vérifier explicitement l'échantillon et programmer en fonction. Un simple exemple :

	AUDIO_INIT_INFO(&a_info); a_info.play.encoding =
	AUDIO_ENCODING_SLINEAR; a_info.play.precision = 16;
	a_info.play.sample_rate = 22050; error = ioctl(audio,
	AUDIO_SETINFO, &a_info); if (error) /* deal with it */ error
	= ioctl(audio, AUDIO_GETINFO, &a_info);
	switch(a_info.play.encoding) { case AUDIO_ENCODING_ULINEAR_LE:
	case AUDIO_ENCODING_ULINEAR_BE: if (a_info.play.precision == 8)
	/* ... */ else /* ... */ break; case ...

	default:
	/* n'oubliez pas de prendre en compte ce que vous ignorez !!!
	 * Par exemple,
	 */
	fprintf(stderr, 
			"Unsupported audio format (%d), ask ports@ about that\n",
			a_info.play.encoding);

	}
	/* à présent, n'oubliez pas de vérifier la fréquence
	 * d'échantillonage que vous avez
	 */
	

Ceci concerne le plus petit fragment de code que vous pourriez traiter avec un grand nombre de problèmes.

Formats 16 bit et "endianness"

Lors d'une utilisation classique, vous demandez simplement le type d'encodage (par exemple, AUDIO_ENCODING_SLINEAR), et vous réessayez un encodage avec "endianness" (par exemple, AUDIO_ENCODING_SLINEAR_LE). Considérant qu'une carte son ne doit pas forcément utiliser le même "endianness" que votre plate-forme, vous devriez vous préparer à rencontrer cela. Le moyen le plus simple est probablement de préparer un buff audio complet, et d'utiliser swab(3) si un changement d'endianness est nécessaire. Traiter des échantillons externes consiste en général à :
  1. Analyser le format de l'échantillon,
  2. Obtenir l'échantillon présent,
  3. Permuter l'endianness si ce n'est pas le format natif,
  4. Calculer ce que vous voulez en sortie dans un buffer,
  5. Permuter l'endianness si votre carte son n'est pas dans le format natif,
  6. Jouer le contenu du buffer.
Evidemment, vous pourriez être capable de sauter les étapes 3 et 5 si vous jouez un son s'averrant être dans le format natif de votre carte son.

Qualité audio

Le matériel pourrait avoir d'étranges limitations, comme être incapable de dépasser les 22050 Hz en stereo, mais plus que 44100 en mono. C'est dans ce genre de cas que vous devriez donner à l'utilisateur la possibilité de changer ses préférences, et d'essayer d'avoir les meilleures performances possibles. Par exemple, il est stupide de limiter la fréquence à 22050 Hz sous prétexte que vous produisez un son stereo. Et si l'utilisateur n'avait pas un système de son stereo connecté à la sortie de sa carte son ?

Il est également grotesque de saisir de manière permanente les limitations des compatibles soundblaster dans votre programme. Vous devriez en être conscient, mais essayer d'obtenir un son au delà de la barrière des 22050 Hz/stereo et vérifier les résultats.

Echantillonage de la fréquence

Vous devriez vraiment vérifier la fréquence d'échantillonage que votre carte vous restitue. Un décalage de 5% relève déjà du mi-ton, et certaines personnes ont une audition beaucoup plus précise que cela, alors que beaucoup d'entre nous ne remarquerons rien. Votre application devrait être en mesure de rééchantilloner à la volée, peut être naïvement, ou via de sournoises applications des formules de rééchantillonage de Shannon si vous le pouvez.

Gamme dynamique

Les échantillons n'utilisent pas toujours la gamme complète de valeurs possibles. Premièrement, les échantillons enregistrés avec un faible gain ne sonneront que très faiblement sur la machine, forçant ainsi l'utilisateur à augmenter le volume. Deuxièmement, sur les machines avec un matériel audio mal isolé, le rendu des sons bas signifie que vous entendrez surtout les battements de coeur de votre machine, au lieu du son que vous attendiez. Enfin, la conversion idiote de 16 bits à 8 bits pourrait vous laisser avec seulement 4 bits audio utilisables, ce qui procurerait une qualité désastreuse.

Si cela est possible, la meilleure solution est probablement de parcourir intégralement le flux que vous êtes en passe de jouer, et de l'arranger afin qu'il utilise la gamme dynamique complète. Si vous ne pouvez pas vous le permettre, mais que vous pouvez gérer ceci afin d'avoir un minimum de regard sur ce que vous êtes en passe de jouer, vous pouvez ajuster le réglage du volume à la volée, vous n'avez qu'a vous assurer que ce dernier reste a une fréquence bien inférieure à celle du son que vous voulez jouer, et que vous n'obtenez aucun débordement -- ces derniers sonneront toujours moins bien que les améliorations que vous essayez de faire.
La perception du volume étant logarithmique, l'utilisation de décalages logarithmiques est généralement suffisante. Si votre donnée est signée, vous devriez explicitement coder le décalage comme une division, l'opérateur C >> n'étant pas utilisable sur des données signées.

Si tout le reste échoue, vous devriez au moins essayer de fournir à l'utilisateur une option de décalage du volume.

Audio performance

Les applications dotées de fins basses n'ont habituellement pas à s'en soucier. Gardez en tête que certains d'entre nous utilisent OpenBSD en fin basse 68030 et que si une application sonore peut fonctionner sur cela, il faut que ce soit le cas.

N'oubliez pas de faire des comparatifs. Les optimisations théoriques ne sont que ceci : théoriques. Des figures significatives devraient être collectées pour vérifier ce qui est une amélioration majeure et ce qui ne l'est pas.

Pour les applications audio haute performance, comme mpegI-layer3, certains points doivent être pris en compte :

Un modèle que vous pourriez avoir à suivre afin d'obtenir des résultats optimisés est de commencer par compiler un petit programme de test qui s'assure du matériel audio disponible, et procède ensuite à la configuration de votre programme pour qu'il traite de façon optimale le matériel audio disponible. Vous pourriez raisonnablement inciter les personnes voulant de bonnes performances audio à recompiler votre port quand ils changent de matériel, en s'assurant des changements.

Temps réel ou synchronisé

Considérant qu'OpenBSD n'est pas temps réel, vous pourriez quand même vouloir écrire des applications audio souvent temps réel, comme par exemple les jeux. Dans ce cas, vous aurez à diminuer la taille des blocs afin que les effets sonores ne soient pas désynchronisés avec le jeu en court. Le problème avec ceci est que l'interface pourrait être affamée, entrainnant des rendements horribles.

Dans le cas ou vous voudriez simplement que audio et graphismes soient synchronisés, et que le comportement de votre programme est prévisible, atteindre la synchronisation est chose facile. Vous jouez juste vos échantillons audio, et demandez au périphérique audio ce que vous êtes actuellement en train de jouer, via AUDIO_GETOOFFS, avant d'utiliser cette information pour synchroniser à l'avance les graphismes. Si vous demandez ceci suffisament fréquemment (disons, tous les dizièmes de seconde), et aussi longtemps que vous avez des ressources pour utiliser votre application, vous pouvez obtenir une très bonne synchronisation par ce moyen. Vous pourriez avoir à peaufiner les figures avec un décalage constant, il peut en effet y avoir des retards entre les informations rapportées par l'audio, ce qui se joue actuellement, et le temps mis par XWindow pour afficher quelquechose.

Contribution retour au code

Dans le cas d'applications audio, travailler avec l'auteur du programme est très important. Si son code ne marche par exemple qu'avec les cartes soundblaster, il y a de fortes chances pour qu'il faille faire face à d'autres technologies très prochainement.

Si vous ne lui envoyez pas vos commentaires de cette manière, votre code aura été inutile.

Il se pourrait aussi qu'il ait déjà notifié les problèmes que vous rencontrez, et qu'il s'y attèle dans l'arbre de développement. Si les patches que vous écrivez représentent plus qu'une poignée de lignes, la coopération est certainement une très bonne idée.


Porting www@openbsd.org
$OpenBSD: audio-port.html,v 1.6 2007/06/05 08:19:52 jufi Exp $