Analyse/Synthèse Friday, 03-Aug-2001 15:48:49 CEST
Il est nécessaire pour utiliser la librairie SDIF de connaître son
emplacement (Actuellement dans: ~virolle/src/SDIF/libsdif/(system)).
Les sources sont sous CVS ($CVSROOT), le projet est SDIF
($CVSROOT/SDIF). Aussi, il est nécessaire de connaître l'emplacement
de sdif.h
(Actuellement dans: ~virolle/src/SDIF/sdif). De
plus il faudra que l'executable est accès au fichier
SdifTypes.STYP
qui est un fichier texte contenant la
définition des types prédéfinis de SDIF (Actuellement dans:
~virolle/src/SDIF/libsdif). Il se peut que l'administrateur système
décide de n'avoir qu'une seule copie de ce fichier. Ainsi, il faut
connaître le path associé.
Lorsque tous ces accès fichiers sont résolus, inclure les paths dans
le(s) makefile(s) pour libsdif.a
et sdif.h
.
Ajouter l'option -lsdif
au linkage du projet
(cf. makefile du test de la librairie Chant avec SDIF dans
$CVSROOT/libchant/test/tsdif). Dans tous les fichiers sources
utilisant Sdif ajouter un #include Sdif.h
.
Important: En cas de recompilation de la libraire,
lire la première partie de la documentation du programmeur concernant
les dépendances machines, systèmes et compilateurs (32 ou 64 bits, le
type fpos_t
, Little ou Big endian).
Avant d'utiliser les fonctions SDIF, il est nécessaire d'initialiser
la librairie, ce qui consiste à charger les types prédéfinis du fichier
SdifTypes.STYP
. La fonction à utiliser est
SdifGenInit(char*)
où l'argument est le nom du fichier
des types prédéfinis avec le path. Il suffit d'une seule initialisation
par execution du programme pour manipuler plusieurs fichier SDIF.
Les types prédéfinis sont stockés dans une variable globale
SdifFileT* gSdifPredefinedTypes.
A la fin de tous les traitements de fichiers SDIF, il est préférable
d'annuler l'initialisation de SDIF avec la procédure
SdifGenKill(void)
. Ainsi toute la mémoire allouée par
l'initialisation est rendue au système.
Dans le cas où le fichier des types prédéfinis est introuvable, la
librairie utilise les types qu'elle contient en hard-codé. Cependant,
tous les types n'y sont peut-être pas et un message d'erreur
est écrit sur stderr
.
La librairie est conçu pour manipuler les fichiers SDIF avec des
fonctions d'assez haut niveau. Il n'est normalement pas nécessaire
d'utiliser les fonctions de stdio ou de iostream. Ainsi, la plupart
des fonctions s'applique à un pointeur sur SdifFileT
qui
est une structure contenant toutes les informations d'un fichier et
plus particulièrement le flux FILE *Stream
. L'ouverture
et la fermeture d'un fichier SDIF ressemble fortement aux méthodes
classiques avec FILE*
. On utilise SdifFileT*
SdifOpenFile(char*, int)
et
SdifCloseFile(SdifFileT*)
. Exemple:
#include "sdif.h" void main(void) { SdifFileT *MySdifFileToWrite; SdifFileT *MySdifFileToRead; SdifGenInit("SdifTypes.STYP"); MySdifFileToWrite = SdifOpenFile("NewFile.sdif", eWriteFile); MySdifFileToRead = SdifOpenFile("ExistingFile.sdif", eReadFile); /* ... */ SdifCloseFile(MySdifFileToWrite); SdifCloseFile(MySdifFileToRead); SdifGenKill(); }
On peut remarquer dans cet exemple les deux modes d'ouverture d'un fichier SDIF:
exit(1)
Le code de la librairie SDIF est construit avec un formalisme au niveau des noms des structures, des variables et des fonctions. Il est souhaitable pour les futurs maintenances de SDIF que les noms des fonctions utilisateurs ne commencent pas par 'Sdif'. En particulier, ne pas nommer une fonction SdifFReadMatrix ou SdifFReadFrame...
(12/1997). Il existe plusieurs utilisations de la librairie:
Dans cette partie sur les opérations modifiant la base de données associée à un fichier, on considère que SdifF est un pointeur sur le type SdifFileT alloué, soit:
SdifFileT* SdifF; /* ... */ SdifF = SdifOpenFile("Name", OpenOption); /* où OpenOption est, soit eReadfile, soit eOpenFile */
SdifNameValuesLT* SdifNameValuesLNewHT
(SdifNameValuesLT *NameValuesL)
Cette fonction permet d'ajouter une nouvelle NVT dans la liste de
tables passée par argument:
SdifNameValuesLNewHT(SdifF->NamefValues);
Attention, à l'ouverture de SdifF, il n'y a aucune table dans
SdifF->NamefValues. Il faudra donc au moins en ajouter une
pour pouvoir y mettre des NameValue.
SdifNameValueT* SdifNameValuesLPut
(SdifNameValuesLT *NameValuesL, char *Name, char *Value)
Cette fonction permet d'ajouter une NameValue à table courante
qui est la dernière table créée ou celle définie en tant que table
courante. Name et Value doivent être des chaines caractères
ASCII sans espacements.
SdifHashTableT* SdifNameValuesLSetCurrHT
(SdifNameValuesLT *NameValuesL, SdifUInt4 NumCurrHT)
Cette fonction permet de définir la nième NVT de la liste
des tables comme NVT courante.
SdifNameValueT* SdifNameValuesLGet
(SdifNameValuesLT *NameValuesL, char *Name)
Cette fonction permet de récupérer une Name-Value de
la liste des NVTs en passant le Name en argument.
Dans le cas ou Name est référencé dans plusieurs NVT, alors
c'est la première NVT le contenant qui sera prise en compte.
Le pointeur retourné est de type SdifNameValueT qui contient
deux champs: Name et Value.
SdifNameValueT* SdifNameValuesLGetCurrHT
(SdifNameValuesLT *NameValuesL, char *Name)
Cette fonction réalise aussi une requête en fonction de Name
mais uniquement dans la NVT courante.
Exemples:
{ SdifNameValueT *NV; /* adition de NVTs et de Name-Values dans chaque NVT */ /* first table */ SdifNameValuesLNewHT(SdifF->NameValues); SdifNameValuesLPut(SdifF->NameValues, "NameTable", "General"); /* second table */ SdifNameValuesLNewHT(SdifF->NameValues); SdifNameValuesLPut(SdifF->NameValues, "NameTable", "analyse"); SdifNameValuesLPut(SdifF->NameValues, "WindowSize", "512"); SdifNameValuesLPut(SdifF->NameValues, "SamplingRate", "32000.0"); /* third table */ SdifNameValuesLNewHT(SdifF->NameValues); SdifNameValuesLPut(SdifF->NameValues, "NameTable", "synthesis"); SdifNameValuesLPut(SdifF->NameValues, "NumberOfChannels", "2"); SdifNameValuesLPut(SdifF->NameValues, "EndTime", "1.0"); SdifNameValuesLPut(SdifF->NameValues, "SamplingRate", "44100.0"); /* Requêtes */ NV = SdifNameValuesLGet(SdifF->NameValues, "NameTable"); /* alors NV est ("NameTable", "General") */ NV = SdifNameValuesLGetFromCurrHT(SdifF->NameValues, "NameTable"); /* alors NV est ("NameTable", "synthesis") */ SdifNameValuesLSetCurrHT(SdifF->NameValues, 2); NV = SdifNameValuesLGetFromCurrHT(SdifF->NameValues, "NameTable"); /* alors NV est ("NameTable", "analyse") */ NV = SdifNameValuesLGet(SdifF->NameValues, "EndTime"); /* alors NV est ("EndTime", "1.0") */ }
SdifMatrixTypeT* SdifCreateMatrixType
(SdifSignature Signature, SdifMatrixTypeT *PredefinedMatrixType)
premet de créer un objet 'type de matrice'. Le premier argument est
la signature de ce type. Le second est l'objet 'type de matrice'
prédéfini dans SDIF.
Important: Tous les types de matrices ou de frames utilisés dans une instance de SdifFileT doivent être ajoutés aux tables de cette instance, de façon a créer le lien avec les types prédéfinis. L'hors de la lecture des entêtes avec les fonctions SdifFReadMatrixHeader et SdifFReadFrameHeader, cette mise à jour se fait automatiquement à l'aide des fonctions SdifTestMatrixType et SdifTestFrameType.
SdifMatrixTypeT* SdifTestMatrixType
(SdifFileT* SdifF, SdifSignature Signature)
Cette fonction vérifie si le type de matrice est répertorié
dans SdifF.
S'il ne l'est pas, alors elle vérifie si c'est un
type prédéfinis. S'il est prédéfini, elle crée le lien de
SdifF vers le type prédéfini. Sinon, elle envoie un message
sur l'erreur standart.
SdifMatrixTypeT* SdifMatrixTypeInsertTailColumnDef
(SdifMatrixTypeT *MatrixType, char *NameCD)
permet d'ajouter une colonne à un type (toujours la dernière colonne).
void SdifPutMatrixType
(SdifHashTableT *MatrixTypesTable, SdifMatrixTypeT* MatrixType)
permet d'ajouter un type de matrice dans une table.
SdifUInt4 SdifMatrixTypeGetNumColumnDef
(SdifMatrixTypeT *MatrixType, char *NameCD)
renvoie la position de la colonne de nom NameCD.
(0 si elle n'existe pas)
SdifColumnDefT* SdifMatrixTypeGetColumnDef
(SdifMatrixTypeT *MatrixType, char *NameCD)
renvoie la définition de la colonne (numéro, nom) en fonction du
nom.(NULL si introuvable)
SdifColumnDefT* SdifMatrixTypeGetNthColumnDef
(SdifMatrixTypeT *MatrixType, SdifUInt4 NumCD)
renvoie la définition de la colonne (numéro, nom) en fonction du
numero.(NULL si introuvable)
SdifMatrixTypeT* SdifGetMatrixType
(SdifHashTableT *MatrixTypesTable, SdifSignature Signature)
renvoie le type de matrice en fonction de la Signature. Renvoie NULL
si le type est introuvable. Attention, si Signature est la signature
d'un type prédéfini, SdifGetMatrixType(SdifF->MatrixTypeTable,Signature)
renvoie NULL si le lien avec entre SdifF et gSdifPredefinedType
n'a pas été mis à jour.
Exemple: On souhaite complèter le type de matrice des FOFs par une nouvelle colonne appelée NewCol et ensuite créer un type exclusif.
{ SdifMatrixTypeT *MtrxTFOF, *NewMtrxT; /* Mise à jour du lien sur le type prédéfini '1FOF' si nécessaire*/ MtrxTFOF = SdifTestMatrixType(SdifF, '1FOF'); /* Maintenant le type de matrice '1FOF' est directement accessible par SdifF et * non uniquement par gSdifPredefinedTypes. */ /* ajout d'une nouvelle colonne (en complétion) */ if (MtrxTFOF) SdifMatrixTypeInsertTailColumnDef(MtrxTFOF, "NewCol"); else ; /* un message d'erreur a été dans ce cas envoyer par SdifTestMatrixType*/ /* Création d'un type exclusif (le premier caractère de la signature doit donc * être 'E') */ NewMtrxT = SdifCreateMatrixType('ENMT', NULL); /* il n'y a pas de type prédéfini pour 'ENMT' donc le deuxième argument est NULL */ SdifPutMatrixType (SdifF->MatrxTypesTable, NewMtrxT); /* ajout à la base */ /* ajout des colonnes */ SdifMatrixTypeInsertTailColumnDef(NewMtrxT, "Col1"); SdifMatrixTypeInsertTailColumnDef(NewMtrxT, "Col2"); SdifMatrixTypeInsertTailColumnDef(NewMtrxT, "Col3"); SdifMatrixTypeInsertTailColumnDef(NewMtrxT, "Col4"); }
Les opérations sur les types de frames sont similaires dans leur fonctionnement à celle des types de matrices.
SdifFrameTypeT* SdifCreateFrameType
(SdifSignature FrameSignature, SdifFrameTypeT *PredefinedFrameType)
SdifFrameTypeT* SdifTestFrameType
(SdifFileT* SdifF, SdifSignature FrameSignature)
SdifFrameTypeT* SdifFrameTypeInsertTailComponent
(SdifHashTableT *MatrixTypesTable, SdifFrameTypeT *FrameType,
SdifSignature MatrixSignature, char *NameC)
void SdifPutFrameType
(SdifHashTableT *FrameTypesTable, SdifFrameTypeT *FrameType)
SdifUInt4 SdifFrameTypeGetNumComponent
(SdifFrameTypeT *FrameType, char *NameCD)
SdifComponentT* SdifFrameTypeGetComponent
(SdifFrameTypeT *FrameType, char *NameCD)
SdifComponentT* SdifFrameTypeGetNthComponent
(SdifFrameTypeT *FrameType, SdifUInt4 NumC)
SdifFrameTypeT* SdifGetFrameType
(SdifHashTableT *FrameTypesTable, SdifSignature FrameSiganture)
Il n'y a pas encore de fonctions de haut niveau pour remplir et interroger la table des StreamID (StreamIDsTable).
SdifStreamIDT* SdifCreateStreamID
(SdifUInt4 NumID, char *Source, char *TreeWay)
permet de créer un pointeur sur un objet de type StreamIDT.
Exemple:
/* dans le cas d'un TreeWay pour champ (non fichier)*/ void ConsOneStreamID(SdifFileT *SdifF, int NumID, char *PatchType, int NumPatch, char *ObjType, int NumObj, int NbSubObj, float StartTime, float EndTime) { SdifStreamIDT* StreamID; char TreeWay[512]; sprintf(TreeWay, "%s/%d/%s/%d/%d/%s/%f", PatchType, NumPatch, ObjType, NumObj, NbSubObj, StartTime, EndTime); StreamID = SdifCreateStreamID(NumID, "Chant", TreeWay); SdifHashTablePut(SdifF->StreamIDsTable, &(StreamID->NumID), 1, StreamID); } /*pour recuperer un StreamID il faut utiliser la fonction SdifHashTableGet*/ { SdifStreamIDT* StreamID; StreamID = (SdifStreamIDT*) SdifHashTableGet (SdifF->StreamIDsTable, &NumID, 0); /* le troisième argument n'est pas utilisé, car la table est indexée directement par des entiers (création de la table avec l'option eInt4). */ }
SdifFrameHeaderT* SdifFSetCurrFrameHeader
(SdifFileT *SdifF, SdifSignature Signature, SdifUInt4 Size,
SdifUInt4 NbMatrix, SdifUInt4 NumID, SdifFloat8 Time)
permet de donner des valeurs à chaque champ de l'entête de frame
temporaire de SdifF.
Exemple: SdifSetCurrFrameHeader(SdifF, '1FOB', 3, NumID, 1.0);
SdifMatrixHeaderT* SdifFSetCurrMatrixHeader
(SdifFileT *SdifF, SdifSignature Signature,
SdifDataTypeET DataType, SdifUInt4 NbRow, SdifUInt4 NbCol)
permet de donner des valeurs à chaque champ de l'entête de matice
temporaire de SdifF.
Exemple: SdifSetCurrMatrixHeader(SdifF, '1FOF', eFloat4, NbFofs, 7);
SdifOneRowT* SdifFSetCurrOneRow
(SdifFileT *SdifF, void *Values)
recopie la mémoire pointée par Values en fonction de l'entête de matrice
courante.
Exemple:
#define NbCols = 10; { float t[NbCols] = { 1., 2., 3., 4., 5., 6., 7., 8., 9., 0.}; SdifSetCurrMatrixHeader(SdifF, 'mtrx', eFloat4, 1, NbCols); SdifSetCurrOneRow (SdifF, (void*) t); }On connait la taille de la mémoire à recopier par le type de donnée (ici: eFloat4) et le nombre de colonnes (ici: NbCols). Il faut que le type de donnée de la matrice courante corresponde avec la taille d'un élément de t. Si t est composé de float sur 4 bytes, alors on doit avoir eFloat4. Si t est composé de double float sur 8 bytes, alors c'est eFloat8.
SdifOneRowT* SdifFSetCurrOneRowCol
(SdifFileT *SdifF, SdifUInt4 numCol, SdifFloat8 Value)
permet de donner la valeur Value dans la ligbe de matrice temporaire
de SdifF à la colonne numCol (0
SdifFloat8 SdifFCurrOneRowCol
(SdifFileT *SdifF, SdifUInt4 numCol)
recupère la valeur stockée à la colonne numCol de la ligne temporaire.
C'est un SdifFloat8 donc un double!!
SdifFloat8 SdifFCurrOneRowColName
(SdifFileT *SdifF, SdifMatrixTypeT *MatrixType, char *NameCD)
idem que la fonction précédente mais en utilisant le type de la matrice
et le nom de la colonne.
SdifSignature SdifFCurrSignature (SdifFileT *SdifF)
renvoie la signature temporaire de Chunk ou de Frame.
SdifSignature SdifFCleanCurrSignature (SdifFileT *SdifF)
met à 0 tous les bits de la signature temporaire.
SdifSignature SdifFCurrFrameSignature (SdifFileT *SdifF)
renvoie la signature temporaire du dernier Frame lu ou du
prochain à écrire.
SdifSignature SdifFCurrMatrixSignature (SdifFileT *SdifF)
renvoie la signature temporaire de la dernier matrice lue ou de
la prochaine à écrire.
SdifOneRowT* SdifFCurrOneRow (SdifFileT *SdifF)
renvoie la ligne temporaire de SdifF.
SdifUInt4 SdifFCurrNbCol (SdifFileT *SdifF)
renvoie SdifF->CurrMtrx->NbCol, nombre de colonnes
de la matrice en cours de traitement.
SdifUInt4 SdifFCurrNbRow (SdifFileT *SdifF)
renvoie SdifF->CurrMtrx->NbRow, nombre de lignes
de la matrice en cours de traitement.
SdifUInt4 SdifFCurrNbMatrix (SdifFileT *SdifF)
renvoie SdifF->CurrFramH->NbMatrix, mombre de matrices
du frame courant.
SdifUInt4 SdifFCurrID (SdifFileT *SdifF)
renvoie SdifF->CurrFramH->NumID, index de l'objet
du frame courant.
SdifFloat8 SdifFCurrTime (SdifFileT *SdifF)
renvoie SdifF->CurrFramH->Time.
size_t SdifFWriteGeneralHeader (SdifFileT *SdifF)
écrit sur le fichier 'SDIF' puis 4 bytes à 0.
size_t SdifFWriteAllASCIIChunks (SdifFileT *SdifF)
écrit tous les chunks ASCII. C'est à dire: les tables de names values,
les types créés ou complétés, et les Stream ID. Il faut donc au
préalable avoir rempli complétement les tables avant de la
lancer. Cette fonction de peut donc pas être executer une 2nd fois
durant une écriture.
size_t SdifFWriteMatrixHeader (SdifFileT *SdifF)
Après avoir donner une valeur à chaque champ de SdifF->CurrMtrxH gràce
à la fonction SdifFSetCurrMatrixHeader, SdifFWriteMatrixHeader écrit
toute l'entête de la matrice. Cette fonction réalise aussi une mise à
jour de SdifF->CurrOneRow, tant au niveau de l'allocation mémoire que
du type de données.
size_t SdifFWriteOneRow (SdifFileT *SdifF)
Après avoir donner les valeurs à chaque case de SdifF->CurrOneRow à
l'aide de SdifFSetCurrOneRow ou de SdifFSetCurrOneRowCol (suivant que
l'on possède déjà un tableau flottant ou respectivement une méthode
pour retrouver une valeur de colonne), SdifFWriteOneRow écrit 1 ligne
de matrice suivant les paramètres de SdifF->CurrMtrxH.
size_t SdifFWriteFrameHeader (SdifFileT *SdifF)
Après avoir donner une valueur à chaque champ de SdifF->CurrFramH
gràce à la fonction SdifFSetCurrFrameHeader, SdifFWriteFrameHeader
écrit toute l'entête de frame. Lorsque la taille est inconnue au
moment de l'écriture, donner la valeur _SdifUnknownSize. Ensuite,
compter le nombre de bytes écrit dans le frame et réaliser un
SdifUpdateChunkSize avec la taille
calculée.
size_t SdifFWritePadding (SdifFileT *SdifF, size_t Padding)
Cette fonction permet en fin d'écriture de matrice d'ajouter le
Padding nécessaire. Il faut cependant avoir la taille de ce
Padding. On utilise SdifFPaddingCalculate(SdifF->Stream,
SizeSinceAlignement) où SizeSinceAllignement est un
size_t
désignant le nombre de bytes qui sépare la
position actuelle d'écriture avec une position connue où le fichier
est aligné sur 64 bits (en général, c'est la taille de la matrice en
cours d'écriture: NbRow*NbCol*DatWitdh).
void SdifUpdateChunkSize (SdifFileT *SdifF, size_t ChunkSize)
execute un retour fichier de ChunkSize bytes et l'écrit, donc on
écrase la taille du chunk ou du frame. Dans le cas où le fichier est
stderr ou stdout, l'action n'est pas réalisée.
/* L'exemple suivant essaye de montrer l'ordonnancement des appels de fonction. Biensûr ce code devrait être plus modulaire. En effet, il devrait y avoir une fonction par niveau structurel d'écriture: une(plus) fonction(s) d'écriture de matrice, une(plus fonction(s) d'écriture de frame... */ #include "sdif.h" void main(void) { SdifFileT *SdifF; SdifUInt4 NbMatrix = 3; SdifUInt4 NumID = 0; SdifFloat8 Time = 0.0; SdifFloat4 TabValue[] = {1,2,3,4,5,6,7}; SdifFloat4 *pTabValue; size_t SizeFrameW; size_t SizeMatrixW; pTabValue = TabValue; /* pour permettre le cast par pointeur */ SdifGenInit("SdifTypes.STYP"); SdifF = SdifOpenFile("NewFile.sdif", eWriteFile); /* remplir les tables NameValues, MatrixTypesTable, * FrameTypesTable et StreamIDsTable. */ [ ..... ] /* écriture de l'entête */ SdifFWriteGeneralHeader (SdifF); /* écriture des chunks ASCII */ SdifFWriteAllASCIIChunks (SdifF) /****FRAME HEADER*****/ /* Mise à jour le l'entête de frame à écrire */ SdifSetCurrFrameHeader (SdifF, '1FOB', _SdifUnknownSize, NbMatrix, NumID, Time); /* écriture de l'entête de frame */ SizeFrameW = SdifFWriteFrameHeader (SdifF); /****FIRST MATRIX***/ /* Mise à jour le l'entête de matrice à écrire : 1 ligne, 1 colonne*/ SdifSetCurrMatrixHeader (SdifF, '1FQ0', eFloat4, 1, 1); /* écriture de l'entête de frame */ SizeMatrixW = SdifFWriteMatrixHeader (SdifF); /* Mise à jour de la ligne-buffer de SdifF * La largeur des données est conservée par le eFloat4 de l'entête de matrice*/ SdifSetCurrOneRow (SdifF, (void*) pTabValue); /* écriture de la ligne */ SizeMatrixW += SdifFWriteOneRow (SdifF); /* Si on a d'autres lignes à écrire alors * on répette SdifSetCurrOneRow et SizeMatrixW += SdifFWriteOneRow... */ /* écriture du Padding en fin de matrice et ajout de la taille de la matrice écrite * à la taile du frame. */ SizeMatrixW += SdifFWritePadding(SdifF, SdifFPaddingCalculate(SdifF->Stream, SizeMatrixW)) SizeFrameW += SizeMatrixW; /** MATRIX 2 & 3 **/ [. 2 matrices à écrire . .] /* pas de padding en fin de frame car on est déjà aligné */ /* la taille écrite ne doit pas compter la signature et la taille===> -8 */ SizeFrameW -= 8; SdifFUpdateChunkSize(SdifF, SizeFrameW); SdifCloseFile(SdifF); SdifGenKill(); }
Remarque: En lecture, on a toujours une avance sur la signature des chunks ou des frames. Ceci permet d'orientée la lecture suivant le type de données: chunk ou frame.
int SdifFGetSignature (SdifFileT *SdifF, size_t *NbCharRead)
lit 4 bytes, les considère comme une signature qui est placée dans
SdifF->CurrSignature, incrémente NbCharRead du nombre de bytes lus et
renvoie le dernier caractère lu convert en int (-1 si erreur).
size_t SdifFReadGeneralHeader (SdifFileT *SdifF)
lit l'entête du fichier, c'est à dire 'SDIF' puis 4 bytes. affiche un
message en cas de non reconnaissance du format.
size_t SdifFReadAllASCIIChunks (SdifFileT *SdifF)
Cette fonction permet de lire tous les Chunk ASCII qui se trouveraient
en début de fichier juste après l'entête générale. Elle s'arrête
lorsqu'elle ne reconnaît pas la signature de chunk comme un ASCII
Chunk. Cette signature est donc normalement celle d'un frame. Elle est
stockée dans SdifF->CurrSignature.
size_t SdifFReadMatrixHeader (SdifFileT *SdifF)
Cette fonction lit une entête de matrice signature
incluse. Elle vérifie le type de matrice, le champ
DataType. Toute les données se trouvent stockées dans
SdifF->CurrMtrxH. La plupart de ses champs sont directement accessible
par les fonctions indépendantes du mode d'ouverture du fichier.
Elle effectue une mise à jour de l'allocation mémoire de
SdifF->CurrOneRow en fonction des paramètres de l'entête de
matrice. Ainsi, on est normalement près pour lire chaque
ligne de la matrice courrante.
size_t SdifFReadOneRow (SdifFileT *SdifF)
Cette fonction permet de lire 1 ligne de matrice. Les données lues
sont stockées dans SdifF->CurrOneRow (jusqu'à une prochaine lecture
d'entête de matrice qui réinitialise ses paramètres).
size_t SdifFReadFrameHeader (SdifFileT *SdifF)
Cette fonction lit l'entête d'un frame à partir de la taille et
jusqu'au temps. Donc elle ne lit pas la signature
mais donne à SdifF->CurrFramH->Signature la valeur de
SdifF->CurrSignature. La lecture doit se faire avant, avec
SdifFGetSignature.
size_t SdifSkipMatrix (SdifFileT *SdifF)
Cette fonction permet de passer une matrice toute entière entête
incluse. Elle est utile lorsque qu'un frame contient plus de matrices
que le programme lecteur n'en connaît. Il peut ainsi les passer pour
retomber sur un autre frame.
size_t SdifSkipMatrixData (SdifFileT *SdifF)
Cette fonction permet de passer une matrice mais après la lecture de
l'entête. On s'en sert lorsque le type de matrice est mauvais,
inconnu, non interprétable par le programme lecteur.
size_t SdifSkipFrameData (SdifFileT *SdifF)
Cette fonction à le même sens que SdifSkipMatrixData mais pour les
frames. Il faut donc pour l'utiliser avoir au préalable lu la
signature et l'entête.
size_t SdifFReadPadding (SdifFileT *SdifF, size_t Padding)
Cette fonction permet de lire le Padding en fin de matrice.
l'utilisation classique de cette fonctin est:
SizeR = SdifFReadPadding(SdifF,
SdifFPaddingCalculate(SdifF->Stream, SizeR));
où SizeR est la taille en bytes lue depuis le début de la matrice,
c'est à dire NbRow*NbCol*DataWith. En réalité, pour que
SdifFPaddingCalculate fonctionne, il est seulement nécessaire que
SizeR soit le nombre de bytes qui s'épare la position actuelle dans le
fichier et un byte, repère d'allignement sur 64 bits.
La librairie possède deux fonctions permettant de faire des conversions de fichiers SDIF binaire vers du texte ou l'inverse.
size_t SdifTextToSdif (SdifFileT *SdifF, char *TextStreamName)
converti un fichier SDIF ouvert en lecture (eReadFile) en un fichier
texte pseudo-SDIF de nom TextStreamName.
size_t SdifToText (SdifFileT *SdifF, char *TextStreamName)
converti un fichier texte pseudo-SDIF de nom TextStreamName en un
fichier SDIF binaire de non SdifF->Name. Le fichier doit avoir été
ouvert en écriture (eWriteFile).
La structure d'un fichier texte pseudo-SDIF est identique à celle des fichier binaire. Les différences sont que:
Dans cette exemple, sont représentés les possibilités des fichier pseudo-SDIF. On y trouve 2 NVTs placées au début. Ensuite, on a un chunk de déclaration de types, où le type de matrice '1CHA' est complèté pour avoir 6 cannaux, un type de matrice et un de frame sont créés en mode exclusif. Ensuite on a un chunk de déclaration d'objet, le premier StreamID rappelle la grammaire d'un StreamID, le second est un StreamID pour Chant et le troisième est un StreamID d'un autre type. Enfin, on a 2 frames qui portent sur les objets déclarés.
SDIF 1NVT { NameTable General; SdifTextAuthor Dupont; Date 15/JAN/1998; } 1NVT { NameTable Synthese; SamplingRate 44100. ; EndTime 5.00; ChantMaxNbSubObjs 5; } 1TYP { 1MTD 1CHA {Channel5, Channel6} 1MTD ENMT {a, b, c} 1FTD ENFT { 1FOF Formants; ENMT UntitledMatrix; } } 1IDS { 0 TypeDeTreeWay:TreeWay; 1 Chant:Patch0/1/FOB/1/5/0./5.; 2 ProgA:A/B/C/D/ENFT/1./5.; } SDFC 1FOB 2 1 0. 1FQ0 32 1 1 110. 1FOF 32 5 7 650. 1 80. 0.002 0.05 0.004 0. 1080. 0.5012 90. 0.002 0.05 0.004 0. 2650. 0.4467 120. 0.002 0.05 0.004 0. 2900. 0.3982 130. 0.002 0.05 0.004 0. 3250. 0.0795 140. 0.002 0.05 0.004 0. 1CHA 32 5 6 1. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0. 1. 0. 0. 1. 0. 0. 1. 0. 0. 0. 1. 0. 1. 0. 0. 0. 0. 1. 1. ENFT 2 2 1. 1FOF 32 5 7 400. 1. 40. 0.002 0.05 0.004 0. 800. 0.3163 80. 0.002 0.05 0.004 0. 2600. 0.2512 100. 0.002 0.05 0.004 0. 2800. 0.2512 120. 0.002 0.05 0.004 0. 3000. 0.0501 120. 0.002 0.05 0.004 0. ENMT 32 4 3 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. ENDC ENDF
Pour convertir un fichier pseudo-SDIF en fichier binaire SDIF avec
l'utilitaire tosdif sous unix:
tosdif -i MyFoB.sdif.txt -o MyFoB.sdif