Obligement - L'Amiga au maximum

Jeudi 25 avril 2024 - 03:31  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in english


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : C - Lecteur 8SVX (deuxième partie)
(Article écrit par Pascal Amiable et extrait d'Amiga News Tech - juin 1992)


Nous allons voir ici l'ensemble des blocs de données (chunks) du format IFF 8SVX puis nous modifierons le programme du mois dernier afin de reproduire un échantillon d'une taille supérieure à 128 ko en mode stéréophonique.

Le mois dernier, nous avons vu rapidement la fonction des blocs de données FORM, VHDR et BODY dont le décodage nous a permis de lire un échantillon simple. En regardant de plus près la structure du fichier, on a :

FORM####8SVX
VHDR####Voice8Header
[NAME####"Nom de l'échantillon"]
[(c) ####"Copyright"]
[AUTH####"Auteur"]
ANNO####"Annotation"
ATAK####EGPoint
RLSE####EGPoint
BODY####Echantillon...

Le bloc de données FORM définit donc à la fois la taille et le type du fichier (ici 8SVX).

Le bloc de données VHDR contenant une structure Voice8Header :

C

Le bloc de données NAME contient une chaîne de caractères utilisable pour stocker le nom du son, par exemple "Blop" ou "Guitare".

Le bloc de données (c) contient une autre chaîne de caractères qui décrit le droit d'auteur du son. Par exemple, "Amiga News Tech".

Le bloc de données AUTH est réservé pour indiquer le nom de l'auteur, par exemple "Herr Doktor".

Le bloc de données ANNO est utilisable pour inscrire des annotations sur l'échantillon. La longueur de ce texte est limitée à 32 767 caractères mais peut très bien être de longueur nulle.

Le bloc de données ATAK contient une structure de type EGPoint, qui permet de définir la valeur d'attaque d'une sonorité. L'attaque d'un son correspond au temps mis pour atteindre un nouveau niveau sonore à partir du niveau courant de restitution. Cette attaque est surtout utile pour les fichiers 8SVX décrivant des instruments.

C

"duration" indique donc le temps que mettra le volume pour atteindre le nouveau volume courant (défini en multipliant l'ancien volume par la valeur du facteur "dest"). La progression de l'ancien volume vers le nouveau est, vous vous en doutez, linéaire.

Le facteur "dest" est défini par un long mot (32 bits) sous la forme mantisse plus exposant. Les 16 bits de poids fort définissent la valeur entière du coefficient, alors que les 16 bits de poids faible définissent les décimales situées après la virgule. Par exemple &0002500 donne un facteur de 2.50.

Comme ATAK, le bloc de données RLSE contient une structure EGPoint qui définit la valeur de descente du volume sonore par un facteur inverse. Son utilisation est en tous points similaire à ATAK.

Le bloc de données BODY signale quant à lui le début des données sonores, c'est-à-dire l'échantillon proprement dit.

Restitution d'échantillons de plus de 128 ko

Pour pouvoir outrepasser la limite de taille de 128 ko pour les échantillons (restriction qui, je le rappelle, est dûe à l'adressage du composant audio), nous allons utiliser une forme de double tampon mémoire assez proche de celle utilisée pour l'animation graphique.

La première chose à faire consiste à découper (virtuellement) l'échantillon en blocs de 64 000 octets. On crée ensuite plusieurs structures IORequest identiques, dans lesquelles on charge les deux premiers "morceaux" d'échantillon.

Une boucle utilisant "GetMsg()" et "Wait()" mettra la tâche en veille pendant la restitution du premier bloc. Une fois ce dernier joué, un message sera renvoyé au programme qui jouera aussitôt le bloc suivant. Pendant ce temps, le programme déchargé de toute contrainte pourra stocker le bloc de données suivant dans le premier IORequest. Après quoi il retournera en veille jusqu'à la prochaine fin de restitution, répétant ainsi le cycle jusqu'à ce qu'il n'y est plus de données à jouer.

A noter que la taille des blocs, fixée à 64 000 octets, est purement arbitraire et que l'on peut prendre n'importe quelle valeur inférieure à 128 ko (attention toutefois à ne pas prendre des blocs trop petits pour laisser le temps au programme de charger le bloc suivant).

La modification de notre programme d'exemple du mois dernier va donc consister à intégrer ce mécanisme en utilisant deux structures IOAudio au lieu d'une. On déclarera donc une nouvelle structure IOAudio dans les variables globales :

struct IOAudio *ioaud2;

Cette structure sera initialisée à zéro en début du programme principal :

ioaud2 = 0L;

De même, on modifiera la partie testant la longueur de l'échantillon de manière à traiter les échantillons de grande taille sans sortir en erreur, ce qui nous donne la portion de code suivante :

C

Lors de l'allocation des strutures IOAudio, on n'oubliera pas d'allouer le pointeur ioaud2 comme suit :

C

Une fois l'initialisation de la structure ioaud1 complète (commande, volume, période...), on initialisera de la même manière la structure ioaud2, soit :

*ioaud2 = *ioaud1; /* copie de structure */

L'adresse de base des données à jouer étant égale, quant à elle, à celle de ioaud1 + 64000 :

ioaud2->ioa_Data = (UBYTE *)chipfich + 64000;

"Aptr" pointera désormais sur ioaud2 :

Aptr = ioaud2;

Il ne nous reste plus qu'à jouer l'échantillon. Si sa taille n'excède pas 128 000 octets, on utilisera la méthode du mois dernier, mais dans le cas contraire, on effectuera un double tampon mémoire avec ioaud1 et ioaud2.

C
C

Lors de la désallocation, on n'oubliera pas de libérer la structure ioaud2, grâce à la ligne suivante :

if (ioaud2)
   FreeMem(ioaud2,sizeof(struct IOAudio));

Lorsque vous aurez modifié le programme d'exemple du mois dernier en suivant les directives énoncées ci-dessus, il sera capable de jouer tout fichier IFF 8SVX, quelle que soit sa taille.

La stéréophonie

Il existe deux méthodes pour restituer un son stéréophonique sur Amiga. La première consiste à numériser simultanément les deux voies (gauche et droite) de la source grâce à un échantillonneur stéréo puis à les rejouer sur deux canaux correctement choisis, avec le même volume. La deuxième consiste à jouer le même échantillon sur deux canaux à des volumes différents, positionnant ainsi le son dans l'espace et autorisant la réalisation d'effets très convaincants de déplacement de la source sonore.

La présence de ces deux types de restitution a amené les développeurs à créer deux blocs de données optionnels, qui permettent de définir un son stéréophonique appartenant à l'un des deux types précités. Ces deux blocs de données sont CHAN et PAN.

Le bloc de données CHAN

CHAN donne les informations nécessaires pour rejouer l'échantillon sur un canal spécifique, ou une combinaison de canaux. Ce bloc de données est donc utilisé dans bon nombre d'échantillonneurs stéréo ou les programmes de restitution associés.

Avant toute utilisation de tels échantillons, on définira les constantes suivantes :

#define RIGHT   4L
#define LEFT    2L
#define STEREO  6L
#define CHAN    MakeID('C','H','A','N')

typedef sampletype LONG;

Si la variable "sampletype" vaut "RIGHT", le programme de lecture sait que l'échantillon a été créé pour être restitué sur le haut-parleur droit, ce qui correspond aux canaux 1 et 2 de l'Amiga. Si "sampletype" vaut "LEFT", on utilisera le haut-parleur gauche, c'est-à-dire les canaux 0 et 3 de l'Amiga. Enfin, si "sampletype" vaut "STEREO", cela signifie qu'une paire de canaux (gauche et droit donc [0,1] et [2,3]) doit être utilisée simultanément pour restituer le son.

Dans le cas d'un son stéréo, les deux échantillons, le gauche et le droit, sont stockés, les uns à la suite des autres après le bloc de données BODY. Il faut savoir que par convention, c'est l'échantillon gauche qui est stocké en premier et que les deux échantillons ont la même longueur.

Dans tous les cas, le programmeur peut ou non tenir compte de ces informations lors de la restitution du son. Mais il serait toutefois dommage de ne pas tenir compte de ces directives.

Le bloc de données PAN

Le bloc de données PAN fournit les informations nécessaires pour créer une restitution stéréophonique d'un son monophonique en le positionnant dans l'espace par restitution du même son sur les deux canaux gauche et droit à des volumes différents. Les données à définir dans votre programme sont les suivantes :

#define PAN MakeID('P','A','N',' ')
typedef sposition Fixed;

"Fixed" est un type défini dans les includes IFF comme LONG et est utilisé pour permettre la compatibilité entre des composants matériels de différentes résolutions. La variable "sposition" décrit la position de la source sonore dans le champ stéréophonique. Il s'agit d'une variable discrète dont la résolution est égale à la moitié de la valeur de discrétisation d'un canal audio.

Je vous rappelle que l'échantillon doit être joué sur les deux canaux en même temps. Le volume global de restitution étant défini par le champ volume de la structure "Voice8Header" du bloc de données VHDR, le calcul des volumes de restitution gauche et droit s'effectue comme suit :

vol_gauche = vol_global / (Unity / sposition);
vol_droit = vol_global - vol_gauche;

"Unity" est une variable dont la valeur est fixée par défaut à 10000L et correspondant au volume maximum possible.

Quelques exemples pour clarifier l'utilisation de ces formules :
  • sposition == Unity : l'échantillon est restitué entièrement sur le haut-parleur gauche.
  • sposition == 0 : l'échantillon est restitué entièrement sur le haut-parleur droit.
  • sposition == Unity/2 : l'échantillon est restitué au centre du champ stéréophonique.
Que faut-il maintenant modifier dans notre programme d'exemple pour qu'il puisse restituer un son stéréophonique ? D'abord réaliser les #define comme indiqué ci-dessus. Ensuite, dans la mesure où nous pourrions être amenés à jouer un échantillon stéréophonique dont la taille serait supérieure à 128 ko, il nous faudra définir quatre structures IOAudio (deux pour chaque voix) :

struct IOAudio *ioaud_11, *ioaud_12, *ioaud_r1, *ioaud_r2;

Comme nous sommes amenés à traiter trois types d'échantillons différents (monophonique standard, stéréophonique et monophonique à restituer en stéréophonie), nous allons déclarer une variable entière type qui contiendra respectivement 0, 1 ou 2 en fonction du type d'échantillon. Cette variable sera initialisée par défaut à zéro.

int type = 0;

Dans la phase d'évaluation des blocs de données, on ajoutera deux instructions "case" pour traiter les blocs de données PAN et CHAN. Pour le bloc de données CHAN, on déclarera un pointeur sur un long qui va contenir le type de son stéréophonique.

LONG *chantype;

case CHAN:   /* échantillon stéréophonique  */
   type = 1; /* on positionne donc type à 1 */
   chantype = (LONG *)(donnee+8L);
   break;

Pour le bloc de données PAN, on déclarera une variable de type pointeur sur un sposition (appelée panpos) qui va contenir le facteur de décalage dans le champ stéréophonique.

sposition *panpos;

case PAN:    /* échantillon mono à jouer en stéréo */
   type = 2; /* on positionne type à 2             */
   panpos = (sposition *)(donnee+8L);
   break;

On alloue l'ensemble des quatre structures IOAudio qui devront ensuite être initialisées, en n'oubliant pas que ioaud_11 et ioaud_12 utilisent un canal gauche (0 ou 3) alors que ioaud_r1 et ioaud_r2 utilisent un canal droit (1 ou 2). Pour ce faire, reportez-vous à cet article. Pour la détermination du volume de sortie, on testera le type d'échantillon : s'il est mono ou stéréo, on fixera un volume identique pour chaque structure IOAudio. Sinon, si c'est un bloc de données de type PAN, on associera un volume différent à chaque paire de canaux.

Soient vol_1 et vol_r, le volume pour chaque canal stéréo et volume, le volume global (initialisé par exemple à 50). On aura :

vol_1 = volume / (Unity / *panpos); /* Unity est IFF.h */
vol_r = volume - vol_r;

Dans le cas d'un échantillon stéréophonique, on fera pointer le début des données sur chaque bloc droit et gauche en prenant en compte la priorité (les données de gauche sont stockées avant les données de droite) et la taille des échantillons (supérieure ou inférieure à 128 ko).

A l'aide de ces informations, je vous laisse le loisir de modifier le programme d'exemple pour pouvoir interpréter des sons stéréophoniques. Je ne pense pas que ce soit une tâche trop ardue pour vous.

Le mois prochain, nous attaquerons le format IFF SMUS, ce qui nous permettra de réaliser un lecteur IFF pour rejouer, par exemple, des morceaux issus de Deluxe Music. En attendant je vous souhaite une bonne lecture et vous clame : "A dans un mois !".


[Retour en haut] / [Retour aux articles] [Article précédent]