IRCAM SDIF Library Tutorial

Diemo Schwarz

August 27, 2000




1   Introduction

This tutorial describes the standard way to read and write an SDIF file using the Ircam SDIF Library. Only rudimentary error checking is done. However, the reading program uses the SDIF selection (see this ICMC article) to show you how easy it is to incorporate powerful selection capabilities into your programs.

To use the sdif library, include the definitions with

#include <sdif.h>
and link with the SDIF library using -lsdif.

SDIF signatures are the 4 characters that identify a frame or matrix type. To create and read them, use:

SdifSignature mysig  = SdifSignatureConst ('1FQ0');
char*         sigstr = SdifSignatureToString (mysig);
A little note on the naming convention of SDIF funtions: All functions starting with SdifF... work on an open SDIF file. They all take an SdifFileT * as first argument.


2   Initialisation

The library is initialised by calling

SdifGenInit ("");
giving an optional .styp file with description of type definitions. An empty string "" means take the file at the standard place, or use the file given by the environment variable SDIFTYPES, if it exists.

To deinitialise and clean up, call:

SdifGenKill ();



3   Reading


size_t  bytesread = 0;
int	eof       = 0;	/* End-of-file flag */

	
/* Open file for reading and parse selection. (See Utilities for selection syntax.) */
SdifFileT *file = SdifFOpen ("filename.sdif::selection", eReadFile); SdifFReadGeneralHeader (file); /* Read file header */ SdifFReadAllASCIIChunks (file); /* Read ASCII header info, such as name-value tables */
/* Read all frames matching the file selection. */
while (!eof && SdifFLastError (file) == NULL) { bytesread += SdifFReadFrameHeader(file); /* search for a frame we're interested in */ while (!SdifFCurrFrameIsSelected (file) || SdifFCurrSignature (file) != mysig) { SdifFSkipFrameData (file); if ((eof = SdifFGetSignature(file, &bytesread) == eEof)) break; /* eof */ bytesread += SdifFReadFrameHeader(file); } if (!eof) { /* Access frame header information */ SdifFloat8 time = SdifFCurrTime (file); SdifSignature sig = SdifFCurrFrameSignature (file); SdifUInt4 streamid = SdifFCurrID (file); SdifUInt4 nmatrix = SdifFCurrNbMatrix (file); int m; /* Read all matrices in this frame matching the selection. */ for (m = 0; m < nmatrix; m++) { bytesread += SdifFReadMatrixHeader (file); if (SdifFCurrMatrixIsSelected (file)) { /* Access matrix header information */ SdifSignature sig = SdifFCurrMatrixSignature (file); SdifInt4 nrows = SdifFCurrNbRow (file); SdifInt4 ncols = SdifFCurrNbCol (file); SdifDataTypeET type = SdifFCurrDataType (file); int row, col; SdifFloat8 value; for (row = 0; row < nrows; row++) { bytesread += SdifFReadOneRow (file); for (col = 1; col <= ncols; col++) { /* Access value by value... */ value = SdifFCurrOneRowCol (file, col); /* Do something with the data... */ } } } else { bytesread += SdifFSkipMatrixData(file); } bytesread += SdifFReadPadding(file, SdifFPaddingCalculate(file->Stream, bytesread)); } /* read next signature */ eof = SdifFGetSignature(file, &bytesread) == eEof; } } if (SdifFLastError (file)) /* Check for errors */ { exit (1); } SdifFClose (file);



4   Writing

SdifFileT *file = SdifFOpen("filename.sdif", eWriteFile);  /* Open file for writing */
/* Here, you could add some text data to the name-value tables */
SdifFWriteGeneralHeader  (file);    /* Write file header information */
SdifFWriteAllASCIIChunks (file);    /* Write ASCII header information */

	
/* Writing can be done in different flavours: For the common case of a frame with one matrix, use: */
SdifFWriteFrameAndOneMatrix (file, mysig, mystream, mytime, /* frame header */ mysig, eFloat4, nrows, ncols, data); /* matrix */
/* If you have one or more matrices ready in row-major order, use: */
SdifUInt4 framesize = SdifSizeOfFrameHeader () + SdifSizeOfMatrix (eFloat4, nrows, ncols); /* as many as you like... */ SdifFSetCurrFrameHeader (file, mysig, framesize, 1, mystream, mytime); SdifFWriteFrameHeader (file); SdifFWriteMatrix (file, mysig, eFloat4, nrows, ncols, data);
/* If you want to calculate your data on-the-fly, you can write it the nitty-gritty way: */
SdifUInt4 SizeFrameW = 0; SdifFSetCurrFrameHeader (file, mysig, _SdifUnknownSize, nmatrix, mystream, mytime); SizeFrameW += SdifFWriteFrameHeader (file); /* Write matrix header */ SdifFSetCurrMatrixHeader (file, mysig, eFloat4, nrows, ncols); SizeFrameW += SdifFWriteMatrixHeader (file); /* Write matrix data */ for (row = 0; row < nrows; row++) { for (col = 1; col <= ncols; col++) { SdifFSetCurrOneRowCol (file, col, value); } SizeFrameW += SdifFWriteOneRow (file); } /* Write matrix padding */ SizeFrameW += SdifFWritePadding (file, SdifFPaddingCalculate (file->Stream, SizeFrameW)); SdifUpdateChunkSize (file, SizeFrameW - 8); /* Set frame size */ SdifFClose (file);



5   Goodies

Some functions to make life with SDIF even easier:

	
/* Check if the file exists and is a good SDIF file */
if (SdifCheckFileFormat ("filename.sdif")) /* ok */;
/* Check if file is good, exists, and contains certain frame types */
SdifSignature wanted [] = { SdifSignatureConst('1TRC'), SdifSignatureConst('1HRM'), eEmptySignature /* end marker */ }, firstfound; int firstindex; /* This returns the signature of the first wanted frame found */ firstfound = SdifCheckFileFramesTab ("filename.sdif", wanted); printf ("First sig found is: %s\n", firstfound ? SdifSignatureToString(firstfound) : "none of interest"); /* Alternatively, you can get the index of the first frame found */ firstindex = SdifCheckFileFramesIndex ("filename.sdif", wanted); printf ("First sig found is: %s\n", firstindex >= 0 ? SdifSignatureToString(wanted [firstindex]) : "none of interest");
N.B.: All of the above functions require a real file, and do not work with standard input.


This document was translated from LATEX by HEVEA.