SFS Manual for Programmers

5. Subroutine Reference

5.1

Functional Reference

SFS FILE MANAGEMENT

RoutineDescription
getitem()locate and load SFS data set
putitem()store SFS data set into file
putNitems()store multiple SFS data sets to a file
sfsbase()get SFS base directory
sfsbuffer()allocate buffer area for SFS data
sfschannel()open output channel to SFS data file
sfsclose()close SFS data file descriptor
sfsdup()duplicate SFS data file identifier
sfsfile()search for SFS data file
sfsitem()locate item in SFS data file
sfsnextitem()locate next item in SFS data file
sfsopen()open a SFS data file
sfsread()read SFS data into buffer
sfsupdate()add a new data set to a SFS file
sfswrite()write data to SFS data file
sfswritelink()write a link item to a SFS data file

SFS DATA SETS

RoutineDescription
histmatch()match string expression against item history
itspec()decode item specification
labelsitem text labelling routines
param(), params()decode entries in history and parameter strings
sfsheader()initialise SFS data set header

OPERATIONAL MESSAGES

RoutineDescription
error()report error message and terminate process
ttytest()test if process connected to foreground terminal
videoterminal-independent text enhancement routines

MISCELLANEOUS

RoutineDescription
getline()read a line from standard input
pathname()get full pathname of file
playbackreplay waveform through DAC routines

5.2

SFS3 Routine Reference

ERROR() - REPORT ERROR MESSAGE AND TERMINATE PROCESS

    extern char *progname;

    void     error(format,param,param,..)
    char     *format;            /* printf format string */
    args     param,..;           /* parameters */

error() prints a message to to the standard error and then terminates the current process using exit(2) with a value of 1. The message is prefixed with 'sfs:' or the contents of the global variable progname if declared. The text of the message is made up from format and the supplied params, with format containing the 'printf' style format for the message, and params containing the arguments.

error() also deletes any temporary files created with sfschannel(SFS3)

Example:

#define PROGNAME "yourprog"
char    *progname=PROGNAME;
:
error("cannot open file '%s', code %d",filename,errno);
:
error("process fails");

GETITEM() - LOCATE AND LOAD SFS DATA SET

    #include "sfs.h"

    void      getitem(filename,it,ty,item,buff)
    char      *filename;  /* pathname of file */
    int       it;         /* item type */
    char      *ty;        /* item specifier */
    struct    item_header *item;    /* returned item header */
    char      **buff;     /* returned buffer address */

getitem() searches filename for a data set of type it and of subtype specification ty. If the data set is found, its item header is returned in item and the data is loaded into a dynamically-allocated buffer, the address of which is returned in buff. The equivalent code fragment is:

        fid = sfsopen(filename,"r",NULL);
        sfsitem(fid,it,ty,&item);
        buff = sfsbuffer(&item,item.numframes);
        sfsread(fid,0,item.numframes,buff);
        sfsclose(fid);

getitem() does not return on failure, instead it terminates the process with error(SFS3).

The buffer allocated by getitem() may be released with free(3).

GETLINE() - READ A LINE FROM STANDARD INPUT

    char        *getline(buff,len)
    char         *buff;            /* input buffer */
    int         len;               /* length of input buffer */

getline() is a routine to read a line of input from the standard input, and place it into buff. A maximum of len-1 characters are read in, and any remaining characters on the line and the terminating '\n' character are discarded.

getline() returns buff on success, and the NULL pointer on end-of-file.

HISTMATCH() - MATCH STRING EXPRESSION AGAINST ITEM HISTORY

    int     histmatch(exp,targ,ret0,ret1,...)
    char        *exp;     /* match expression */
    char        *targ;     /* target string */
    char        *ret0,*ret1,...     /* returned sub-strings */

histmatch() is a function to perform string matching on speech file histories as stored in item headers and processed using the label routines. It returns a code expressing a match between a match expression exp, and a target string (item history) targ. The code is '1' for success, '0' for failure, and '-1' for an error on the string expression.

The following string match characters are currently supported in exp:

?
Match any single character (except line start and line end).
*
Match zero or more characters (including line start and line end).
%0,%1,..,%9
Match a string of characters up to ';', ',', ')' and line end, and return the string in a function argument given after the target string. Thus '%0' will return a substring into variable ret0, etc. which should be of a large enough size. Matches are constrained to include equal numbers of open and close parentheses.
%%
Performs matching as for %0 without returning a string. Matches are constrained to include equal numbers of open and close parentheses.
any
Any other characters must match exactly. Escape special characters with '\'.

For example:

        char        param[16];

        histmatch("inwd(freq=%0)","inwd(freq=12800)",param);
        infreq = atoi(param);    /* equal to 12800 */

The parameter exp may contain a single match expression or a sequence of expressions separated by '\033' (ESCAPE) characters. Each expression in exp must match whole target string.

histmatch() returns at the first matching expression.

ITSPEC() - DECODE ITEM SPECIFICATION

    int itspec(string,type,match)
    char *string;     /* item type specification */
    int *type;        /* returned type */
    char **match;     /* returned subtype match */

An item specification is composed of two parts: an item datatype selector and an item subtype selector; the routine itspec() decodes an item specification into a datatype number and a subtype match string suitable for use with getitem() and sfsitem(). The datatype selector can be specified as a digit string or as a two-character mnemonic (SP, LX, etc: lower case is automatically converted). The subtype selector may take one of three forms:

.number
the number is taken to be the subtype number of the item - usually the occurrence count of the given type in the file.
^string, ^string^
the string is taken to be a direct history match on the item required. If no trailing '^' is present, a final '*' is assumed, if the match string ends in a '^', the expression must match the whole of the target expanded history. Matching facilities are described in histmatch(SFS3).
string
(datatype=mnemonic only) the entire specification (with the first two letters in capitals) is taken to be a label code. This code is looked up in the labels file(s) to return one or more history match strings which may be used to locate an item in the file. See labels(SFS5).

When the subtype part of the item specification is not present, itspec() returns suitable strings according to the entries in the summary table below:

Input StringExampleDatatypeSubtype Match String
<digit(s)>55"0"
<digit(s)>.5.5"*"
<digit(s)>.<digit(s)>5.035 "03"
<digit(s)>.^string5^pitch5 "pitch*"
<digit(s)>.^string^5^pitch^5 "pitch"
<mnemonic>LP6"0"
<mnemonic>.LP.6"*"
<mnemonic>.<digit(s)>LP.056 "05"
<mnemonic>^<string>LP^pitch6 "pitch*"
<mnemonic>^<string>^LP^pitch^6 "pitch"
<mnemonic><string>LPpitch6 "PSapply(*rules=pitch*)"
(found from labels file)

itspec() returns 0 on success, 1 on failure.

itspec() modifies its string argument when the subtype part of the specification is a history match. The pointer in ty points either to a component of string or to a dynamically allocated area.

LABELS - ITEM TEXT LABELLING ROUTINES

    char  *lab_store(item)  /* store/return expanded history */
    struct item_header *item;    /* item header */

    void    lab_reset()          /* reset expanded history database */

    void    lab_initfile(filename) /* initialise expanded history dbase. */
    char    *filename;             /* for this file */

    char    *lab_getmatch(code)   /* get history match from short code */
    char    *code;                /* short code */

    char    *lab_gettext(history) /* get text description */
    char    *history;             /* expanded history */

These routines provide a simple mechanism for accessing and describing data sets using short codes and textual descriptions rather than the more formal mechanisms of item numbering and item histories. The routines lab_getmatch() and lab_gettext() access a labels file where the mappings between short codes and history matches, and the mappings between history matches and text descriptions are kept, see labels(SFS5).

lab_store() adds an item history to an internal database of histories for the file. It returns the expanded history for the item, which is simply the item history but with all referred items (recursively) expanded. For example if the item list was:

 1.01  inwd
 2.01  inwd(freq=10000)
 3.01  tx(2.01)
12.01  fmanal(1.01,3.01)

then the expanded histories would be:

 1.01 inwd
 2.01 inwd(freq=10000)
 3.01 tx(inwd(freq=10000))
12.01 fmanal(inwd,tx(inwd(freq=10000)))

Notice that to expand the history for an item, lab_store() requires to be passed the histories of all earlier items in the file. The expanded histories can be obtained as the file is processed, or they can be set up for the whole file with a simple loop, like:

fid = sfsopen(filename,"r",NULL);
while (sfsnextitem(fid,&item)) lab_store(&item);

or with a call to the routine lab_initfile() (below).

lab_reset() resets the internal database of histories, so that another file can be processed within the same program.

lab_initfile() scans the items in the given file, and calls lab_store() for each item.

lab_getmatch() takes a short code specifying a type of data set and returns a string match expression that selects appropriate items on the basis of their expanded history. The string match expressions are stored in a labels file and expect to be used with the string match function histmatch(SFS3). lab_getmatch() returns NULL if the code cannot be found.

lab_gettext() takes an expanded item history and returns a text description of the item. The text descriptions are stored in the labels file, and the first text description is returned which matches the given history. The routine returns NULL if no text description can be found. For the structure of the labels file see labels(SFS5). Thus to obtain a text description of an arbitrary item, one could use the code:

char    *text;
/* : */
lab_reset();                /* if required */
lab_initfile(filename);        /* if file not scanned */
/* : */
if ((text = lab_gettext(lab_store(&item)))==NULL)
    printf("hist=%s\n",item.history)
else
    printf("text=%s\n",text);

The labels files searched by the label routines is determined by the environment variable SFSLABEL (multiple files separated by ':'). If SFSLABEL is not present, the default file: SFSBASE/data/labels is used.

PARAM() - DECODE NUMERIC ENTRY IN HISTORY AND PARAMETER STRINGS

double    param(string,parameter,default)
char      *string;        /* target string */
char      *parameter;     /* parameter to find */
double    default;        /* default value */

param() provides a convenient mechanism for extracting numeric parameter values from item histories and parameter lists. The routine is given the address of the string, the name of the parameter and a default value. If the routine finds the substring '<parameter>=' in string then it returns the floating point value of the following number. If the substring is not found, the default value is returned. If the substring '<parameter>' is found, the value 1.0 is returned. Valid parameter names begin with an alphabetic character. Valid separator characters are: ' ', ',', ';', '(', & ')'.

Example calls might be:

sampfreq = param(item.history,"freq",12800.0);

or

linkflag = param(item.history,"linked",0.0);

PARAMS() - DECODE STRING ENTRY IN HISTORY AND PARAMETER STRINGS

char    *params(string,parameter,default)
char    *string;       /* target string */
char    *parameter;    /* parameter to find */
char    *default;      /* default string */

params() provides a convenient mechanism for extracting string parameter values from item histories and parameter lists. The routine is given the address of the string, the name of the parameter and a default value. If the routine finds the substring '<parameter>=' in string then it returns the value string up to the next separator. If the substring is not found, the default string is returned. If the substring '<parameter>' is found, then that string is returned. Valid parameter names begin with an alphabetic character. Valid separator characters are: ',', ';', '(', & ')'.

An example call might be:

match = params(item.history,"type",NULL);

PATHNAME() - GET FULL PATHNAME OF FILE

char *pathname(name)
char  *name;      /* relative pathname of file */

pathname() is a subroutine to return the full pathname of file. For pathnames not beginning with '/', it concatenates name with the current working directory and eliminates strings such as './' and 'dir/..'. The routine returns a pointer to a static area.

PLAYBACK - REPLAY WAVEFORM THROUGH DAC

int      dac_open(devicename)
char     *devicename;        /* device selection
                                =NULL for default */
								   
int      dac_playback(buff,count,freq,nbits,nchan,nrep)
short    *buff;        /* waveform buffer */
int      count;        /* number samples */
double   freq;         /* sampling frequency */
int      nbits;        /* number of bits =12 or =16 */
int      nchan;        /* number of channels */
int      nrep;         /* number of repetitions */

void     dac_close(rapid)
int      rapid;        /* rapid close flag */

The SFS DAC routines support a number of audio systems. When SFS is built a number of supported devices are specified and included in SFS programs. At run-time the user selects one of the supported devices through the use of the environment variable 'DAC'.

The routine dac_open() determines the currently required device and attempts to open it. The routine dac_playback() replays a waveform from memory. The routine dac_close() closes the connection to the audio device.

PUTITEM() - STORE SFS DATA SET TO FILE

void     putitem(filename,item,numf,buff)
char     *filename;       /* pathname of file */
struct item_header *item; /* item header */
int      numf;            /* # frames to write */
char     *buff;           /* buffer address */

putitem() adds to an existing data file filename the data set described by item, numf and buff.

The equivalent code fragment is:

int ofid;
ofid=sfschannel(filename,&item);
sfswrite(ofid,numf,buff);
sfsupdate(filename);

If an error occurs, putitem() terminates the process with a call to error().

PUTNITEMS() - STORE MULTIPLE SFS DATA SETS TO A FILE

void    putNitems(filename,item,numf,buff,numitem)
char   *filename;         /* pathname of file */
struct item_header *item; /* item header */
int    numf;              /* # frames to write */
char   *buff;             /* buffer address */
int    numitem;           /* number of items */

putNitems() is a generalisation of putitem() for adding multiple items to a file. putNitems() stores the data sets passed in item, numf and buff in temporary files and only updates the existing data file filename the last time it is called. The parameter numitem should be used to specify the number of data sets.

Example use is:

#define NUMITEMS 3
:
putNitems(filename,&item1,numf1,data1,NUMITEMS);
:
putNitems(filename,&item2,numf2,data2,NUMITEMS);
:
putNitems(filename,&item3,numf3,data3,NUMITEMS);

There is an operational constraint on the number of simultaneous open files and hence the maximum number of items that can be stored simultaneously with putNitems().

SFSBASE() - GET SFS BASE DIRECTORY

char    *sfsbase()

sfsbase() returns a pointer to a static area containing the pathname of the base subdirectory for the SFS software. The default directory is built in to the software but may be overridden with the environment variable SFSBASE.

SFSBUFFER() - ALLOCATE BUFFER AREA FOR SFS DATA

#include "sfs.h"
char        *sfsbuffer(item,numf)
struct item_header *item; /* item header */
int         numf;         /* buffer size in frames */

sfsbuffer() creates a memory buffer to hold data frames in a suitable format for reading or writing data from/to a file with sfsread() and sfswrite() for any item type.

sfsbuffer() takes details about the item frame format from the item header, and the size of the buffer in frames (for framesize equal to 1, 1 frame = 1 sample). The buffers are constructed as arrays of the primitive data structure for the item: e.g. short sp[]; struct lp_rec lp[]; struct fm_rec fm[]; etc.

Note that creating a general output buffer for annotation items is inefficient since the maximum space must be allocated for each label, so you should consider using a (sfs) buffer of length 1, or creating an array of an_rec within your own program (and performing appropriate memory allocation for the labels).

SFSCHANNEL() - OPEN OUTPUT CHANNEL TO SFS DATA FILE

#include "sfs.h"
int    sfschannel(filename,item)
char    *filename;         /* speech file pathname */
struct item_header *item;  /* output item header */

sfschannel() opens an output file to hold data to be added to a speech file. The name of the speech file is used to create a temporary file in the same directory, and to associate an output item to a particular file. The item header should be created with sfsheader() and have the history and params fields initialised separately.

sfschannel() returns a file descriptor greater than 0 on success, and -1 on failure. File descriptors returned by sfschannel() are closed by sfsupdate().

SFSCLOSE() - CLOSE SFS DATA FILE DESCRIPTOR

int    sfsclose(fid)
int    fid;  /* file descriptor */

sfsclose() closes a file descriptor opened with sfsopen(). Note that there is a maximum number of files that may be opened simultaneously.

SFSDUP() - DUPLICATE SFS DATA FILE DESCRIPTOR

int    sfsdup(fid)
int    fid; /* file descriptor */

sfsdup() duplicates a file descriptor opened on a file using sfsopen(). This routine should be preferred to opening the file twice. The duplicate descriptor is positioned in the file identically to the original descriptor at the time sfsdup() was called.

SFSFILE() - SEARCH FOR SFS DATA FILE

char    *sfsfile(filename)
char    *filename; /* speech file pathname */

sfsfile() returns a pointer to a static area containing the full pathname of a speech file. The environment variable SFSPATH specifies a list of directories separated by ':'. These directories are searched in turn and if the given file is found, then the full pathname is returned. If the file is not found, the original filename is returned unchanged.

SFSITEM() - LOCATE ITEM IN SFS DATA FILE

#include "sfs.h"
int     sfsitem(fid,datatype,spec,item)
int     fid;      /* file descriptor */
int     datatype; /* generic data type */
char    *spec;    /* item specification */
struct item_header *item;  /* returned item header */

sfsitem() attempts to locate an item in a file opened with sfsopen() that meets the specification given by the variables datatype and spec. The variable datatype should contain the item 'datatype' code for the data set. The variable spec is a pointer to a string containing either the number of the data set expressed as a string (with '0' for last) or a string match expression that should be matched against the history fields of the items in the file of the type datatype. Thus if spec is "*", the first item of the given type is located. If datatype is given as 0, the routine locates the first item of any type in the file.

sfsitem() returns 1 on success and 0 on failure. If the item is found and item is not NULL, then the item header is returned.

SFSHEADER() - INITIALISE SFS DATA SET HEADER

#include "sfs.h"
int        sfsstruct[];

void    sfsheader(item,it,floating,datasize,framesize,frameduration,
                  offset,windowsize,overlap,lxsync)
struct item_header *item; /* item header */
int      datatype;        /* item type */
int      floating;        /* structured/integer/floating */
int      datasize;        /* datum size */
int      framesize;       /* frame size */
double   frameduration;   /* frame duration */
double   offset;          /* data set offset */
int      windowsize;      /* fixed frame window size */
int      overlap;         /* fixed frame overlap */
int      lxsync;          /* excitation synchronous flag */

sfsheader() should be used to initialise item headers for all new data sets. The entire item header is first cleared then the arguments are used to initialise appropriate fields. sfsheader() also adds machine-specific information to the header so that the exact format of floating point numbers etc, can be determined by sfsread(). Thus you should not use old item headers for new data, since these may have been created on a different machine.

SFSNEXTITEM() - LOCATE NEXT ITEM IN SFS DATA FILE

#include "sfs.h"
int        sfsnextitem(fid,item)
int        fid;            /* file descriptor */
struct item_header *item;  /* returned item header */

sfsnextitem() locates the next data set in a file opened with sfsopen(), and returns the item header if found.

If the item argument is supplied as NULL, sfsnextitem() rewinds to the top of the file. The next call with a valid item argument will return the first item header in the file.

sfsnextitem() returns 1 on success and 0 if there is no next data set.

SFSOPEN() - OPEN A SFS DATA FILE

#include "sfs.h"
int    sfsopen(filename,mode,head)
char   *filename; /* speech file pathname */
char   *mode;     /* access mode requested */
struct main_header *head;  /* returned main header */

sfsopen() attempts to open filename to check that it is a valid speech file. There are four supported operations requested as a string passed in mode:

rread main header into head, check file ok for reading, return file identifier.
wread main header into head, check file ok for updating, return file identifier.
hwrite main header from head, return success code.
ccreate new file using head, return success code.

For any operation, default action is performed if head is supplied as NULL.

sfsopen() returns the file identifier or 0 if the operation is successful. It returns -1 if the file does not exist, and -2 for any other error.

SFSREAD() - READ SFS DATA INTO BUFFER

#include "sfs.h"
int     sfsread(fid,start,numf,buff)
int     fid;    /* file descriptor */
int     start;  /* index of first frame */
int     numf;   /* number of frames to load */
char    *buff;  /* buffer address */

sfsread() loads the whole or part of a data set into memory once it has been located by sfsitem() or sfsnextitem(). The routine takes the file descriptor fid, the start index of the data in frames start, the number of frames to be loaded numf, and the address of a memory buffer in which to place the data buff. This buffer can be created with sfsbuffer().

sfsread() returns the number of frames actually loaded, or zero if there is a read error. Read access to unstructured and fixed-length structured items can be made in any frame order, read access to variable-length structured items (currently only annotations) must be made in serial order.

Foreign or linked data sets are automatically decoded by sfsread().

SFSUPDATE() - ADD A NEW DATA SET TO A SFS FILE

int    sfsupdate(filename)
char     *filename; /* speech file pathname */

sfsupdate() is the main routine for adding new data items to speech database files. Apart from a few special utility programs, all file update programs should use this routine to add data sets to the file. Once data has been stored using sfschannel() and sfswrite() this routine should be called to update the speech file.

sfsupdate() returns 1 on success and 0 on error. In either case, all temporary files created by sfschannel() for the given file are deleted.

sfsupdate() checks the contents of the new datasets against the contents of the datafile. It uses the criterion that two items are duplicated if their history fields are identical. If no duplicate items are found, the data sets are appended to the datafile. If duplicate items are found, the file is restructured. If the duplicate datafile item has not been subsequently processed it is deleted. If the duplicate item has been used as input to a subsequent item, it is 'truncated' to its item header only (and with its datatype field negated). In all cases the subtype fields of the new items are automatically given numbers according to their position in the file.

SFSWRITE() - WRITE DATA TO SFS DATA FILE

#include "sfs.h"
int    sfswrite(fid,numf,buff)
int    fid;   /* output file descriptor */
int    numf;  /* number of frames to write */
char   *buff; /* buffer address */

sfswrite() should be used to write new information to the output channel opened by sfschannel(). The routine takes the file descriptor provided by sfschannel() fid, the number of frames to be written numf, and a pointer to the buffer where the data is held buff. Note that the buffer should be created with sfsbuffer(), or should be constructed using the same conventions.

sfswrite() automatically updates the numframes and length fields in the item header associated with the channel.

sfswrite() returns the number of frames written on success and 0 on failure.

SFSWRITELINK() - WRITE A LINK ITEM TO A SFS DATA FILE

int    sfswritelink(item,numf,link,filename)
struct item_header  *item;     /* output item header */
long                numf;      /* number of frames linked */
struct link_header  *link;     /* output link header */
char                *filename; /* output file name */

sfswritelink() opens an output channel on the given file using the supplied item header. It then writes the link header as data down the channel. When the program later calls sfsupdate() the item header and link headers are written to the output file with the appropriate settings for the numframes and datapresent fields in the item header.

TTYTEST() - TEST IF PROCESS CONNECTED TO FOREGROUND TERMINAL

int    ttytest()

ttytest() is a routine to check if it is sensible to report messages to the standard output. It returns 1 if the process is connected to a terminal and is running in the foreground, and 0 otherwise.

VIDEO - TERMINAL-INDEPENDENT TEXT ENHANCEMENT ROUTINES

void    initvideo(flag);
int    flag;

void   italicon();
void   italicoff();
void   boldon();
void   boldoff();
void   uparrow();

initvideo() is an optional routine that may be used to enforce the generation of terminal codes even if the process is not connected to a terminal. If flag is set then the following routines always produce codes. Default action is only to send codes if the process is talking to a terminal, in which case this routine need not be called.

italicon() sends appropriate codes to the terminal to turn italics (or underlining) on.

italicoff() sends appropriate codes to the terminal to turn italics (or underlining) off.

boldon() sends appropriate codes to the terminal to turn bold (or reverse video) on.

boldoff() sends appropriate codes to the terminal to turn bold (or reverse video) off.

uparrow() sends appropriate codes to the terminal to move the cursor up one line.


© 2000 Mark Huckvale University College London