# SDIF

# Format Specification

Analyse/Synthèse

Dominique Virolle

- General SDIF Concept

- Matrices
- Frames
- Temporal Concept
- Special Frames
- BigEndian

- The Format

- File Header
- Frame

- Frame Header
- Frame Data

- Matrix

- Matrix Header
- Matrix Data

- Example of Frame in text
- Special Frames Specifications

- Informations Table

- Informations Table Header
- Informations Table Data
- Padding

- Types Declaration

- Types Declaration Header
- Types Declaration Data

- Matrix Type
- Frame Type
- Types Declaration Grammar

- Stream IDs Table

- Stream IDs Table Header
- Stream IDs Table Data

- SDIF Reserved Words

- Information Table Words
- Predefined Types

- Predefined Matrix Types
- Predefined Frame Types

- StreamID TreeWay for the Chant program

- Description of each element of TreeWay
- Example TreeWay for the Chant program

# General SDIF Concept

- Matrices
- Frames
- Temporal Concept
- Special Frames
- BigEndian

The general idea of SDIF is to store information related to signal processing and specifically of sound, in files, according to a common format to all data types. Thus, it is possible to store results or parameters of analyses, syntheses...

## Matrices

In first, the data storage is in the form of matrices where each column represents a field of structure, and each row an element of this structure. A structure which one can represent in the form of matrix is called "simple" in this document.

Thus, for a structure "FilterStruct", made up of three fields "frequency", "amplitude", and "bandwidth", elements of "FilterStruct" are stored like a matrix of three columns and as many rows than there are elements.

Filter | frequency | amplitude | bandwidth
--- | --- | --- | ---
Filter1 | - | - | -
Filter2 | - | - | -
FilterN | - | - | -

## Frames

The second specification of SDIF is that the matrices are clustered in frames. There are several types of frames: banks of filters, banks of fofs... A frame is addressed to an object containing several sub-objects of structure simple(s). Thus, a frame FilterBank makes it possible to represent a whole of Filters. A structure associated with a frame is called "compound".

## Temporal Concept

With each modification in the time of object parameters, is associated a SDIF frame block for object type. A SDIF file is overall a succession of frames ordered in time.

## Special Frames

A file SDIF is composed of several Special Frames in the order:

- Zero, one or more table of information "Information Table",
- Optional Special Frame of declarations or completions of the types of matrices or frames "Types Declaration",
- An optional table of index SDIF "Stream IDs Table",
- A continuation of Special Frames of the type "Frame".

There should be Time Table but its format and its position were not decided yet.

## BigEndian

For any computer equipement of which writes or reads files SDIF, all the data are written in BigEndian IEEE with a alignement of 8 bytes for each block (matrix).

# The Format

- File Header
- Frame

- Frame Header
- Frame Data

- Matrix

- Matrix Header
- Matrix Data

- Example of Frame in text
- Special Frames Specifications

- Informations Table

- Informations Table Header
- Informations Table Data
- Padding

- Types Declaration

- Types Declaration Header
- Types Declaration Data

- Matrix Type
- Frame Type
- Types Declarations Grammar

- Stream IDs Table

- Stream IDs Table Header
- Stream IDs Table Data

## File Header

Header of a SDIF file is composed of 3 fields and a padding:

Signature SDIF | 4 bytes | "SDIF"
Header Special Frame Size (Padding included ) | 4 bytes | == 8 (or ffffffff hexa by default)
SDIF Specification Version | 4 bytes | == 2
Padding | 4 bytes | '/0'

## Frame

### Frame Header

Frame Signature | 4 bytes | char[4]
Frame Size (not counting Signature and Size) | 4 bytes | int 4
Time; | 8 bytes | float 8
StreamID | 4 bytes | int 4
Matrix Count | 4 bytes | int 4

Frame signature is the type of frame data. The size of the frame not includes signature and size fields. The time must be more or equal than the previous frame. The StreamID refers to frames which have the same ID. The matrix count can be less than matrices number of frame signature type specification. It's possible to omit matrices in a frame. The matrices order is not important.

### Frame Data

Data frame is simply a succession of N Matrices. There is no Padding for a frame because the alignement is assumed by the alignement of each matrix.

Matrix 1 | 8 bytes aligned
... | 8 bytes aligned
Matrix N | 8 bytes aligned

## Matrix

### Matrix Header

Matrix Signature | 4 bytes | char
Matrix Data Type | 4 bytes | int 4
Row Count | 4 bytes | int 4
Column Count | 4 bytes | int 4

The Matrix Signature must be in the Frame Type specification

The Matrix Data Type is represented by a integer

- Float4 = 1.
- Float8 = 2.

The Row Count depends on the number of simple elements (or sub-objects) which contains the compound object referred by the StreamID field into the frame header. For one element, the relation between two times is made by the position in the matrix which is the same. There will be some matrix types which will have a first column named index. This column makes the link between two time. It's important when a sub-object dies. This is the case, for example, of partials in HMM.

### Matrix Data

Matrix is written row by row in the file or the stream. It's followed by a eventual padding of 4 bytes set as '\0' for the alignement.

Row 1 | (4 or 8 bytes)*C | float 4 or 8
... | (4 or 8 bytes)*C | float 4 or 8
Row L | (4 or 8 bytes)*C | float 4 or 8
Padding | 0 or 4 bytes | '\0'

## Example of Frame in text

    ( ) : comment in this example.

    (frame of a bank of fofs which contains 3 matrices)

    '1FOB'  <FrameSize>  (Time=)1.45	(ID=)0	(Nbmatrix=)3

      (matrix 1 : frequency phasor)
      '1FQ0'    (DataType=)32    (L=)1    (C=)1

           (frequency)
              164.

      (matrix 2 : fofsparameters)
      '1FOF'    (DataType=)32    (L=)5    (C=)7
          (frequency amplitude bandwidth tex     atten   debatt phase)
    	   609.       80.      78.       0.002   0.05    0.004   0.     (fof1)
    	   1000.      53.9	   88.       0.002   0.05    0.004   0.     (fof2)
    	   2450.      18.	   123.      0.002   0.05    0.004   0.     (fof3)
    	   2700.      19.	   128.      0.002   0.05    0.004   0.     (fof4)
    	   3200.      6.1	   138.      0.002   0.05    0.004   0.     (fof5)

      (matrix 3 : fofschannels)
      '1CHA'    (DataType=)32    (L=)5    (C=)1
            (channel1 channel2)
    	   1.5       1.    (fof1)
    	   1.5	     1.    (fof2)
    	   1.5	     2.2   (fof3)
    	   1.5	     0.5   (fof4)
    	   1.5	     1.5   (fof5)

## Special Frames Specifications

A SDIF Special Frame is frame which doesn't contain any matrices. It is marked by a Signature at the upper level of SDIF file or stream.

## Informations Table

### Informations Table Header

Informations Table Header is a frame header with particular values to indicate the special aspect of this frame.

Signature Informations Table | 4 bytes | "1NVT"
Special Frame Size | 4 bytes | not counting signature and size (Padding included and by default ffffffff hexa)
Time | 8 bytes | float8 (-DBL_MAX == ffefffff hexa)
StreamID | 4 bytes | int4 (0)
MatrixCount | 4 bytes | int4 (0)

### Informations Table Data

The table of information makes it possible to have general information like the author of the file, the version of SDIF library, the number of cannels... The data of this Special Frame are in ASCII.

The data start with ' { ' and finish by ' } '. Each information is in the form `<Name> <Value> ';'` . It is necessary to have at least a space character between the name and the value (and not the character ' \0 ' because it is an ASCII part).

Informations Table Data Example :

    1NVT<FrameSize><Time==-DLB_MAX><StreamID==0><MatrixCount==0>{
      numChannels   6;
      IrcamSdifLibraryVersion    1.0.0.alpha;
      MonProgrammeParametreSpecial  integer4  ;
    }<Padding>

Associated grammar is:

    <Info Table Data>    := '{' <Info declaration> | ... '}'
      <Info declaration> := [<space chars>] <Name>
                                     <space chars> <Value> [<space chars>]';'
        <space chars>    := <space> | ...
          <space>        :=  ' ' | '\t' | '\n' | '\f' | '\r' | '\v'
        <Name>           := ASCII string
        <Value>          := ASCII string

### Padding

The ASCII aspect of the table of information starts with the ' { ' and ends with the ' } '. But after the ' } ', there is Padding which can vary from 0 to 7 bytes. Each bytes of Padding is put at ' \0 '. Padding makes it possible to align the file on 64 bits. Thus the next frame begins aligned.

## Types Declaration

It is possible in SDIF to complete the types of matrices or frames existing (cf: Predefined Types) or to create new ones. If types already exists, it is considered that declaration on this type is a completion. If there does not exist, then it is a creation.

However, for a given type, there can be only one declaration in a file SDIF. I.e. a type can't be completed a twice, and create a new type then complete it is forbidden.

As for the tables of information, types declaration data are in ASCII. On the other hand, there can be only one of them.

Important : Creations are highly disadvised because it acts of an exclusive mode linked to an application. Moreover, the first character of types created names must be 'E'. Thus, an exclusive type can be added to the base of the predefined types by replacing the 'E' by a digit. Then, the files using the exclusive type is always readable.

### Types Declaration Header

Types Declaration Header is a frame header with particular values to indicate the special aspect of this frame.

Signature Types Declaration | 4 bytes | "1TYP"
Special Frame Size | 4 bytes | not counting signature and size (Padding included and by default ffffffff hexa)
Time | 8 bytes | float8 (-DBL_MAX == ffefffff hexa)
StreamID | 4 bytes | int4 (0)
MatrixCount | 4 bytes | int4 (0)

### Types Declaration Data

The data of Types Declaration is in ASCII. It starts with '{' and ends by '}'. A data is either a declaration of matrix type, or a declaration of frame type. As a frame type is a whole of matrices, its declaration depends on the declarations of matrices contained types. Two keywords make it possible to know if it is a matrix or a frame declaration : "1MTD" for matrix, "1FTD" for frame.

Note : this both keywords should allow types declaration evoluates to a binary frame with two matrices, one for the matrices declaration and another for the frames declaration. At the moment, the problem is the variability size of a declaration which would be a matrix row.

#### Matrix Type

A matrix type declaration starts by "1MTD". Then follows the matrix type name on 4 characters ASCII of which the first be a figure indicate the type version for a completion or ' E' for a creation. Then, column names declaration is like an array in C.

Examples :

       1MTD EFIL {frequency, amplitude, bandwidth}
       1MTD  1TM1 { field1, field2, field3 }
       1MTD2TM2{field21,field22,field23}

    EFIL is a creation, 1TYP and 2TYP are completions.

As the sizes of " 1MTD " and the name of the type are fixed, it is not necessary to have spaces (however, it is preferable).

The field names define columns order in the matrices. This one cannot be modified without creating a new type. Contrary to the structures C, the fields are not typed. This comes owing to the fact that data are always floats on 4 bytes or 8 bytes (cf. Matrix Data).

Matrix Completion :

When matrix type is predefined (there exists like format in SDIF), a declaration on this type involves the completion mode. Completion consists in adding new columns (fields) to the matrices (with the simple structures). Thus, if 1FIL is preset in SDIF with "frequency", "amplitude", and "bandwidth", `1MTD 1FIL {saliance, correction}` adds two new columns to the matrix (4 and 5). But no modifications of the predefined columns is possible.

#### Frame Type

A frame type declaration starts with "1FTD". Next follows the name of the frame type on 4 ASCII characters whose first digit indicates the type version for a completion or 'E' for a creation. The block of definition starts with '{' and finished by '}'. Each data of the frame type is: a name of an existing matrix type and a field name of structure frame. At the end of each field declaration, there is one ';'.

Example (suppose 1FIB, 1FIL, 1TM1 and 2TM2 exist) :

    Creation: exclusive mode
        1FTD EFIB
         {
           1FIL  filters;
           1TM1  TMexample1;
         }

    Completion
        1FTD 1FIB
         {
           2TM2 TMexample2;
         }

    EFIB and 1FIB do not represent the same frame type even if they have same first matrices,
    and that the 3 significant letters are 'FIB'.

Thus, one definite EFIB like a frame of 2 matrices. As for the matrices, if the type of frames is predefined, then one completes frame type by additional matrices. Thus, if 1FIB is predefined as in the preceding example, if one declares `1FTD 1FIB {2TM2 TMexample2}` , then one adds a new matrix to 1FIB.

Important:As the order of matrices in the frame data is not important, a frame type cannot contains more than one matrix of the same matrix type.

#### Types Declaration Grammar

    <Types Declaration Data> := '{' <Matrix or Frame Declaration> | ... '}'
      <Matrix or Frame Declaration> :=  <Matrix Declaration>
                                           | <Frame Declaration>
        <Matrix Declaration> := 1MTD [space chars] <Matrix Name> [space chars]
                                       '{' <Col Names > <One Col Name> '}'
          <Matrix Name> := 4 chars (32bits)
          <Col Names> := [<(N-1) Col Names>]
            <(N-1) Col Names> := <One Col Name Not Last> | ...
              <One Col Name Not Last> := <One Col Name> ','
          <One Col Name> := [space chars]<string>[space chars]
             <string> := ASCII chars
        <Frame Declaration> := 1FTD [space chars] <Frame Name> [space chars]
                                       '{' <Frame Component> | ... '}'
          <Frame Name>  :=  4 chars (32bits)
          <Frame Component> := [spaces] <Matrix Name>
                                     [spaces] <Frame Component Name>[spaces] ';'
             <Frame Component Name> := <string>

Types declaration example:

    1TYP<FrameSize><Time==-DLB_MAX><StreamID==0><MatrixCount==0>{
      1MTD 1FIL {frequency, amplitude, banwidth}
      1MTD 1CHA {channel1, channel2}

      1FTD FIB
        {
          1FIL filtersparameters;
          1CHA filterschannels;
        }

      1MTD 1FOF {frequency, amplitude, banwidth, tex, debatt, atten, phase}
      1MTD 1FQ0 {fondamentalfq0}

      1FTD 1FOB
        {
          1FQ0 pitch;
          1FOF fofsparameters;
          1CHA fofschannels;
        }
    }<Padding>

The Special Frame Types Declaration is optionnal.

## Stream IDs Table

### Stream IDs Table Header

Types Declaration Header is a frame header with particular values to indicate the special aspect of this frame.

Signature Stream IDs Table | 4 bytes | "1IDS"
Special Frame Size | 4 bytes | not counting signature and size (Padding included and by default ffffffff hexa)
Time | 8 bytes | float8 (-DBL_MAX == ffefffff hexa)
StreamID | 4 bytes | int4 (0)
MatrixCount | 4 bytes | int4 (0)

### Stream IDs Table Data

The table of ID makes it possible to have information on the objects to which the frames will apply. A ID is an integer refering a particular object. Two objects always have two different ID, even if they are different by their types. Thus a ID is an absolute key for an object compared to a file SDIF. The ID==0 is reserved for the special frames.

The data start with ' { ' and ends by ' } '. Each information is in the form `<ID> <Source or Destination> : <TreeWay> '; '`. The data are in ASCII.

Stream IDs Table Data example:

    1IDS<FrameSize><Time==-DLB_MAX><StreamID==0><MatrixCount==0>{
      1   MyProg:Group1/1/FIB/0/12/500./3./80.;
      2   MyProg:Group1/1/FIB/1/5/500./3./80.;
      3   MyProg:Group1/1/FIB/2/8/500./3./80.;
      4   YourProg:FOB/"Fofbank"/4/4/2;
    }<Padding>

Meaning and the construction of TreeWay depend on the Source, but nothing is predefined. The Source could be a name of program, or a name of method of calculation, of analysis, synthesis... It is useful for the program which will read the data and not by that which writes them. This is why one speaks about Source or Destination. TreeWay can give information on links between object. A component in TreeWay seems obligatory: there must be the name of the type of the object in TreeWay. The table of the ID is the means to declare objects which will be modified in time via the frames.
As for the precedents chunk, Stream IDs Chunk is aligned on 8 bytes by Padding.

The grammar is:

    <ID Table Data>            := '{' <ID declaration> | ... '}'
      <ID declaration>         := [<space chars>] <ID>
                                         <space chars> <Souce ou Destination> ':'
    			             [<space chars>] <TreeWay> ';'
        <space chars>          := <space> | ...
          <space>              :=  ' ' | '\t' | '\n' | '\f' | '\r' | '\v'
        <ID>                   := ASCII digits
        <Source ou Destination>:= ASCII string
        <TreeWay>              := ASCII string (définition variable)
             Les composants de TreeWay sont séparés par le symbol '/'.

# SDIF Reserved Words

- Information Table Words
- Predefined Types

- Predefined Matrix Types

- Fondamental frequency "1FQ0"
- "Forme d'Onde Formantique" "1FOF"
- Channels "1CHA"
- Resonnant filers "1RES"
- Random distribution "1DIS"

- Predefined Frame Types

- Fofs bank "1FOB"
- Resonnant filters bank "1REB"
- Noise "1NOI"

- StreamID TreeWay for the Chant program

- Description of each element of TreeWay
- Example TreeWay for the Chant program

## Information Table Words

Author | author of the file
SDIFTypesVersion | version of the format of the types
NVTName | Name of the name value table

## Predefined Types

1 november 1998

### Predefined Matrix Types

Name | Meaning
--- | ---
1FQ0 | fundamental Frequency or excitation of a bank of fofs
1FOF | "Forme d'Onde Formantique"
1CHA | Channels
1RES | Resonnant Filters
1DIS | Distribution of a random process

    1FQ0    {Frequency, Mode, Hit}
     Frequency  : Fundamental frequency of a bank of fofs >0.(Hz).
     Mode       : Mode of excitation (0: Frequency, 1:Hit, 2:Both).
     Hit        : Excitation (Dirac) over a precise time (0: no excitation, 1: excitation).

    1FOF	{Frequency, Amplitude, BandWidth, Tex, DebAtt, Atten, Phase}
     Frequency  : Frequency of the fof >0. (Hz).
     Amplitude  : Lineary amplitude of the envelope of the fof.
     BandWidth  : Bandwidth of Fof >0. (Hz).
     Tex        : Time of exitation >0. (seconds).
     DebAtt     : Moment of beginning of the attenuation of the envelope >0. (seconds).
     Atten      : Duration of the attenuation >0. (seconds).
     Phase      : Phase of the sinusoid of the fof 0. with 2pi rad.

    1CHA	{Channel1, Channel2, Channel3, Channel4}
     ChannelX   : Linear amplitude on the Channel X >0..
     If there is more than 4 channels, it is enough to have types declaration frame
     and to make a completion of 1CHA: 1MTD 1CHA { Channel5, Channel6 } One
     can thus add the channels one as many than one wishes it.

    1RES	{Frequency, Amplitude, BandWidth, Saliance, Correction}
     Frequency  : Frequency of the resonant filter.
     Amplitude  : Lineary amplitude of the Filter.
     BandWidth  : Bandwidth of the Filter >0. (Hz).
     Saliance   : percentage of error of the parameters 0.à 100.
     Correction : automatic correction of the amplitude compared to

                  other parameters 0. to 1.

    1DIS	{Distribution, Amplitude}
     Distribution : type of distribution (not yet definite but 0 means equi-distributed)
     Amplitude    : variance of the random process (amplitude). This type can be completed
      by higher order variances.

### Predefined Frame Types

Name | Meaning
--- | ---
1FOB | FOFs bank
1REB | Resonnant filters bank
1NOI | Noise

    1FOB
      {
        1FQ0  PitchModeHit;
        1FOF  Formants;
        1CHA  FormantsChannels;
      }
     PitchModeHit     : excitation of the fofbank. Only 1 row by frame 1FOB.
     Formants         : parameters of the envelopes of fof.
     FormantsChannels : amplitude of output of the fofs on each channel.

    1REB
      {
        1RES  Filters;
        1CHA  FiltersChannels;
      }
     Filters: paramameters of the filters.
     Filterschannels: amplitude of output of the filters on each channel.

    1NOI
      {
        1DIS  NoiseInfo;
      }
    NoiseInfo : Noise parameters.

}

## StreamID TreeWay for the Chant program

The TreeWay field of StreamID does not have an absolute definition. Its interpretation depends on the Source field which represents the type of TreeWay which follows it. Only format envisaged is that TreeWay must have the pace of a URL

Chant library can interpret of StreamID whose Source field is 'Chant' and where the TreeWay field follows this format:
`<PatchType>/<NumPatch>/<ObjType>/<NumObj> /<NbSubObjt>/<StartTime>/<EndTime>[/"<SoundFileName>"]`
([ ] means here "eventually", Obj: Object, Num: Number, Nb: Numbers ).

### Description of each element of TreeWay

- PatchType: It is the predefined type of patch in Chant to which belongs the indexed object. The possible values are Patch0, Patch1, ..., Patch10, (November98).
- NumPatch:Number which refers the patch among all patchs in the same type. One can control several patch of the Patch0 type. The first will have NumPatch=1 and second NumPatch=2...
- ObjType: A Chant patch is an assembly of objects of different types. ObjType represents the type of the indexed object. The recognized types are: 'FOB', 'REB', 'NOI' and 'SND'. The three first are also predefined frames types signatures without version. Then, there is a link between the object type in TreeWay and the frame type which makes it possible to make move this object.
- NumObj: If a patch contains several objects of same type, it is necessary to be able to refer each one of them. Then, NumObj determines which object of ObjType type frame addresses itself. The number has a very precise meaning for the patch connection. Also, the predefined patchs are fixed, one cannot have NumObj=3 if the patch contains only two objects. (cf. Exemple below).
- NbSubObj: Maximum Numbers of sub-objects of the object indexed by StreamID. For a bank of FOFs, it is typically the number of FOFs maximum of the bank (in the same way for the banks of filters). The objects typified by 'NOI' or 'SND' are the noise and the files sounds. They do not have sub-objects. In this case NbSubObj=0.
- StartTime and EndTime: They are times of beginning and end of the object.
- SoundFileName: This TreeWay element must be in TreeWay only for a 'SND' object. It contains the name of the sound file referred by this object. The only constraint is the name placed between '"' must not contains characters ';' and '"'.

### Exemple

Let us take an example of the very general type of patch.
Each object type of Chant is represented here. This patch type is only one example and does not exist like predefined patch type.

There are 2 banks of filters. This will utilize the number of the object (on the right names on the diagram). Indeed, the bank of filter whose number is 1 corresponds to the bank which filters only the bank of FOFs. Bank 2 corresponds to that which filters all the objects. Follows for example the patch StreamIDs.

    1IDS  (...)
    {
      145   Chant:PatchTypeExample/1/FOB/1/23/0./5.;
      7     Chant:PatchTypeExample/1/REB/1/45/0./5.;
      32    Chant:PatchTypeExample/1/NOI/1/0/0./6.;
      12    Chant:PatchTypeExample/1/SND/1/0/0./6./"./snd/file.sf.rs";
      122   Chant:PatchTypeExample/1/REB/2/85/0./6.;
    } (padding)

NumID are independants. They must only be single. The number of sub-object, times of ends and beginning are also independent for each object. The object of NumID 7 is the bank of filters 1 of the patch. Then, it filters only the bank of FOFs. The object of NumID 122 is the bank of filters 2 which filters the bank of FOFs, the noise and the file sound.
To have another StreamID:
`123 Chant:PatchTypeExemple/1/REB/3/85/0./6.;`
does not allow to have a third bank of filters, because a type of patch is fixed. Moreover, if it misses one of the components of the patch, then this patch will not appears in the synthesis. A patch must be complete to be computed.

Currently, these patch types are available:

Stream ID SND of Patch2 contains the name of a sound file to filter. However, there is neither matrix, nor frame associated with this object.

     Stream ID Example for a Patch1 :
      1	Chant:Patch1/1/FOB/1/4/0./1.;
      2	Chant:Patch1/1/REB/1/5/0./1.;
      3	Chant:Patch1/1/NOI/1/0/0./1.;   // a noise doesn't have sub-object.

    another Patch1:
      4	Chant:Patch1/2/FOB/1/3/2./5.;
      5	Chant:Patch1/2/REB/1/8/2./5.;
      6	Chant:Patch1/2/NOI/1/0/2./5.;

    Patch2:
      7	Chant:Patch2/1/NOI/1/0/0./4.;
      8	Chant:Patch2/1/REB/1/5/0./5.;
      9	Chant:Patch2/1/SND/1/0/0./4./"filename";