Image logo.gif


LA LIBRAIRIE CHANT

Manuel d'utilisation
des fonctions en C

Avril 1997 Analyse/Synthèse
Wednesday, 21-Jan-1998 17:13:14 CET

Dominique Virolle



Généralités

Introduction

La librairie Chant a été écrite en C par Francisco Iovino, optimisée par Chris Rogers et Gerhand Eckel en 1994 et par Dominique Virolle en 1997. Son objectif est de permettre la réalisation de synthèse sonore avec des Formes d'Onde Formantiques (FOFs). Si vous ne connaissez pas la notion de FOF, vous pouvez vous référer aux articles de Xavier Rodet [CHANT 1979] ou à la documentation de PatchWork-Chant (Introduction). La documentation présentée ici a pour objectif d'expliquer comment faire la synthèse par FOFs à l'aide de la librairie Chant dans un programme C.

Cette introduction est suivit par une vue globale de la librairie et des éléments qui peuvent être construits avec Chant.

Les autres parties donnent le détail de chaque type d'élément avec les fonctions C et des exemples.

Au départ

Pour utiliser Chant, il est nécessaire d'avoir un #include <chant.h> dans chaque fichier utilisant une fonction ou un type de la librairie. De plus, il faudra avoir -lchant -lm en option de link. Aucun autre #include n'est normalement nécessaire. Répertoire actuel de la librairie : /u/formes/virolle/src/libchant/lib/$(uname -s)_$(uname -r).

Les entités de la librairie

Chant permet de contrôler 5 grandes entités :

et 2 sous entités :

Tous les éléments appartenant à ces entités sont contrôlable dans le temps.

Un exemple de schéma de synthèse :

Image syllabe.gif

On peut constater que les chemins des connexions aboutissent au port de sortie. C'est la condition pour qu'un élément soit pris en compte dans le calcul.

La librairie permet de créer ces éléments (on peut parler d'objets) et de les paramétrer en fonction du temps.

Pour chaque objet, il faudra :

Réaliser une synthèse, c'est déclarer des objets, les connecter, et construire une fonction par paramètre.

Les paramètres (Break Point Functions)

Pour chaque objet d'une entité ou d'une sous-entité, on peut contrôler les paramètres dans le temps avec des Break Point Functions. Un paramètre est en fait une fonction paramètre(temps, valeur). Il existe au moins 1 break point function par paramètre variable dans le temps et par objet.

Break Point Function (bpf) : c'est une fonction f(t) définie sous forme discrète ; on connaît f seulement pour {t0,......,tn}. Les autres valeurs de f sont approximées par interpolation. L'interpolation effectuée dans la librairie Chant est d'ordre 1 (on relie les points par une droite).

long
ChTimeToSam (float t)
est une fonction permettant de convertir un temps en son équivalent index d'échantillon.


Variables Globales

Pour pouvoir commencer une synthèse avec Chant, il faut au préalable avoir initialisé certaines variables globales :

Fréquence d'échantillonage

La fréquence d'échantillonage est stockée dans la variable globale gChSamRate. Pour lui attribuer une valeur, on utilise la procédure void ChSetSamRate(float Sr).

Ainsi :

  ChSetSamRate(44100.);
permet d'avoir une fréquence d'échantillonage de 44100 Hz.

Nombre de canaux

De même, il faut donner une valeur à la variable gChNumChannels, et cela avec la procédure void ChSetNumChannels(int n). Le nombre de canaux doit être compris entre 1 et 256.

Ainsi :

  ChSetNumChannels(2);
permet d'avoir une synthèse stéréo.

Taille du buffer

Les fonctions de creation ont souvent un argument qui est le taille du buffer. Il est préférable d'utiliser toujours la même en créant une variable globale. 512 est une valeur convenable. On peut choisir la taille du buffer avec la procédure void ChSetBufferSize (int n). Mais elle ne doit pas être utilisée aprés la création d'un objet (FofBank, FilterBank, Souffle, File).

Les listes d'objets

Chant utilise 4 listes d'objet (de globals.h) qui sont :

    gChFofBankList
    gChFilterBankList
    gChSouffleList
    gChFileList

Il est nécessaire de les initialiser et cela se fait très simplement avec la procédure void ChInitGenLists().
En fin de programme, on détruit toutes les listes avec la procédure void ChMakeEmptyGenLists().

Récapitulatif Fonctions pour les Variables Globlales

void
ChInitDefaultGenValues() permet d'initialiser les variables globales à des valeurs par défault. gChSamRate == 44100., gChNumChannels == 1, gChDefaultEndTime très grand pour les applications temps réels, gChDefaultNbObjects == 16 (nombre de sous objets (FOFs par FofBank ou Filtres par FilterBank) maximum.

void
ChSetSamRate (float Sr)

void
ChSetNumChannels(int n)

void
ChSetBufferSize (int n)

void
ChInitGenLists (void)

void
ChMakeEmptyGenLists (void)


FofBank

Ci dessous, les courbes de 5 FOFs d'un même FofBank. La courbe, en bas, à droite, est le signal résultat somme de ces FOFs.

Image FofBank.gif

Ci dessous, les courbes des 5 spectres de FOFs correspondant. La courbe, en bas, à droite, est le spectre du signal total.

Image FofBankspectr.gif

On peut souhaiter corriger le spectre au niveau des très basses fréquences. Pour cela, il suffit d'ajouter un FOF dont la fréquence est proche de 0 (exemple : 50 Hz). On peut également connecter le FofBank à un filtre.

Les FofBanks sont les objets principaux de Chant puisqu'ils contiennent chacun plusieurs FOFs. Le schéma ci-dessous montre le détail d'un FofBank possédant 2 FOFs pour une synthèse sur 2 cannaux. Il y a 2 sorties pour chaque FofBank. L'une permet de connecter le FofBank directement au port de sortie avec la gestion des amplitudes des FOFs sur chaque canal, et l'autre permet de le connecter à des bancs de filtres avec une amplitude de sortie du FofBank. (cf : Connexions)

Image FofBankDescr.gif

Création d'un FofBank

La création d'un FofBank demande de connaître plusieurs paramètres généraux :

On appelle le début (respectivement la fin) d'un FofBank (ou d'un autre objet) l'instant où le FofBank se déclenche (respectivement arrête son activité) dans la synthèse.

long
ChTimeToSam (float t)
est une fonction permettant de convertir un temps en son équivalent index d'échantillon.

Dans l'exemple qui suit, est présentée la création d'un FofBank. Les index ont été calculés à partir d'une représentation temporelle à l'aide de ChTimToSam. Les fonctions ChCreate s'occupent de l'allocation de la mémoire. On remarque que la création est suivie par une initialisation. Le nombre de FOFs utilisés est ici égal à MFofs.

{
  FofBankType *pFofBank;

  long nbFofs = 6; /* nombre de Fofs dans le FofBank */
  float StartTimeFofBank = 0.;
  float EndTimeFofBank = 3.;
       
  /* Creation du FofBank */
  
  pFofBank = ChCreateFofBank ("MyFofBank", 0, nbFofs/* MFofs*/, BufSize);
  ChInitFofBank (pFofBank,
	         ChTimeToSam (StartTimeFofBank),
	         ChTimeToSam (EndTimeFofBank),
	         nbFofs); /* Nombre de FOFs utilisés */
}

Les paramètres d'un FofBank

Le principe pour donner des valeurs à un paramètre est toujours le même. Il faut insérer un point (temps ,valeur) dans la bpf du paramètre désiré. On utilise pour l'insertion la procédure ChInsertPoint(ListType *bpfunction, float time, float value). Cette procédure assure l'ordonnancement des points de la bpf en fonction du temps et l'unicité de chaque time. De plus, lorsque time est maximum par rapport aux points de la bpf, ChInsertPoint ne parcourt pas la bpf et fait appel à ChAddPoint qui insère le nouveau point directement à la fin de la bpf sans se soucier de la valeur de time (cela dans une optique temps réel).
Pour pouvoir récupérer la bpf, on utilise des fonctions de la librairie qui commencent par ChGet.

Les paramètres pouvant varier dans le temps d'un FofBank sont son excitation (f0, Hit), l'amplitude sur chaque canal et les 7 paramètres de chaque FOF.

Un FofBank est un ensemble de FOF dont peut déclencher la synthèse, soit suivant une fréquence, soit à des instants précis, soit les deux ensemble. On a ainsi 3 structures de données : une pour le mode d'excitation qui peut varier au cours du temps, une pour les fréquences (bpf), et une pour les instants précis de déclenchement.

Il y a donc trois modes d'excitation possibles. Le mode peut changer au cours du temps. A l'initialisation d'un Fofbank, le mode au temps 0.0 relatif au FofBank est mis pour des excitations à la fois en fréquence et par instant.

Les trois modes sont représentés par des énumérations:

Les fonctions permettant d'accéder aux données du mode d'excitation sont ChGetFofBankExcitationModeFun et ChGetFofBankExcitationModePointList.

 /* eFreqOnly, eHitOnly, eFreqAndHit sont des entiers, mais le stockage des modes se fait
  * dans un structure de bpf (float). Il faut donc réaliser un cast pour ChInsertPoint().
  * L'insertion de eFreqOnly à l'instant AtTime1==0.0 écrase la valeur par défault qui
  * est eFreqAndHit. (temps relatifs au FofBank)
  */

  float AtTime1 = 0.;
  float AtTime2 = 5.;
  float AtTime3 = 10.;

  ChInsertPoint (ChGetFofBankExcitationModeFun (pFofBank), AtTime1, (float) eFreqOnly);
  ChInitCurrent (ChGetFofBankExcitationModePointList (pFofBank));

  ChInsertPoint (ChGetFofBankExcitationModeFun (pFofBank), AtTime2, (float) eHitOnly);
  ChInitCurrent (ChGetFofBankExcitationModePointList (pFofBank));

  ChInsertPoint (ChGetFofBankExcitationModeFun (pFofBank), AtTime3, (float) eFreqAndHit);
  ChInitCurrent (ChGetFofBankExcitationModePointList (pFofBank));

Le mode d'excitation n'est pas une bpf puisque seulement trois valeurs peuvent y être et qu'il n'y a pas d'interpolation.

Pour faire varier la fréquence assignée à un FofBank, on fait ChInsertPoint(ChGetFofBankFreqFun (FofBank), Time, Value);. Dans l'exemple qui suit, on ajoute 2 points à la bpf ExcitationFreqFun qui permettent ici de faire un glissendo de La4 à La3.

{
  /* Soit pFofBank un FofBankType créé  (temps relatifs au FofBank)*/

  float AtTime1 = 0.;
  float AtTime2 = 2.;

  ChInsertPoint (ChGetFofBankExcitationModeFun (pFofBank), AtTime1, (float) eFreqOnly);
  ChInitCurrent (ChGetFofBankExcitationModePointList (pFofBank));
  /* le mode est à partir du temps 0. relatif au FofBank eFreqOnly. */
  /* [...] */

  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank), AtTime1, 440.);
  ChInitCurrent (ChGetFofBankExcitationFreqPointList (pFofBank));

  /* [...] */

  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank), AtTime2, 220.);
  ChInitCurrent (ChGetFofBankExcitationFreqPointList (pFofBank));
}

L'excitation d'un FofBank à un instant précis ne permet qu'un unique déclenchement sur cette instant. Le mode eHitOnly permet essentiellement de faire des percussions. Les fonctions permettant d'accéder à ces données sont ChGetFofBankExcitationHitFun et ChGetFofBankExcitationHitPointList. Lorsque l'on souhaite un déclenchement du FofBank au temps Time on insert un point (Time, 1.) dans la fonction d'excitation par coups. "1." n'a aucun sens réel.

{
  /* Soit pFofBank un FofBankType créé (temps relatifs au FofBank)*/

  float AtTime1 = 0.;
  float AtTime2 = 2.;

  ChInsertPoint (ChGetFofBankExcitationModeFun (pFofBank), AtTime1, (float) eHitOnly);
  ChInitCurrent (ChGetFofBankExcitationModePointList (pFofBank));
  /* le mode est à partir du temps 0. relatif au FofBank eHitOnly. */
  /* [...] */

  ChInsertPoint (ChGetFofBankExcitationHitFun (pFofBank), AtTime1, 1.);
  ChInitCurrent (ChGetFofBankExcitationHitPointList (pFofBank));

  /* [...] */

  ChInsertPoint (ChGetFofBankExcitationHitFun (pFofBank), AtTime2, 1.);
  ChInitCurrent (ChGetFofBankExcitationHitPointList (pFofBank));
}

Il y a deux façons de paramétrer l'amplitude du FofBank sur chaque canal. Soit l'amplitude est la même pour tous les FOFs (Shared), soit au contraire, chaque FOF a sa propre bpf par canal. La première méthode permet de paramétrer l'amplitude d'un FofBank rapidement mais dans sa globalité.

La deuxième est prévu pour des effets plus fins par rapport aux FOFs. Ces deux méthodes sont incompatibles pour un même FofBank. Si des paramètres ont été ajoutés au niveau de chaque FOF, puis que l'on donne soudainement un paramètre global, alors ce dernier annule l'effet des premiers. (Shared prioritaire).

L'exemple ci-après montre l'ajout d'un point dans la bpf du canal 0 d'un FofBank.

{
  /* Soit pFofBank un FofBankType créé (temps absolus)*/

  long numChannel = 0; /* numéro du canal dont on va modifier la bpf */
  float AtTime = 0.;
  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, numChannel), AtTime, 1.);  
  ChInitCurrent (ChGetFofBankSharedChanPointList (pFofBank, numChannel));
}

L'exemple ci-dessous montre la paramètrisation de l'amplitude d'un FofBank à 2 FOFs en stéréo. L'amplitude est ici indépendante pour chaque FOF. Ainsi, sur le canal 1 (Right), le FOF 0 est 4 fois plus fort que le FOF 1.

{
  /* Soit pFofBank un FofBankType créé */

  float AtTime = 0.;
 
  /* ChGetFofBankChanFun (pFofBank, <numero de FOF>, <numero du canal>)
   */
  ChInsertPoint (ChGetFofBankChanFun (pFofBank, 0, 0), AtTime, 1.);  
  ChInitCurrent (ChGetFofBankChanPointList (pFofBank, 0, 0));
  ChInsertPoint (ChGetFofBankChanFun (pFofBank, 0, 1), AtTime, 2.);  
  ChInitCurrent (ChGetFofBankChanPointList (pFofBank, 0, 0));

  ChInsertPoint (ChGetFofBankChanFun (pFofBank, 1, 0), AtTime, 1.5);  
  ChInitCurrent (ChGetFofBankChanPointList (pFofBank, 1, 0));
  ChInsertPoint (ChGetFofBankChanFun (pFofBank, 1, 1), AtTime, 0.5);  
  ChInitCurrent (ChGetFofBankChanPointList (pFofBank, 1, 1));

}

cf : principe.

Lorsque l'on utilise la sortie vers un FilterBank, on ne contrôle pas l'amplitude par canal car les filtres ne reçoivent que des signaux monos. Par contre, cette sortie possède une bpf d'amplitude. On utilise les fonctions ChGetFofBankAmpFun(FofBankType *FofBank) et ChGetFofBankAmpPointList(FofBankType *FofBank) pour paramétrer cette bpf.

{
  /* soit pFofBank un FofBank créé et connecté sur un FilterBank*/

  float AtTime = 0.;

  ChInsertPoint (ChGetFofBankAmpFun (pFofBank), AtTime, 0.5);
  ChInitCurrent (ChGetFofBankAmpPointList (pFofBank));
}

Chacun des 7 paramètres d'un FOF possède sa bpf. Le principe est toujours le même. La différence provient du fait que la fonction ChGetFofBankParFun demande en argument un numéro de FOF et le nom du paramètre.

On utilise les noms qui suivent provenant de #define (FofBank.h).

EXC_TIME 0  temps d'excitation
DEB_TIME 1  temps de début d'atténuation
ATT_TIME 2  temps d'atténuation
AMP      3  amplitude
FREQ     4  fréquence
BW       5  largeur de bande à -3db
PHASE    6  phase

Exemple :

{
  /* Soit pFofBank un FofBankType créé (temps relatifs au FofBank)*/

  long numFof = 0; /* numéro du FOF dont on va modifier les bpf */
  float AtTime = 0.;

  ChInsertPoint (ChGetFofBankParFun (pFofBank, numFof, FREQ), AtTime, 1750.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, numFof, FREQ));
  
  ChInsertPoint (ChGetFofBankParFun (pFofBank, numFof, AMP), AtTime, 15.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, numFof, AMP));
  
  ChInsertPoint (ChGetFofBankParFun (pFofBank, numFof, BW), AtTime, 48);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, numFof, BW));
  
  ChInsertPoint (ChGetFofBankParFun (pFofBank, numFof, EXC_TIME), AtTime, 0.002);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, numFof, EXC_TIME));
  
  ChInsertPoint (ChGetFofBankParFun (pFofBank, numFof, DEB_TIME), AtTime, 0.05);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, numFof, DEB_TIME));
  
  ChInsertPoint (ChGetFofBankParFun (pFofBank, numFof, ATT_TIME), AtTime, 0.004);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, numFof, ATT_TIME));
  
  ChInsertPoint (ChGetFofBankParFun (pFofBank, numFof, PHASE), AtTime, 0.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, numFof, PHASE));
}

Il est possible de donner la même bpf d'un paramètre à tous les FOFs du FofBank en utilisant la fonction ChGetFofBankSharedFun(FofBankType *FofBank, int ParName). Cela peut être très pratique pour les paramètres comme la phase, le temps d'excitation, le temps de début d'atténuation et le temps d'atténuation qui sont souvent les mêmes pour tous les FOFs (ChGetFofBankSharedParFun et ChGetFofBankSharedParPointList).

Récapitulatif FofBank

FofBankType *
ChCreateFofBank (char *Name, int FofBankID, int MFofs, int BufSize)

void
ChInitFofBank (FofBankType *FofBank, long SSample, long ESample, int NumFofs)

void
ChSetNumFormants (FofBankType *FofBank, int n)
permet d'utiliser seulement n FOFs parmi les MFofs déclarés à la création. Ainsi cette procédure permet de changer le nombre de Fofs dans le temps. Evidement, il ne faut pas avoir n > MFofs.

FofBankType *
ChSearchFofBank_Name (char *Name)
renvoie le pointeur sur le FofBank de nom <Name>,
renvoie NULL accompagné d'un message si la recherche échoue.

FofBankType *
ChSearchFofBank_ID (int NumFofBank)
renvoie le pointeur sur le FofBank d'identificateur <NumFofBank>,
renvoie NULL accompagné d'un message si la recherche échoue.

ListType *
ChGetFofBankExcitationModeFun (FofBankType *FofBank)

PointListType *
ChGetFofBankExcitationModePointList (FofBankType *FofBank)

ListType *
ChGetFofBankExcitationFreqFun (FofBankType *FofBank)

PointListType *
ChGetFofBankExcitationFreqPointList (FofBankType *FofBank)

ListType *
ChGetFofBankExcitationHitFun (FofBankType *FofBank)

PointListType *
ChGetFofBankExcitationHitPointList (FofBankType *FofBank)

ListType *
ChGetFofBankSharedChanFun (FofBankType *FofBank, int Channel)

PointListType *
ChGetFofBankSharedChanPointList (FofBankType *FofBank, int Channel)

ListType *
ChGetFofBankChanFun (FofBankType *FofBank, int Fof, int Channel)

PointListType *
ChGetFofBankChanPointList (FofBankType *FofBank, int Fof, int Channel)

ListType *
ChGetFofBankAmpFun (FofBankType *FofBank)

PointListType *
ChGetFofBankAmpPointList (FofBankType *FofBank)

ListType *
ChGetFofBankParFun (FofBankType *FofBank, int Fof, int ParName)

PointListType *
ChGetFofBankParPointList (FofBankType *FofBank, int Fof, int ParName)

ListType *
ChGetFofBankSharedFun (FofBankType *FofBank, int ParName)

PointListType *
ChGetFofBankSharedPointList (FofBankType *FofBank, int ParName)


FilterBank

Image FofBankDescr.gif

Création d'un FilterBank

Le principe pour la création d'un FilterBank est le même que pour celle du FofBank. C'est seulement plus simple puisqu'il n'y a pas de FofBank. On utilise la fonction ChCreateFilterBank pour créer l'objet et allouer la mémoire et la procédure ChInitFilterBank pour initialiser les paramètres. Il est nécessaire de fournir le nombre de filtres maximum du Filterbank,le nombre de filtres utilisés, ses index d'échantillon de début et de fin.

{
  FilterBankType *pFilterBank;

  long nbFilters = 5;
  float StartTimeFilterBank = 0.;
  float EndTimeFilterBank = 2.;
  
      
  /* Creation du FilterBank */
  
  pFilterBank = ChCreateFilterBank ("myFilterBank", 0, nbFilter/* max */, BufSize);
  ChInitFilterBank (pFilterBank,
	            ChTimeToSam (StartTimeFilterBank),
	            ChTimeToSam (EndTimeFilterBank),
	            nbFilters/* utilisés */);
}

Les paramètres d'un FilterBank

La modification des paramètres d'un FilterBank repose sur le même principe qu'avec un FofBank.

Les deux méthodes pour paramétrer l'amplitude par canal d'un FofBank se retrouvent pour le FilterBank. Les noms des fonctions ne diffèrent que d'un 'FilterBank' juste après le ChGet.

Exemple d'une insertion d'un point dans la bpf (shared) de l'amplitude d'un FilterBank.

{
  /* Soit pFilterBank un FilterBankType créé (temps absolus)*/

  long numChannel = 0;
  float AtTime = 0.;


  ChInsertPoint (ChGetFilterBankSharedChanFun (pFilterBank, numChannel), AtTime, 1.);
  ChInitCurrent (ChGetFilterBankSharedChanPointList (pFilterBank, numChannel));
}

Exemple d'une insertion d'un point dans chaque bpf de l'amplitude par canal et par filtre d'un FilterBank à 2 filtres.

{
  /* Soit pFilterBank un FilterBankType créé (temps absolus)*/
  float AtTime = 0.;

  /* ChGetFilterBankChanFun (pFilterBank, <numero du filtre>, <numero du canal>)
   */ 
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 0), AtTime, 0.7);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 0, 0));
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 1), AtTime, 1.5);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 0, 1));

  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 0), AtTime, 1.);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 1, 0));
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 1), AtTime, 1.);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 1, 1));

}

cf : principe.

On utilise les fonctions ChGetFilterBankAmpFun(FilterBankType *FilterBank) et ChGetFilterBankAmpPointList(FilterBankType *FilterBank).

{
  /* soit pFilterBank un FilterBank créé et connecté sur un FilterBank*/

  float AtTime = 0.;

  ChInsertPoint (ChGetFilterBankAmpFun (pFilterBank), AtTime, 0.5);
  ChInitCurrent (ChGetFilterBankAmpPointList (pFilterBank));
}

Les filtres ont 4 paramètres :

FIL_GAIN 0  gain du filtre
FIL_BW   1  largeur de bande à -3db
FIL_FREQ 2  fréquence du filtre résonnant
FIL_COR  3  correction du filtre par rapport au gain

Exemple : ici, la fréquence, le gain et la largeur de bande sont paramétrés filtre par filtre alors que la correction est identique pour tous les filtres du FilterBank.

{
  /* Soit pFilterBank un FilterBankType créé (temps relatifs au FilterBank)*/

  float AtTime = 0.;
  
  /* filtre 0 */
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_FREQ), AtTime, 540.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 0, FIL_FREQ));

  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_GAIN), AtTime, 2.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 0, FIL_GAIN));

  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_BW), AtTime, 40.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 0, FIL_BW));


  /* filtre 1 */
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_FREQ), AtTime, 1750.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 1, FIL_FREQ));

  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_GAIN), AtTime, 1.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 1, FIL_GAIN));

  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_BW), AtTime, 80.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 1, FIL_BW));


  /* filtre 2 */
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_FREQ), AtTime, 2280.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 2, FIL_FREQ));

  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_GAIN), AtTime, 1.5.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 2, FIL_GAIN));

  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_BW), AtTime, 15.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 2, FIL_BW));


  /* on a choisi d'avoir une seule bpf FIL_COR pour tous les filtres */
  ChInsertPoint (ChGetFilterBankSharedFun (pFilterBank, FIL_COR), AtTime, 1);
  ChInitCurrent (ChGetFilterBankSharedPointList (pFilterBank, FIL_COR));
}

Récapitulatif FilterBank

FilterBankType *
ChCreateFilterBank (char *Name, int FilterBankID, int MFils, int Size)

void
ChInitFilterBank (FilterBankType *FilterBank, long SSample, long ESample, int NumFils)

void
ChSetNumFilters (FilterBankType *FilterBank, int n)
permet de faire varier au cours du temps le nombre de filtres utilisés.

FilterBankType *
ChSearchFilterBank_Name (char *Name)
renvoie le pointeur sur le FilterBank de nom <Name>,
renvoie NULL accompagné d'un message si la recherche échoue.

FilterBankType *
ChSearchFilterBank_ID (int NumFilterBank)
renvoie le pointeur sur le FilterBank d'identificateur <NumFilterBank>,
renvoie NULL accompagné d'un message si la recherche échoue.

ListType *
ChGetFilterBankChanFun (FilterBankType *FilterBank, int Fil, int Channel)

PointListType *
ChGetFilterBankChanPointList (FilterBankType *FilterBank, int Fil, int Channel)

ListType *
ChGetFilterBankSharedChanFun (FilterBankType *FilterBank, int Channel)

PointListType *
ChGetFilterBankSharedChanPointList (FilterBankType *FilterBank, int Channel)

ListType *
ChGetFiltreBankAmpFun (FiltreBankType *FiltreBank)

PointListType *
ChGetFiltreBankAmpPointList (FiltreBankType *FiltreBank)

ListType *
ChGetFilterBankParFun (FilterBankType *FilterBank, int Fil, int Par)

PointListType *
ChGetFilterBankParPointList (FilterBankType *FilterBank, int Fil, int Par)

ListType *
ChGetFilterBankSharedFun (FilterBankType *FilterBank, int Par)

PointListType *
ChGetFilterBankSharedPointList (FilterBankType *FilterBank, int Par)


Souffle

Un Souffle est un bruit blanc.

Image SouffleDescr.gif

Important : un Souffle est toujours connecté à un FilterBank.

Création d'un Souffle

C'est le même principe qu'avec les FilterBanks. La structure d'un Souffle est plus simple. Seuls les index d'échantillons de début et de fin sont nécessaires.

{
  SouffleType *pSouffle;

  float StartTimeSouffle = 0.;
  float EndTimeSouffle = 0.5;
  

  /* Creation du Souffle */
  
  pSouffle = ChCreateSouffle ("mySouffle", 0, BufSize);
  ChInitSouffle (pSouffle,
	         ChTimeToSam (StartTimeSouffle),
	         ChTimeToSam (EndTimeSouffle));
}

Amplitude d'un Souffle

cf : principe.

On utilise les fonctions ChGetSouffleAmpFun(SouffleType *Souffle) et ChGetSouffleAmpPointList(SouffleType *Souffle).

{
  /* soit pSouffle un Souffle créé */

  float AtTime = 0.;

  ChInsertPoint (ChGetSouffleAmpFun (pSouffle), AtTime, 0.5);
  ChInitCurrent (ChGetSouffleAmpPointList (pSouffle));
}

Récapitulatif Souffle

SouffleType *
ChCreateSouffle (char *Name, int SouffleID, int Size)

void
ChInitSouffle (SouffleType *Souffle, long SSample, long ESample)

SouffleType *
ChSearchSouffle_Name (char *Name)
renvoie le pointeur sur le Souffle de nom <Name>,
renvoie NULL accompagné d'un message si la recherche échoue.

SouffleType *
ChSearchSouffle_ID (int NumSouffle)
renvoie le pointeur sur le Souffle d'identificateur <NumSouffle>,
renvoie NULL accompagné d'un message si la recherche échoue.

ListType *
ChGetSouffleAmpFun (SouffleType *Souffle)

PointListType *
ChGetSouffleAmpPointList (SouffleType *Souffle)


File

Un File est un fichier son mono que l'on envoie à un FilterBank. Un tel fichier pourrait provenir d'une précédente synthèse de Chant par exemple ou être un train d'impulsions de formes diverses ou encore un fichier aiff.

Image FileDescr.gif

Important : un File est toujours connecté à un FilterBank.

Déclaration d'un File

C'est le même principe qu'avec les FilterBanks.

{
  FileType *pFile;

  char Name[64] = "FichierSon";
  float StartTimeFile = 0.;
  float EndTimeFile = 10.;
  float Offset = 1;
  
 
  /* Creation du File */
  
  pFile = ChCreateFile ("myFile", 0, Name, BufSize);
  ChInitFile (pFile,
	      ChTimeToSam (StartTimeFile),
	      ChTimeToSam (EndTimeFile),
	      Offset);
}

Amplitude d'un File

cf : principe.

On utilise les fonctions ChGetFileAmpFun(FileType *File) et ChGetFileAmpPointList(FileType *File).

{
  /* Soit pFile un File créé */

  float AtTime = 0.;  

  ChInsertPoint (ChGetFileAmpFun (pFile), AtTime, 1.1);
  ChInitCurrent (ChGetFileAmpPointList (pFile));
}

Récapitulatif File

FileType *
ChCreateFile (char *NameID, int FileID, char *Name, int Size)

void
ChInitFile (FileType *File, long SSample, long ESample,long Offset)

FileType *
ChSearchFile_Name (char *Name)
renvoie le pointeur sur le File de nom <Name>,
renvoie NULL accompagné d'un message si la recherche échoue.
<Name> est le nom d'identification de l'objet dans Chant ; ce n'est pas le nom du fichier son importé.

FileType *
ChSearchFile_ID (int NumFile)
renvoie le pointeur sur le File d'identificateur <NumFile>,
renvoie NULL accompagné d'un message si la recherche échoue.

ListType *
ChGetFileAmpFun (FileType *File)

PointListType *
ChGetFileAmpPointList (FileType *File)


Connexions

Il existe 6 types de connexions. Pour qu'un objet entre en considération dans la synthèse, il faut qu'il soit connecté à un FilterBank, lui-même connecté au port de sortie. Un FofBank peut être directement connecté au port de sortie.
Nouveau : Les FilterBanks peuvent être maintenant connectés entre eux.

Connexions sur le port de sortie

short
ChConnFofBankPort (struct FofBankT *FofBank)

Exemple :

{
/* Soit pFofBank un FofBank créé et lié à un ou plusieurs FofBank*/
 
  ChConnFofBankPort (pFofBank);  
}

short
ChConnFilterBankPort (struct FilterBankT *FilterBank)

Exemple :

{
/* Soit pFilterBank un FilterBank */
  
  ChConnFilterBankPort (pFilterBank);
}

Connexions sur un FilterBank

short
ChConnFofBankFilterBank (FofBankType *FofBank, FilterBankType *FilterBank)

Exemple :

{
/* Soient pFofBank un FofBank créé et lié à un ou plusieurs FofBank
 * et pFilterBank un FilterBank
 */

  ChConnFofBankFilterBank (pFofBank, pFilterBank);
}

short
ChConnSouffleFilterBank (SouffleType *Souffle, FilterBankType *FilterBank)

Exemple :

{
/* Soient pSouffle un Souffle créé
 * et pFilterBank un FilterBank
 */

  ChConnSouffleFilterBank (pSouffle, pFilterBank);
}

short
ChConnFileFilterBank (FileType *File, FilterBankType *FilterBank)

Exemple :

{
/* Soient pFile un File déclaré
 * et pFilterBank un FilterBank
 */

  ChConnFileFilterBank (pFile, pFilterBank);
}

short
ChConnFilterBankFilterBank (FilterBankType *FilterBank1, FilterBankType *FilterBank2)

La particularité de cette connexion est qu'elle permet de connecter deux objets appartenant à la même entité. Toutefois, il est interdit de connecter les FilterBanks en cycle. Dans le cas d'une tentative d'une connexion qui aboutirait à un filtre, l'action de connection est annulée.
Exemple :

{
/* Soient pFilterBank1 et pFilterBank2 deux FilterBanks déclarés
 * On connecte la sortie de pFilterBank1 à l'entrée de pFilterBank2
 */

  ChConnFileFilterBank (pFilterBank1, pFilterBank2);
}


Synthèses

La synthèse repose (au niveau utilisateur) sur 3 procédures :

void
ChOpenPort (char *Name)

void
ChClosePort ()

void
ChSynthesis (long StartSam, long EndSam)

et sur une variable globale gChOutPort définie dans globals.h.

Temps de début et de fin

La fonction qui contrôle le calcul doit connaître le temps de début et de fin de synthèse (convertis en index d'échantillon).

rappel :
long
ChTimeToSam (float t)
est une fonction permettant de convertir un temps en son équivalent index d'échantillon.

Fichier de Sortie

Les fonctions ChOpenPort et ChClosePort permettent de contrôler le fichier de sortie binaire.

  ChOpenPort ("foo.bin");

ChOpenPort s'occupe de l'allocation mémoire et de l'initialisation de gChOutPort.

Synthèse en temps différé

La synthèse en temps différé consiste à lancer le calcul une fois que tous les paramètres ont été donnés. On calcule ainsi tout d'un seul coup.

  ChSynthesis (ChTimeToSam(StartTime), ChTimeToSam(EndTime));

Synthèse orientée temps réel

La fonction ChSynthesis ne réalise le calcul qu'entre deux index d'échantillon donnés en argument. Cela permet donc de faire la synthèse tranche par tranche et donc d'avoir une optique temps réel.

Mais ChSynthesis ne vérifie pas la cohérence temporelle. La figure ci-dessous montre le type d'erreurs que l'on peut obtenir si l'on ne contrôle pas correctement les lancements de synthèse. En effet, si à la connaissance des bpfs jusqu'à s1, on lance ChSynthesis(0, ChTimeToSam(t1)), alors les bpfs 2 et 3 ne seront pas interpolées comme on le souhaite puisqu'aucun point, après t1 pour ces deux bpfs, n'est connu.

Image bpfs.gif

Par contre si ChSynthesis(0, ChTimeToSam(t1)) est lancé à la connaissance des bpfs jusqu'à s1', alors toutes les interpolations peuvent être effectuées.

Ainsi, pour faire de la synthèse temps réel, il faut que toutes les bpfs soient "mises à jour" régulièrement quitte à redonner la même valeur à un paramètre pour exprimer le fait qu'il ne change pas.

--NEW-- On utilise pour la synthèse orientée temps réel la fonction ChTimeControlSynthesis(TimeControlType*, float) où le floatant est le temps courant. La fonction ne synthétise alors que jusqu'au temps maximum connu pour toutes les bpfs. Il faut dans ce cas initialiser la variable global gChTimeControl avec void ChInitTimeControl(TimeControlType*).

Exemple complet

#include <stdio.h>
#include <stdlib.h>
#include "chant.h" 
/* pas <chant.h>  car la librairie n'est pas
 * (au moment de l'ecriture de cet exemple)
 * dans le repertoire des librairies
 */

int main()
{
  float StartTime = 0.;
  float EndTime = 2.;
  long  BufSize = 512;

  FilterBankType *pFilterBank;
  float StartTimeFilterBank = 0.;
  float EndTimeFilterBank = 2.;
  long nbFilter = 3;


  SouffleType *pSouffle;
  float StartTimeSouffle = 0.;
  float EndTimeSouffle = 0.5;


  FofBankType *pFofBank;
  float StartTimeFofBank = 0.4;
  float EndTimeFofBank = 2.;
  long nbFofs = 6;



  ChInitDefaultGenValues();
  ChSetNumChannels(2);

  ChInitGenLists();
  
  ChOpenPort ("foo.bin");
  

  /* Creation du Souffle */
  
  pSouffle = ChCreateSouffle ("mySouffle", 0, BufSize);
  ChInitSouffle (pSouffle,
                 ChTimeToSam (StartTimeSouffle),
                 ChTimeToSam (EndTimeSouffle));



  /* Creation du FilterBank */
  
  pFilterBank = ChCreateFilterBank ("myFilterBank", 0, nbFilter, BufSize);
  ChInitFilterBank (pFilterBank,
                    ChTimeToSam (StartTimeFilterBank),
                    ChTimeToSam (EndTimeFilterBank),
                    nbFilter);


  /* Creation du FofBank et du FofBank */  
    
  pFofBank = ChCreateFofBank ("FofBank1", 0, nbFofs, BufSize);
  ChInitFofBank (pFofBank,
                 ChTimeToSam (StartTimeFofBank),
                 ChTimeToSam (EndTimeFofBank),
                 nbFofs);

  ChInitCurrent (ChGetFofBankAmpPointList (pFofBank));


  /* Connexions */

  ChConnSouffleFilterBank (pSouffle, pFilterBank);
  ChConnFilterBankPort (pFilterBank);
  ChConnFofBankPort (pFofBank);


  /* Amplitude du Souffle */

  ChInsertPoint (ChGetSouffleAmpFun (pSouffle),StartTimeSouffle, 4.);
  ChInitCurrent (ChGetSouffleAmpPointList (pSouffle));

  ChInsertPoint (ChGetSouffleAmpFun (pSouffle), EndTimeSouffle, 2.);
  ChInitCurrent (ChGetSouffleAmpPointList (pSouffle));



  /* Amplitude par canal Filtre par Filtre */

      /*filtre 0 canal 0 */
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 0),  0.,    2.);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 0),  0.2,   1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 0),  0.33,  1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 0),  0.5,   1. );
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 0, 0));

      /*filtre 0 canal 1 */
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 1),  0.,    1.1);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 1),  0.2,   1.1);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 1),  0.33,  1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 0, 1),  0.5,   1.2);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 0, 1));
  
      /*filtre 1 canal 0 */
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 0),  0.,    1.);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 0),  0.2,   1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 0),  0.33,  1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 0),  0.5,   1.);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 1, 0));

      /*filtre 1 canal 1 */
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 1),  0.,    1.1);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 1),  0.2,   1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 1),  0.33,  2.);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 1, 1),  0.5,   1.);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 1, 1));

      /*filtre 2 canal 0 */
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 2, 0),  0.,    1.);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 2, 0),  0.2,   1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 2, 0),  0.33,  2.);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 2, 0),  0.5,   1.1);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 2, 0));

      /*filtre 2 canal 1 */
  /*  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 2, 1),  0.,    1.1);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 2, 1),  0.2,   1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 2, 1),  0.33,  1.5);
  ChInsertPoint (ChGetFilterBankChanFun (pFilterBank, 2, 1),  0.5,   1.4);
  ChInitCurrent (ChGetFilterBankChanPointList (pFilterBank, 2, 1));
  */

  /* parametre des filtres */
      /* COR  en Shared */
  ChInsertPoint (ChGetFilterBankSharedFun (pFilterBank, FIL_COR),   0.,  1);
  ChInsertPoint (ChGetFilterBankSharedFun (pFilterBank, FIL_COR),   0.05, 1);
  ChInitCurrent (ChGetFilterBankSharedPointList (pFilterBank, FIL_COR));

  /* filtre 0 */
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_FREQ),     0.,  540.);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_FREQ),     0.05, 240.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 0, FIL_FREQ));
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_GAIN),     0.,  6.);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_GAIN),     0.05, 6.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 0, FIL_GAIN));
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_BW),       0.,  140.);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 0, FIL_BW),       0.05, 90.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 0, FIL_BW));


  /* filtre 1 */
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_FREQ),     0.,  980.);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_FREQ),     0.05, 1100.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 1, FIL_FREQ));
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_GAIN),     0.,  12.);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_GAIN),     0.05, 18.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 1, FIL_GAIN));
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_BW),       0.,  200.);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 1, FIL_BW),       0.05, 80.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 1, FIL_BW));

  /* filtre 2 */
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_FREQ),     0.,  2200.);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_FREQ),     0.05, 1500.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 2, FIL_FREQ));
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_GAIN),     0.,  7.5);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_GAIN),     0.05, 8.5);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 2, FIL_GAIN));
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_BW),       0.,  500.);
  ChInsertPoint (ChGetFilterBankParFun (pFilterBank, 2, FIL_BW),       0.05, 500.);
  ChInitCurrent (ChGetFilterBankParPointList (pFilterBank, 2, FIL_BW));


  /* On connait toutes les informations jusqu'a 0.4 seconde.
   * on ne connait pas jusqu'a 0.5s car le FofBank apparait
   * a 0.4s et aucune donnee n'a ete fournie.
   * on peut lancer la synthese sur [0, 0.4[.
   */
   ChSynthesis (ChTimeToSam(StartTime), ChTimeToSam(0.399));
   

  /**** FofBank ****/
  /* pitch du FofBank */

  ChInsertPoint (ChGetFofBankExcitationModeFun (pFofBank), 0., (float) eFreqOnly);
  ChInitCurrent (ChGetFofBankExcitationModePointList (pFofBank));
  /* le mode est à partir du temps 0. relatif au FofBank eFreqOnly. */

  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.00,  110.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.05,  105.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.10,  110.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.15,  115.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.20,  110.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.25,  105.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.30,  110.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.35,  115.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.40,  110.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.45,  105.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.50,  110.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  0.55,  115.);
  ChInsertPoint (ChGetFofBankExcitationFreqFun (pFofBank),  1.60,  110.);
  ChInitCurrent (ChGetFofBankExcitationFreqPointList (pFofBank));

  /* Amplitude par canal pour tous les FOFs */
    /* canal 0 */
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 0),  0.0,  0.5);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 0),  0.1,  1.);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 0),  0.2,  1.5);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 0),  0.3,  1.5);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 0),  0.4,  1.);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 0),  1.6,  0.);  
  ChInitCurrent (ChGetFofBankSharedChanPointList (pFofBank, 0));
    /* canal 1 */
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 1),  0.0,  0.5);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 1),  0.1,  2.);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 1),  0.2,  0.8);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 1),  0.3,  1.2);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 1),  0.4,  1.);  
  ChInsertPoint (ChGetFofBankSharedChanFun (pFofBank, 1),  1.6,  0.);  
  ChInitCurrent (ChGetFofBankSharedChanPointList (pFofBank, 1));
  
  /* parametres des FOFs */
  /* en Shared pour certain */
  /* EXC_TIME */
  ChInsertPoint (ChGetFofBankSharedFun (pFofBank,  EXC_TIME),  0.0,  0.002);
  ChInsertPoint (ChGetFofBankSharedFun (pFofBank,  EXC_TIME),  1.6,  0.003);
  ChInitCurrent (ChGetFofBankSharedPointList (pFofBank, EXC_TIME));
  /* DEB_TIME */
  ChInsertPoint (ChGetFofBankSharedFun (pFofBank, DEB_TIME ),  0.0,  0.05);
  ChInsertPoint (ChGetFofBankSharedFun (pFofBank, DEB_TIME ),  1.6,  0.05);
  ChInitCurrent (ChGetFofBankSharedPointList (pFofBank,DEB_TIME ));
  /* ATT_TIME */
  ChInsertPoint (ChGetFofBankSharedFun (pFofBank, ATT_TIME),  0.0,  0.004);
  ChInsertPoint (ChGetFofBankSharedFun (pFofBank, ATT_TIME),  1.6,  0.003);
  ChInitCurrent (ChGetFofBankSharedPointList (pFofBank, ATT_TIME));
  /* PHASE */
  ChInsertPoint (ChGetFofBankSharedFun (pFofBank, PHASE),   0.0,  0.0);
  ChInsertPoint (ChGetFofBankSharedFun (pFofBank, PHASE),   1.6,  0.0);
  ChInitCurrent (ChGetFofBankSharedPointList (pFofBank, PHASE));

  /* FREQ */
  /* FOF 0 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 0, FREQ), 0.0, 0.0001);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 0, FREQ), 1.6, 0.0001);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 0, FREQ));
  /* FOF 1 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 1, FREQ), 0.0, 609.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 1, FREQ), 0.3, 325.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 1, FREQ), 1.6, 325.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 1, FREQ));
  /* FOF 2 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 2, FREQ), 0.0, 1000.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 2, FREQ), 0.3, 700.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 2, FREQ), 1.6, 700.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 2, FREQ));
  /* FOF 3 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 3, FREQ), 0.0, 2450.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 3, FREQ), 1.6, 2450.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 3, FREQ));
  /* FOF 4 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 4, FREQ), 0.0, 2700.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 4, FREQ), 1.6, 2700.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 4, FREQ));
  /* FOF 5 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 5, FREQ), 0.0, 3240.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 5, FREQ), 1.6, 3240.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 5, FREQ));


  /* AMP */
  /* FOF 0 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 0, AMP), 0.0, 36.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 0, AMP), 1.6, 36.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 0, AMP));
  /* FOF 1 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 1, AMP), 0.0, 33.8);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 1, AMP), 1.6, 33.8);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 1, AMP));
  /* FOF 2 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 2, AMP), 0.0, 27.7);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 2, AMP), 1.6, 27.7);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 2, AMP));
  /* FOF 3 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 3, AMP), 0.0, 21.8);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 3, AMP), 1.6, 21.8);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 3, AMP));
  /* FOF 4 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 4, AMP), 0.0, 20.8);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 4, AMP), 1.6, 20.8);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 4, AMP));
  /* FOF 5 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 5, AMP), 0.0, 10.);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 5, AMP), 1.6, 10.);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 5, AMP));


  /* BW */
  /* FOF 0 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 0, BW), 0.0, 10);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 0, BW), 1.6, 10);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 0, BW));
  /* FOF 1 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 1, BW), 0.0, 78);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 1, BW), 1.6, 78);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 1, BW));
  /* FOF 2 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 2, BW), 0.0, 88);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 2, BW), 1.6, 88);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 2, BW));
  /* FOF 3 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 3, BW), 0.0, 123);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 3, BW), 1.6, 123);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 3, BW));
  /* FOF 4 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 4, BW), 0.0, 128);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 4, BW), 1.6, 128);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 4, BW));
  /* FOF 5 */
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 5, BW), 0.0, 138);
  ChInsertPoint (ChGetFofBankParFun (pFofBank, 5, BW), 1.6, 138);
  ChInitCurrent (ChGetFofBankParPointList (pFofBank, 5, BW));


  ChSynthesis (ChTimeToSam(0.399)+1, ChTimeToSam(EndTime) );
   
  ChClosePort ();

  ChMakeEmptyGenLists();
}


Simplification de l'utilisation de Chant (1997)

De nouvelles fonctions ont été ajoutées à la librairie (ChUser.*). Celles-ci ont pour objectif de simplifier l'utilisation de Chant en éliminant l'utilisation des fonctions de bas niveau ChInsertPoint et ChInitCurrent. Toutes ces nouvelles fonctions sont préfixées de 'ChU', signifiant qu'il s'agit de fonctions d'utilisation de Chant.

Les nouvelles fonctions

Il y a deux types de fonctions utilisateur : les créations d'objets et les ajouts de points dans les bpfs.

Remarque : ChUPutFofBankChan est prioritaire sur ChUPutFofChan. Il faut, pour chaque paramètre, pour chaque FOF, utiliser l'un ou l'autre. (rappel : Amplitude par canal d'un FofBank) De même avec ChUPutFofBankPar et ChUPutFofPar, ChUPutFilterBankChan et ChUPutFilterChan, et ChUPutFilterBankPar et ChUPutFilterPar.
Les temps sont relatifs aux objets (entre 0. et EndTime-StartTime) sauf pour les sorties sur cannaux qui sont en temps absolus (entre StartTime et EndTime).

FofBankType*
ChUCreateFofBank char *iName, int FofBankId, float StartTime, float EndTime, int nbFofs, int BufSize)

FilterBankType*
ChUCreateFilterBank (char *iName, int FilterBankId, float StartTime, float EndTime, int nbFilters, int Size)

SouffleType*
ChUCreateSouffle (char *iName, int SouffleId, float StartTime, float EndTime, int Size)

FileType*
ChUCreateFile (char *NameID, int FileID, char *iName, float StartTime, float EndTime, long Offset, int Size)

FofBankType*
ChUPutFofChan (FofBankType *ioFofBank, int Fof, int Channel, float Time, float Value)

FofBankType*
ChUPutFofBankChan (FofBankType *ioFofBank, int Channel, float Time, float Value)

FilterBankType*
ChUPutFilterChan (FilterBankType *ioFilterBank, int Filter, int Channel, float Time, float Value)

FilterBankType*
ChUPutFilterBankChan (FilterBankType *ioFilterBank, int Channel, float Time, float Value)

SouffleType*
ChUPutSouffleAmp (SouffleType *ioSouffle, float Time, float Value)

FileType*
ChUPutFileAmp (FileType *ioFile, float Time, float Value)

FofBankType*
ChUPutFofBankExcitationMode (FofBankType *ioFofBank, float Time, float Value)

FofBankType*
ChUPutFofBankExcitationFreq (FofBankType *ioFofBank, float Time, float Value)

FofBankType*
ChUPutFofBankExcitationHit (FofBankType *ioFofBank, float Time)

FofBankType*
ChUPutFofPar (FofBankType *ioFofBank, int Fof, int ParName, float Time, float Value)

FofBankType*
ChUPutFofBankPar (FofBankType *ioFofBank, int ParName, float Time, float Value)

FilterBankType*
ChUPutFilterPar (FilterBankType *ioFilterBank, int Filter, int ParName, float Time, float Value)

FilterBankType*
ChUPutFilterBankPar (FilterBankType *ioFilterBank, int ParName, float Time, float Value)

Exemple

#include <stdio.h>
#include <stdlib.h>
#include "chant.h" 
/* pas <chant.h>  car la librairie n'est pas
 * (au moment de l'ecriture de cet exemple)
 * dans le repertoire des librairies
 */

int main(void)
{
  FofBankType *oFofBank;
  FilterBankType *oFilterBank;
  SouffleType *oSouffle;

  ChInitDefaultGenValues();
  ChSetSamRate(16000.);

  ChInitGenLists();
  

  oSouffle= ChUCreateSouffle ("Souffle",
                              1,
                              0.,
                              gChDefaultEndTime,
                              gChBufferSize);
  ChUPutSouffleAmp(oSouffle, 0.000000, 0.000000);
  oFilterBank= ChUCreateFilterBank ("FilterBank",
				    2,
				    0.,
				    gChDefaultEndTime,
				    gChDefaultNbObjects,
				    gChBufferSize);
  ChSetNumFilters(oFilterBank, 0);
  ChSetNumFilters(oFilterBank, 5);
  ChUPutFilterPar(oFilterBank, 0, FIL_FREQ, 0.000000, 609.000000);
  ChUPutFilterPar(oFilterBank, 0, FIL_GAIN, 0.000000, 30.000000);
  ChUPutFilterPar(oFilterBank, 0, FIL_BW,   0.000000, 78.000000);
  ChUPutFilterPar(oFilterBank, 0, FIL_COR,  0.000000, 1.000000);
  ChUPutFilterPar(oFilterBank, 1, FIL_FREQ, 0.000000, 1000.000000);
  ChUPutFilterPar(oFilterBank, 1, FIL_GAIN, 0.000000, 23.900000);
  ChUPutFilterPar(oFilterBank, 1, FIL_BW,   0.000000, 88.000000);
  ChUPutFilterPar(oFilterBank, 1, FIL_COR,  0.000000, 1.000000);
  ChUPutFilterPar(oFilterBank, 2, FIL_FREQ, 0.000000, 2450.000000);
  ChUPutFilterPar(oFilterBank, 2, FIL_GAIN, 0.000000, 18.000000);
  ChUPutFilterPar(oFilterBank, 2, FIL_BW,   0.000000, 123.000000);
  ChUPutFilterPar(oFilterBank, 2, FIL_COR,  0.000000, 1.000000);
  ChUPutFilterPar(oFilterBank, 3, FIL_FREQ, 0.000000, 2700.000000);
  ChUPutFilterPar(oFilterBank, 3, FIL_GAIN, 0.000000, 19.000000);
  ChUPutFilterPar(oFilterBank, 3, FIL_BW,   0.000000, 128.000000);
  ChUPutFilterPar(oFilterBank, 3, FIL_COR,  0.000000, 1.000000);
  ChUPutFilterPar(oFilterBank, 4, FIL_FREQ, 0.000000, 3240.000000);
  ChUPutFilterPar(oFilterBank, 4, FIL_GAIN, 0.000000, 6.100000);
  ChUPutFilterPar(oFilterBank, 4, FIL_BW,   0.000000, 138.000000);
  ChUPutFilterPar(oFilterBank, 4, FIL_COR,  0.000000, 1.000000);
  ChUPutFilterChan(oFilterBank, 0, 0, 0.000000, 1.000000);
  ChUPutFilterChan(oFilterBank, 1, 0, 0.000000, 1.000000);
  ChUPutFilterChan(oFilterBank, 2, 0, 0.000000, 1.000000);
  ChUPutFilterChan(oFilterBank, 3, 0, 0.000000, 1.000000);
  ChUPutFilterChan(oFilterBank, 4, 0, 0.000000, 1.000000);
  ChUPutSouffleAmp(oSouffle, 0.050000, 0.200000);
  ChUPutSouffleAmp(oSouffle, 0.100000, 1.000000);
  ChUPutSouffleAmp(oSouffle, 0.200000, 1.200000);
  ChUPutSouffleAmp(oSouffle, 0.300000, 2.000000);
  ChUPutSouffleAmp(oSouffle, 0.500000, 1.800000);
  oFofBank= ChUCreateFofBank ("FofBank",
                              0,
                              0.5,
                              gChDefaultEndTime,
                              gChDefaultNbObjects,
                              gChBufferSize);
  ChSetNumFormants(oFofBank, 0);
  ChUPutFofBankExcitationFreq (oFofBank, 0.00000, 80.00000);
  ChSetNumFormants(oFofBank, 5);
  ChUPutFofPar(oFofBank, 0, FREQ,     0.000000, 609.000000);
  ChUPutFofPar(oFofBank, 0, AMP,      0.000000, 80.000000);
  ChUPutFofPar(oFofBank, 0, BW,       0.000000, 78.000000);
  ChUPutFofPar(oFofBank, 0, EXC_TIME, 0.000000, 0.002000);
  ChUPutFofPar(oFofBank, 0, DEB_TIME, 0.000000, 0.050000);
  ChUPutFofPar(oFofBank, 0, ATT_TIME, 0.000000, 0.004000);
  ChUPutFofPar(oFofBank, 0, PHASE,    0.000000, 0.000000);
  ChUPutFofPar(oFofBank, 1, FREQ,     0.000000, 1000.000000);
  ChUPutFofPar(oFofBank, 1, AMP,      0.000000, 53.900002);
  ChUPutFofPar(oFofBank, 1, BW,       0.000000, 88.000000);
  ChUPutFofPar(oFofBank, 1, EXC_TIME, 0.000000, 0.002000);
  ChUPutFofPar(oFofBank, 1, DEB_TIME, 0.000000, 0.050000);
  ChUPutFofPar(oFofBank, 1, ATT_TIME, 0.000000, 0.004000);
  ChUPutFofPar(oFofBank, 1, PHASE,    0.000000, 0.000000);
  ChUPutFofPar(oFofBank, 2, FREQ,     0.000000, 2450.000000);
  ChUPutFofPar(oFofBank, 2, AMP,      0.000000, 18.000000);
  ChUPutFofPar(oFofBank, 2, BW,       0.000000, 123.000000);
  ChUPutFofPar(oFofBank, 2, EXC_TIME, 0.000000, 0.002000);
  ChUPutFofPar(oFofBank, 2, DEB_TIME, 0.000000, 0.050000);
  ChUPutFofPar(oFofBank, 2, ATT_TIME, 0.000000, 0.004000);
  ChUPutFofPar(oFofBank, 2, PHASE,    0.000000, 0.000000);
  ChUPutFofPar(oFofBank, 3, FREQ,     0.000000, 2700.000000);
  ChUPutFofPar(oFofBank, 3, AMP,      0.000000, 19.000000);
  ChUPutFofPar(oFofBank, 3, BW,       0.000000, 128.000000);
  ChUPutFofPar(oFofBank, 3, EXC_TIME, 0.000000, 0.002000);
  ChUPutFofPar(oFofBank, 3, DEB_TIME, 0.000000, 0.050000);
  ChUPutFofPar(oFofBank, 3, ATT_TIME, 0.000000, 0.004000);
  ChUPutFofPar(oFofBank, 3, PHASE,    0.000000, 0.000000);
  ChUPutFofPar(oFofBank, 4, FREQ,     0.000000, 3240.000000);
  ChUPutFofPar(oFofBank, 4, AMP,      0.000000, 6.100000);
  ChUPutFofPar(oFofBank, 4, BW,       0.000000, 138.000000);
  ChUPutFofPar(oFofBank, 4, EXC_TIME, 0.000000, 0.002000);
  ChUPutFofPar(oFofBank, 4, DEB_TIME, 0.000000, 0.050000);
  ChUPutFofPar(oFofBank, 4, ATT_TIME, 0.000000, 0.004000);
  ChUPutFofPar(oFofBank, 4, PHASE,    0.000000, 0.000000);
  ChUPutFofChan(oFofBank, 0, 0, 0.500000, 0.050000);
  ChUPutFofChan(oFofBank, 1, 0, 0.500000, 0.100000);
  ChUPutFofChan(oFofBank, 2, 0, 0.500000, 0.050000);
  ChUPutFofChan(oFofBank, 3, 0, 0.500000, 0.100000);
  ChUPutFofChan(oFofBank, 4, 0, 0.500000, 0.050000);
  ChUPutFofBankExcitationFreq (oFofBank, 0.100000, 113.00000);
  ChUPutSouffleAmp(oSouffle, 0.700000, 0.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 0.300000, 108.00000);
  ChUPutFofBankExcitationFreq (oFofBank, 0.400000, 113.00000);
  ChUPutFofBankExcitationFreq (oFofBank, 0.500000, 108.00000);
  ChUPutFofPar(oFofBank, 0, FREQ,     0.500000 , 609.000000);
  ChUPutFofPar(oFofBank, 0, AMP,      0.500000, 500.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 0.600000, 113.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 0.700000, 113.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 0.800000, 108.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 0.900000, 113.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.000000, 164.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.100000, 160.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.200000, 168.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.300000, 160.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.400000, 168.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.500000, 160.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.600000, 113.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.700000, 108.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.800000, 113.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 1.900000, 108.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 2.000000, 220.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 2.100000, 215.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 2.200000, 225.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 2.300000, 215.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 2.400000, 225.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 2.500000, 196.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 3.000000, 164.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 3.500000, 130.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 4.000000, 160.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 4.500000, 110.000000);
  ChUPutFofPar(oFofBank, 0, FREQ,     4.500000, 609.000000);
  ChUPutFofPar(oFofBank, 0, AMP,      4.500000, 80.000000);
  ChUPutFofPar(oFofBank, 0, BW,       4.500000, 78.000000);
  ChUPutFofPar(oFofBank, 0, EXC_TIME, 4.500000, 0.002000);
  ChUPutFofPar(oFofBank, 0, DEB_TIME, 4.500000, 0.050000);
  ChUPutFofPar(oFofBank, 0, ATT_TIME, 4.500000, 0.004000);
  ChUPutFofPar(oFofBank, 0, PHASE,    4.500000, 0.000000);
  ChUPutFofPar(oFofBank, 1, FREQ,     4.500000, 1000.000000);
  ChUPutFofPar(oFofBank, 1, AMP,      4.500000, 53.900002);
  ChUPutFofPar(oFofBank, 1, BW,       4.500000, 88.000000);
  ChUPutFofPar(oFofBank, 1, EXC_TIME, 4.500000, 0.002000);
  ChUPutFofPar(oFofBank, 1, DEB_TIME, 4.500000, 0.050000);
  ChUPutFofPar(oFofBank, 1, ATT_TIME, 4.500000, 0.004000);
  ChUPutFofPar(oFofBank, 1, PHASE,    4.500000, 0.000000);
  ChUPutFofPar(oFofBank, 2, FREQ,     4.500000, 2450.000000);
  ChUPutFofPar(oFofBank, 2, AMP,      4.500000, 18.000000);
  ChUPutFofPar(oFofBank, 2, BW,       4.500000, 123.000000);
  ChUPutFofPar(oFofBank, 2, EXC_TIME, 4.500000, 0.002000);
  ChUPutFofPar(oFofBank, 2, DEB_TIME, 4.500000, 0.050000);
  ChUPutFofPar(oFofBank, 2, ATT_TIME, 4.500000, 0.004000);
  ChUPutFofPar(oFofBank, 2, PHASE,    4.500000, 0.000000);
  ChUPutFofPar(oFofBank, 3, FREQ,     4.500000, 2700.000000);
  ChUPutFofPar(oFofBank, 3, AMP,      4.500000, 19.000000);
  ChUPutFofPar(oFofBank, 3, BW,       4.500000, 128.000000);
  ChUPutFofPar(oFofBank, 3, EXC_TIME, 4.500000, 0.002000);
  ChUPutFofPar(oFofBank, 3, DEB_TIME, 4.500000, 0.050000);
  ChUPutFofPar(oFofBank, 3, ATT_TIME, 4.500000, 0.004000);
  ChUPutFofPar(oFofBank, 3, PHASE,    4.500000, 0.000000);
  ChUPutFofPar(oFofBank, 4, FREQ,     4.500000, 3240.000000);
  ChUPutFofPar(oFofBank, 4, AMP,      4.500000, 6.100000);
  ChUPutFofPar(oFofBank, 4, BW,       4.500000, 138.000000);
  ChUPutFofPar(oFofBank, 4, EXC_TIME, 4.500000, 0.002000);
  ChUPutFofPar(oFofBank, 4, DEB_TIME, 4.500000, 0.050000);
  ChUPutFofPar(oFofBank, 4, ATT_TIME, 4.500000, 0.004000);
  ChUPutFofPar(oFofBank, 4, PHASE,    4.500000, 0.000000);
  ChUPutFofChan(oFofBank, 0, 0, 5.000000, 0.050000);
  ChUPutFofChan(oFofBank, 1, 0, 5.000000, 0.100000);
  ChUPutFofChan(oFofBank, 2, 0, 5.000000, 0.050000);
  ChUPutFofChan(oFofBank, 3, 0, 5.000000, 0.100000);
  ChUPutFofChan(oFofBank, 4, 0, 5.000000, 0.050000);
  ChUPutFofBankExcitationFreq (oFofBank, 4.600000, 164.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 4.700000, 110.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 4.800000, 105.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 4.900000, 115.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 5.000000, 105.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 5.100000, 115.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 5.200000, 105.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 5.300000, 115.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 5.400000, 105.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 5.500000, 115.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 5.600000, 105.000000);
  ChUPutFofBankExcitationFreq (oFofBank, 5.700000, 115.000000);
  ChUPutFofPar(oFofBank, 0, FREQ,     5.700000, 609.000000);
  ChUPutFofPar(oFofBank, 0, AMP,      5.700000, 80.000000);
  ChUPutFofPar(oFofBank, 0, BW,       5.700000, 78.000000);
  ChUPutFofPar(oFofBank, 0, EXC_TIME, 5.700000, 0.002000);
  ChUPutFofPar(oFofBank, 0, DEB_TIME, 5.700000, 0.050000);
  ChUPutFofPar(oFofBank, 0, ATT_TIME, 5.700000, 0.004000);
  ChUPutFofPar(oFofBank, 0, PHASE,    5.700000, 0.000000);
  ChUPutFofPar(oFofBank, 1, FREQ,     5.700000, 1000.000000);
  ChUPutFofPar(oFofBank, 1, AMP,      5.700000, 53.900002);
  ChUPutFofPar(oFofBank, 1, BW,       5.700000, 88.000000);
  ChUPutFofPar(oFofBank, 1, EXC_TIME, 5.700000, 0.002000);
  ChUPutFofPar(oFofBank, 1, DEB_TIME, 5.700000, 0.050000);
  ChUPutFofPar(oFofBank, 1, ATT_TIME, 5.700000, 0.004000);
  ChUPutFofPar(oFofBank, 1, PHASE,    5.700000, 0.000000);
  ChUPutFofPar(oFofBank, 2, FREQ,     5.700000, 2450.000000);
  ChUPutFofPar(oFofBank, 2, AMP,      5.700000, 18.000000);
  ChUPutFofPar(oFofBank, 2, BW,       5.700000, 123.000000);
  ChUPutFofPar(oFofBank, 2, EXC_TIME, 5.700000, 0.002000);
  ChUPutFofPar(oFofBank, 2, DEB_TIME, 5.700000, 0.050000);
  ChUPutFofPar(oFofBank, 2, ATT_TIME, 5.700000, 0.004000);
  ChUPutFofPar(oFofBank, 2, PHASE,    5.700000, 0.000000);
  ChUPutFofPar(oFofBank, 3, FREQ,     5.700000, 2700.000000);
  ChUPutFofPar(oFofBank, 3, AMP,      5.700000, 19.000000);
  ChUPutFofPar(oFofBank, 3, BW,       5.700000, 128.000000);
  ChUPutFofPar(oFofBank, 3, EXC_TIME, 5.700000, 0.002000);
  ChUPutFofPar(oFofBank, 3, DEB_TIME, 5.700000, 0.050000);
  ChUPutFofPar(oFofBank, 3, ATT_TIME, 5.700000, 0.004000);
  ChUPutFofPar(oFofBank, 3, PHASE,    5.700000, 0.000000);
  ChUPutFofPar(oFofBank, 4, FREQ,     5.700000, 3240.000000);
  ChUPutFofPar(oFofBank, 4, AMP,      5.700000, 6.100000);
  ChUPutFofPar(oFofBank, 4, BW,       5.700000, 138.000000);
  ChUPutFofPar(oFofBank, 4, EXC_TIME, 5.700000, 0.002000);
  ChUPutFofPar(oFofBank, 4, DEB_TIME, 5.700000, 0.050000);
  ChUPutFofPar(oFofBank, 4, ATT_TIME, 5.700000, 0.004000);
  ChUPutFofPar(oFofBank, 4, PHASE,    5.700000, 0.000000);
  ChUPutFofChan(oFofBank, 0, 0, 6.500000, 0.000000);
  ChUPutFofChan(oFofBank, 1, 0, 6.500000, 0.000000);
  ChUPutFofChan(oFofBank, 2, 0, 6.500000, 0.000000);
  ChUPutFofChan(oFofBank, 3, 0, 6.500000, 0.000000);
  ChUPutFofChan(oFofBank, 4, 0, 6.500000, 0.000000);

  /* Connexions */
  ChOpenPort ("foo.bin");  

  ChConnFofBankPort(oFofBank);
  ChConnSouffleFilterBank(oSouffle, oFilterBank);
  ChConnFilterBankPort(oFilterBank);


  printf("Synthesis begin\n");
  ChSynthesis(ChTimeToSam(0.), ChTimeToSam(6.5));
  printf("Synthesis end\n");
  
   
  ChClosePort ();
  ChMakeEmptyGenLists();

  return 0;
}


Fichier de paramètres SDIF

Pour synthétiser à partir d'un fichier de paramètres SDIF:

{
  ChInitDefaultGenValues();
  ChInitGenLists(); 

  ChOpenPort("out.bin");

  ChReadSdifFile("parametre.sdif", eLoadAndSynthesis);

  ChClosePort();

  ChMakeEmptyGenLists();
}

Le fichier SDIF doit contenir des données pour Chant. Elles doivent être déclarées dans la table des StreamIDs (1IDS) au format prévu pour Chant (cf. Documentation de la Norme SDIF).

Le TreeWay d'un StreamID doit faire référence à un type de patch prédéfini. Ils sont:

Image Patch0.gif Image Patch1.gif Image Patch2.gif Image Patch3.gif Image Patch4.gif Image Patch5.gif Image Patch6.gif Image Patch7.gif Image Patch8.gif Image Patch9.gif Image Patch10.gif