Avril 1997 Analyse/Synthèse
Wednesday, 21-Jan-1998 17:13:14 CET
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.
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)
.
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 :
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.
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.
Pour pouvoir commencer une synthèse avec Chant, il faut au préalable avoir initialisé certaines variables globales :
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.
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.
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).
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()
.
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)
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.
Ci dessous, les courbes des 5 spectres de FOFs correspondant. La courbe, en bas, à droite, est le spectre du signal total.
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)
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 */ }
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:
eFreqOnly
(== (int) 0):
Seule la bpf des fréquences d'excitation est prise en compte,eHitOnly
(== (int) 1):
Seuls les temps d'excitation sont pris en compte,eFreqAndHit
(== (int) 2):
Les frèquences et les coups d'excitation sont pris en compte. 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
).
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)
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 */); }
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)); }
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)
Un Souffle est un bruit blanc.
Important : un Souffle est toujours connecté à un FilterBank.
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)); }
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)); }
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)
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.
Important : un File est toujours connecté à un FilterBank.
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); }
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)); }
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)
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.
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); }
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); }
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
.
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.
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
.
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));
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.
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*)
.
#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(); }
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.
Il y a deux types de fonctions utilisateur : les créations d'objets et les ajouts de points dans les bpfs.
ChUCreate
Objet *pObjet; pObjet = ChUCreate<Objet>(<<paramètres>>);
ChUPut
'.
Leur utilisation est prévue pour être procédurale mais elles renvoient le pointeur sur l'objet
modifié.ChUPut<Objet><Par>(pObjet, <<identificteurs de la bpf>>, <temps>, <valeur>);Syntaxe pour un paramètre d'une Sous-Entité : (pObjet crée)
ChUPut<Sous-Objet>Par(pObjet, <<identificteurs du Sous-Objet>, <<identificteurs de la bpf>, <temps>, <valeur>);
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)
#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; }
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: