# IRCAM SDIF Library Tutorial

### Diemo Schwarz

### October 26, 2001

## 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);
    	    }

    	    /* Read matrix-padding to assure 8 byte alignment.
    		      (Frames are then automatically aligned.) */
    	    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.