Logo Search packages:      
Sourcecode: biosig4c++ version File versions  Download package

scp-decode.cpp

/*
    $Id: scp-decode.cpp,v 1.24 2008-07-12 20:46:58 schloegl Exp $
    This function is part of the "BioSig for C/C++" repository 
    (biosig4c++) at http://biosig.sf.net/ 

Modifications by Alois Schloegl 
    Jun 2007: replaced ultoa with sprintf 
    Aug 2007: On-The-Fly-Decompression using ZLIB
    Oct 2007: Consider SunOS/SPARC platform 
            obsolete code sections marked, this reduced SegFault from 18 to 1.
            

---------------------------------------------------------------------------
Copyright (C) 2006  Eugenio Cervesato.
Developed at the Associazione per la Ricerca in Cardiologia - Pordenone - Italy,
based on the work of Eugenio Cervesato & Giorgio De Odorico. The original
Copyright and comments follow.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
---------------------------------------------------------------------------

______________________________________________________________________________

   scp-decode.cpp       This is the "decode" module of the program SCP-AV.
                        It opens an SCP-ECG v1.0 to v2.0 test file and
                        extracts all the informations.

                         Release 2.3 - feb 2006
---------------------------------------------------------------------------
**************************************************************************

************************* original Copyright *****************************
Copyright (C) 2003-2004  Eugenio Cervesato & Giorgio De Odorico.
Developed at the Associazione per la Ricerca in Cardiologia - Pordenone - Italy.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
---------------------------------------------------------------------------
*/
//______________________________________________________________________________
/*
   scp-decode.cpp       This is the "decode" module of the program SCP-AV.
                        It opens an SCP-ECG v1.3 or v2.0 test file and
                        extracts all the informations.

                  Developed by ING. GIORGIO DE ODORICO (giorgio.deodorico@tiscali.it)

                        Documentation of the standard comes mainly from:
                        http://www.centc251.org/TCMeet/doclist/TCdoc02/N02-015-prEN1064.pdf

                        Internationalization, test, bug fix by Eugenio Cervesato (eugenio.cervesato@aopn.fvg.it)

                        Release 2.1 - february 2004

*/
// ************************* end of the original Copyright *****************************

// contribution of Michael Breuss <m.breuss@tma-medical.com>. see 'by MB' in the sources
// contribution of Stelios Sfakianakis <ssfak@ics.forth.gr>. see 'by SS' in the sources
// contribution of Federico cantini <cantini@ifc.cnr.it>. see 'by FeC' in the sources

//void remark(char *string);

// 
#define WITH_OBSOLETE_PARTS 


//      by E.C. 13.10.2003   part nedded to compile with gcc (Linux).
//                           To compile with Borland C++ add the conditional define: WIN32.
//                           In porting, I nedded to adapt fseek() and write a custom ultoa()

#define COMPAT

//______________________________________________________________________________

#include <iostream>
#include <cstring>    //strcat, strcpy
#include <cstdio>
#include <stdlib.h>
using namespace std;

//______________________________________________________________________________
//               FILE POINTERS

#include "../biosig-dev.h"
#include "structures.h"
#include "codes.h"
//     the following define is private of Eugenio Cervesato. Please other readers ignore it!
#ifdef CPPBUILDER3
#include "CPPBUILDER3.h"  // inside are definitions needed to run on C++Builder GUI as a standalone module and bypass ZLIB
#endif
//     end of private define.
HDRTYPE* in;

//---------------------------------------------------------------------------
static U_int_L _COUNT_BYTE=1UL;                  // counter of bytes read
static U_int_L _DIM_FILE;                      // file length in byte
static const U_int_S _NUM_SECTION=12U;     // sections over 11 are not considered

//______________________________________________________________________________
//                      section 2
U_int_S         Input_Bit(U_int_S*,U_int_M&,U_int_M,U_int_S&,bool&);
int_M           Input_Bits(U_int_S*,U_int_M&,U_int_M,U_int_S&,U_int_S,bool&);
void            decompress(TREE_NODE*,int_M*,U_int_S&,U_int_M&,int_L*,U_int_M,U_int_M&,table_H*,U_int_M*,U_int_M&);
void            Tree_Destroy(TREE_NODE*);
TREE_NODE       *Tree_Create(TREE_NODE*,U_int_M,table_H*,U_int_M);
void            Huffman(int_L*,U_int_M*,U_int_S*,U_int_M&,U_int_M,table_H*,U_int_M*);
void            InitHuffman(table_H*);                          //inizialize default Huffman table

//______________________________________________________________________________
//                      sections 3, 4, 5 and 6
template<class t1>
void            Differences(int_L*,t1,U_int_S);
void            Multiply(int_L*,U_int_L,U_int_M);
void            Interpolate(int_L*,int_L*,f_lead,lead*,f_Res,Protected_Area*,U_int_L);
void            ExecFilter(int_L*,int_L*,U_int_L&,U_int_M);
void            DoFilter(int_L*,int_L*,f_Res,f_lead,lead*,Protected_Area*,Subtraction_Zone*);
void            DoAdd(int_L*,int_L*,f_Res,int_L*,f_BdR0,Subtraction_Zone*,f_lead,lead*);
void            Opt_Filter(int_L*, int_L*, f_Res, f_lead, lead*, Protected_Area*);

//______________________________________________________________________________
//                             INTERNAL FUNCTIONS
char*           ReadString(char*,U_int_M);                          //read a string
char            *FindString(U_int_M);                         // calculate the length of a string and write it down
int_M           Look(alfabetic*,U_int_M,U_int_M,U_int_M);      //look at a number in alfabetic and give the position of the array

//______________________________________________________________________________
template<class t1>
void            ReadByte(t1&);         //read a byte from stream
void            Skip(U_int_M);        //skip some bytes

//______________________________________________________________________________
U_int_M         ReadCRC();                             //read first 6 bytes of the file
bool            Check_CRC(U_int_M,U_int_L,U_int_L);     // CRC check
//______________________________________________________________________________

U_int_L         ID_section(U_int_L, int_S &version);              //read section ID header
void            sectionsOptional(pointer_section*,DATA_DECODE&,DATA_RECORD&,DATA_INFO&);       //handles optional sections

#ifdef WITH_OBSOLETE_PARTS
void            section_0(pointer_section*, int size_max);                    //read section 0
void            Init_S1(DATA_INFO &inf);
void            section_1(pointer_section,DATA_INFO&);    //read section 1 data
void            section_1_0(demographic&);                        //read tag 0 of section 1
void            section_1_1(demographic&);                        //read tag 1 of section 1
void            section_1_2(demographic&);                        // ... and so on ...
void            section_1_3(demographic&);
void            section_1_4(demographic&);
void            section_1_5(demographic&);
void            section_1_6(demographic&);
void            section_1_7(demographic&);
void            section_1_8(demographic&);
void            section_1_9(demographic&);
void            section_1_10(clinic&,U_int_M&);
void            section_1_11(demographic&);
void            section_1_12(demographic&);
void            section_1_13(clinic&,U_int_M&);
void            section_1_14(descriptive&);
void            section_1_15(descriptive&);
void            section_1_16(descriptive&);
void            section_1_17(descriptive&);
void            section_1_18(descriptive&);
void            section_1_19(descriptive&);
void            section_1_20(clinic&);
void            section_1_21(clinic&);
void            section_1_22(clinic&);
void            section_1_23(descriptive&);
void            section_1_24(descriptive&);
void            section_1_25(device&);
void            section_1_26(device&);
void            section_1_27(device&);
void            section_1_28(device&);
void            section_1_29(device&);
void            section_1_30(clinic&,U_int_M&);
void            section_1_31(device&);
void            section_1_32(clinic&,U_int_M&, int_S version);
void            section_1_33(device&);
void            section_1_34(device&);
void            section_1_35(clinic&,U_int_M&);
void            section_1_();                                   //skip tags of the manufacturer of the section 1
void            section_1_255();                                //read tag 255 of section 1
void            section_7(pointer_section,DATA_RECORD&, int_S version); //read section 7
void            section_8(pointer_section,DATA_INFO&);          //read section 8
void            section_10(pointer_section,DATA_RECORD&, int_S version); //read section 10
void            section_11(pointer_section,DATA_INFO&);         //read section 11
#endif
void            section_2(pointer_section,DATA_DECODE&);        //read section 2
void            section_3(pointer_section,DATA_DECODE&, int_S version); //read section 3
void            section_4(pointer_section,DATA_DECODE&, int_S version); //read section 4
bool            section_5(pointer_section,DATA_DECODE&,bool);   //read section 5
void            section_6(pointer_section,DATA_DECODE&,bool);   //read section 6

//______________________________________________________________________________
void            Decode_Data(pointer_section*,DATA_DECODE&,bool&);

//______________________________________________________________________________

void *mymalloc(size_t size)            // by E.C. 07.11.2003    this is a workaround for a bug
{                                      // present somewhere in memory allocation.
//        char buff[30];               // this problem should be fixed next!
//        ultoa(size, buff, 10);       // used for debug purposes, shows the size
//        remark(buff);
//    fprintf(stdout,"MYMEMALLOC: %i\n",size);
//        void *res=malloc(size*2);      // this way each time a doubled memory is requested. And it works!!
      void *res=malloc(size);
      return res;
}

/* moved by MB
   must be declared before first call (otherwise compiler error)
*/
//--------------------------------BYTE & BIT------------------------------------
template<class t1>
void ReadByte(t1 &number)
{
//read the requested number of bytes and
//convert in decimal, taking into account that the first byte is the LSB.
//the sign of the number is kept
      U_int_S *num, dim=sizeof(t1);
      U_int_S mask=0xFF;


      if(dim!=0 && (num=(U_int_S*)mymalloc(dim))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      ifread(num,dim,1,in);
      // *num = *(U_int_S*)(in->AS.Header+_COUNT_BYTE);
      number=0;
      _COUNT_BYTE+=dim;

      while((dim--)>0)
      {
            number<<=8;
            number+=num[dim]&mask;
      }
      free(num);
}//end ReadByte

//                      MAIN

int scp_decode(HDRTYPE* hdr, pointer_section *section, DATA_DECODE &decode, DATA_RECORD &info_recording, DATA_INFO &info_textual, bool &add_filter)
{
      U_int_M CRC;
      U_int_L pos;

      if (hdr->FILE.OPEN) {
            ifseek(hdr,0,SEEK_SET);
      }
      else  
            hdr = ifopen(hdr,"rb");

      if (!hdr->FILE.OPEN)
      {
            fprintf(stdout,"Cannot open the file %s.\n",hdr->FileName);
            return FALSE;              // by E.C. 15.10.2003    now return FALSE
      }

      in = hdr;
      _COUNT_BYTE=1UL;
      CRC=ReadCRC();
      pos=_COUNT_BYTE;
      ReadByte(_DIM_FILE);
//    if (CRC != 0xFFFF) Check_CRC(CRC,pos,_DIM_FILE-2U);  // by E.C. may 2004 CARDIOLINE 1.0
      ifseek(in, 0L, SEEK_SET);

//mandatory sections
#ifdef WITH_OBSOLETE_PARTS
      section_0(section, _DIM_FILE);                 // by E.C. may 2004 check file size
      section_1(section[1],info_textual);

      sectionsOptional(section,decode,info_recording,info_textual);
#else 

      if (section[2].length>0)      
            section_2(section[2],decode);       //HUFFMAN
      if (section[3].length>0)      
            section_3(section[3],decode,hdr->aECG->Section1.Tag14.VERSION);      //lead
      if (section[4].length) 
            section_4(section[4],decode,hdr->aECG->Section1.Tag15.VERSION);       // fiducial locations
      if (section[5].length)
            if (!section_5(section[5],decode,section[2].length)) 
                  section[5].length=0 ;       //type 0 median beat
      if (section[6].length)
            section_6(section[6],decode,section[2].length);       //rhythm compressed data

#endif
 
      ifclose(in);

      Decode_Data(section,decode,add_filter);
      return TRUE;              // by E.C. 15.10.2003    now return TRUE
}
//______________________________________________________________________________
//                           COMPUTATIONAL FUNCTIONS

#ifdef WITH_OBSOLETE_PARTS
//------------------------------STRINGS----------------------------------------
char *ReadString(char *temp_string, U_int_M num)
//read a string from the stream.
//the first extracted byte is written for fist.
//each byte read from the stream is first "transformed" in char.
{
      if((temp_string=(char*)mymalloc(sizeof(char)*(num+2)))==NULL)    // by E.C. 26.02.2004 one more byte
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }

      if(!num)
            return NULL;

      _COUNT_BYTE+=num;

      ifread(temp_string,sizeof(char),num,in);
      if (temp_string[num-1]!='\0')
            temp_string[num]='\0';

      return temp_string;
}//end ReadString

int_M Look(alfabetic *code_, U_int_M a, U_int_M b, U_int_M key_)
// look num in code_.number and give the element position
{
      U_int_M middle=(a+b)/2U;

      if(code_[middle].number==key_)
            return middle;
      if(a>=b)
            return -1;
      if(code_[middle].number<key_)
            return Look(code_,middle+1,b,key_);
      else
            return Look(code_,a,middle-1,key_);
}//end Look

char *FindString(U_int_M max)
//read bytes until NULL
{
      char *temp_string, c;
      U_int_M num=0;
      //fpos_t
      long filepos;

      if(!max)
            return NULL;

      filepos = iftell(in); //FGETPOS(in,&filepos);
      do
      {
            c=ifgetc(in);
            ++num;
      }
      while(c!='\0' && num<max);

      ifseek(in,filepos COMPAT,0);

      if((temp_string=(char*)mymalloc(sizeof(char)*(num+2)))==NULL)   // by E.C. one extra byte nedded
      {                                                               // for later str_cat()
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }

      if(!num)
            return NULL;

      _COUNT_BYTE+=num;

      ifread(temp_string,sizeof(char),num,in);
      if (temp_string[num-1]!='\0')
            temp_string[num]='\0';

      return temp_string;
}//end FindString
#endif

void Skip(U_int_M num)
//skip num bytes from the stream
{
      if(num>0U)
            ifseek(in,num,1U);
      _COUNT_BYTE+=num;
}//end Skip

//______________________________________________________________________________
//                         INITIALIZATION FUNCTIONS

void InitHuffman(table_H *riga)
//build the default Huffman table
{
/*
  The table is contructed as stated in the protocol SCP-ECG; each structure in each line.
  Columns are:
        bit_prefix = number of bits in the prefix
        bit_code   = number of bits in the code
        TMS        = table mode
        base_value = base value (decoded)
        cp         = prefix code (in bits)
        base_code  = decimal value of reversed cp

  From the stream I take a bit at a time until I find a correspondent value in the Huffman table.
  If:
        nbp=nbc the decode value is vb
        nbp!=nbc
           if m=1 I take nbc-nbp bits next in the stream
           if m=0 change to table vb
  Remark: Huffman tables stored in the stream contain vb in 2 complemented bytes.
  The decimal value of cp is included. Furthermore, always the MSB comes first!
  In my Huffman tables I set cp as a decimal value. Infact, I read a group of bits
  from the stream and convert them by multipying by 2^pos (where pos is
  0 for bit 0, 1 for bit 1 and so on). So I read bits as they are.

              DEFAULT HUFFMAN TABLE
             nbp nbc  m  vb  cp10    cp
               1,  1, 1,  0,    0,    0,
               3,  3, 1,  1,    1,    4,
               3,  3, 1, -1,    5,    5,
               4,  4, 1,  2,    3,   12,
               4,  4, 1, -2,   11,   13,
               5,  5, 1,  3,    7,   28,
               5,  5, 1, -3,   23,   29,
               6,  6, 1,  4,   15,   60,
               6,  6, 1, -4,   47,   61,
               7,  7, 1,  5,   31,  124,
               7,  7, 1, -5,   95,  125,
               8,  8, 1,  6,   63,  252,
               8,  8, 1, -6,  191,  253,
               9,  9, 1,  7,  127,  508,
               9,  9, 1, -7,  383,  509,
              10, 10, 1,  8,  255, 1020,
              10, 10, 1, -8,  767, 1021,
              10, 18, 1,  0,  511, 1022,
              10, 26, 1,  0, 1023, 1023,
*/

      U_int_S i;

      i= 0U;  riga[i].bit_prefix= 1U; riga[i].bit_code= 1U; riga[i].TMS=1U; riga[i].base_value= 0; riga[i].base_code=   0UL;
      i= 1U;  riga[i].bit_prefix= 3U; riga[i].bit_code= 3U; riga[i].TMS=1U; riga[i].base_value= 1; riga[i].base_code=   1UL;
      i= 2U;  riga[i].bit_prefix= 3U; riga[i].bit_code= 3U; riga[i].TMS=1U; riga[i].base_value=-1; riga[i].base_code=   5UL;
      i= 3U;  riga[i].bit_prefix= 4U; riga[i].bit_code= 4U; riga[i].TMS=1U; riga[i].base_value= 2; riga[i].base_code=   3UL;
      i= 4U;  riga[i].bit_prefix= 4U; riga[i].bit_code= 4U; riga[i].TMS=1U; riga[i].base_value=-2; riga[i].base_code=  11UL;
      i= 5U;  riga[i].bit_prefix= 5U; riga[i].bit_code= 5U; riga[i].TMS=1U; riga[i].base_value= 3; riga[i].base_code=   7UL;
      i= 6U;  riga[i].bit_prefix= 5U; riga[i].bit_code= 5U; riga[i].TMS=1U; riga[i].base_value=-3; riga[i].base_code=  23UL;
      i= 7U;  riga[i].bit_prefix= 6U; riga[i].bit_code= 6U; riga[i].TMS=1U; riga[i].base_value= 4; riga[i].base_code=  15UL;
      i= 8U;  riga[i].bit_prefix= 6U; riga[i].bit_code= 6U; riga[i].TMS=1U; riga[i].base_value=-4; riga[i].base_code=  47UL;
      i= 9U;  riga[i].bit_prefix= 7U; riga[i].bit_code= 7U; riga[i].TMS=1U; riga[i].base_value= 5; riga[i].base_code=  31UL;
      i=10U;  riga[i].bit_prefix= 7U; riga[i].bit_code= 7U; riga[i].TMS=1U; riga[i].base_value=-5; riga[i].base_code=  95UL;
      i=11U;  riga[i].bit_prefix= 8U; riga[i].bit_code= 8U; riga[i].TMS=1U; riga[i].base_value= 6; riga[i].base_code=  63UL;
      i=12U;  riga[i].bit_prefix= 8U; riga[i].bit_code= 8U; riga[i].TMS=1U; riga[i].base_value=-6; riga[i].base_code= 191UL;
      i=13U;  riga[i].bit_prefix= 9U; riga[i].bit_code= 9U; riga[i].TMS=1U; riga[i].base_value= 7; riga[i].base_code= 127UL;
      i=14U;  riga[i].bit_prefix= 9U; riga[i].bit_code= 9U; riga[i].TMS=1U; riga[i].base_value=-7; riga[i].base_code= 383UL;
      i=15U;  riga[i].bit_prefix=10U; riga[i].bit_code=10U; riga[i].TMS=1U; riga[i].base_value= 8; riga[i].base_code= 255UL;
      i=16U;  riga[i].bit_prefix=10U; riga[i].bit_code=10U; riga[i].TMS=1U; riga[i].base_value=-8; riga[i].base_code= 767UL;
      i=17U;  riga[i].bit_prefix=10U; riga[i].bit_code=18U; riga[i].TMS=1U; riga[i].base_value= 0; riga[i].base_code= 511UL;
      i=18U;  riga[i].bit_prefix=10U; riga[i].bit_code=26U; riga[i].TMS=1U; riga[i].base_value= 0; riga[i].base_code=1023UL;
}//end InitHuffman

//______________________________________________________________________________
//                           handle sections

U_int_M ReadCRC()
// read the CRC of the entire file or of a section and convert it to decimal.
{
      U_int_M dim;

      ReadByte(dim);

      return dim;
}//end ReadCRC

bool Check_CRC(U_int_M CRC, U_int_L pos, U_int_L length)
/* CRC check starting from pos for Length

Remark: all computations are in byte.
A     = new byte
B     = temp byte
CRCHI = MSB of the CRC (16 bits)
CRCLO = LSB of the CRC

START:
      for A=first_byte to last_byte in block do:
              A = A xor CRCHI
              CRCHI = A
            shift A right 4 times         {fulfill with zeroes}
            A = A xor CRCHI               {I J K L M N O P}
            CRCHI = CRCLO                 {swap CRCHI, CRCLO}
            CRCLO = A
            rotate A left 4 times         {M N O P I J K L}
                B = A                     { temp save }
                rotate A left once        { N O P I J K L M }
                A = A and $1F                   { 0 0 0 I J L L M }
                CRCHI = A xor CRCHI
                A = B and $F0                   { M N O P 0 0 0 0 }
                CRCHI = A xor CRCHI       { CRCHI complete }
                rotate B left once              { N O P 0 0 0 0 M }
                B = B and $E0                   { N O P 0 0 0 0 0 }
                CRCLO = B xor CRCLO             { CRCLO complete }
        end

Final check on the CRC is accomplished by adding or concatenating CRCHI and CRCLO at
the end of the data stream. Calculating the checksum of the resulting data stream shall result in
a zero CRC if the data was correctly received.

*/
{
      U_int_L i;
      U_int_S A, B;
      U_int_S CRCLO, CRCHI;

      CRCLO=0xFF;
      CRCHI=0xFF;
      ifseek(in,pos-1,0U);
      for(i=1;i<=length;i++)
      {
            A=ifgetc(in);
            A^=CRCHI;
            A^=(A>>4);
            CRCHI=CRCLO;
            CRCLO=A;
            A=(A<<4)|(A>>4U);
            B=A;
            A=(A<<1)|(A>>7U);
            A&=0x1F;
            CRCHI^=A;
            A=B&0xF0;
            CRCHI^=A;
            B=(B<<1)|(B>>7U);
            B&=0xE0;
            CRCLO^=B;
      }//end for

      CRCLO-=CRC%256UL;
      CRCHI-=CRC/256UL;
      if ((CRCLO==CRCHI) && (CRCLO==0))
            return 1;
      else
      {
            fprintf(stderr,"Cannot read the file: BAD CRC.\n");
//          exit(2);
            return 0;
      }
}//end Check_CRC

U_int_L ID_section(U_int_L pos, int_S &version)
//read section Header
{
      U_int_L dim;
      U_int_M CRC;

      CRC=ReadCRC();
      Skip(2U);
      ReadByte(dim);
//    if (CRC != 0xFFFF) Check_CRC(CRC,pos+2,dim-2);  // by E.C. may 2004 CARDIOLINE 1.0
      ifseek(in,pos+7L,0);
      ReadByte(version);                   // by E.C. may 2004  store the version number
      Skip(7U);

      return dim;
}//end ID_section


void sectionsOptional(pointer_section *section, DATA_DECODE &block1, DATA_RECORD &block2, DATA_INFO &block3)
//handles optional sections
{
      U_int_S i=0, bimodal;

//initialization
      block1.t_Huffman=NULL;
      block1.flag_Huffman=NULL;
      block1.data_lead=NULL;
      block1.data_protected=NULL;
      block1.data_subtraction=NULL;
      block1.length_BdR0=NULL;
      block1.samples_BdR0=NULL;
      block1.Median=NULL;
      block1.length_Res=NULL;
      block1.samples_Res=NULL;
      block1.Residual=NULL;
//    block1.Reconstructed=NULL;
      block2.data_spike=NULL;
      block2.type_BdR=NULL;
      block2.data_BdR=NULL;
      block2.data_additional=NULL;
      block2.lead_block=NULL;
      block3.text_dim=NULL;
      block3.text_report=NULL;
      block3.data_statement=NULL;
      block3.text_statement=NULL;

      //variables inizialization
      block1.flag_lead.number=0;
      block1.flag_lead.subtraction=0;
      block1.flag_lead.all_simultaneously=0;
      block1.flag_lead.number_simultaneously=0;

      block1.flag_BdR0.length=0;
      block1.flag_BdR0.fcM=0;
      block1.flag_BdR0.AVM=0;
      block1.flag_BdR0.STM=0;
      block1.flag_BdR0.number_samples=0;
      block1.flag_BdR0.encoding=0;

      block1.flag_Res.AVM=0;
      block1.flag_Res.STM=0;
      block1.flag_Res.number=0;
      block1.flag_Res.number_samples=0;
      block1.flag_Res.encoding=0;
      block1.flag_Res.bimodal=0;
      block1.flag_Res.decimation_factor=0;

      block2.data_global.number=0;
      block2.data_global.number_QRS=0;
      block2.data_global.number_spike=0;
      block2.data_global.average_RR=0;
      block2.data_global.average_PP=0;
      block2.data_global.ventricular_rate=0;
      block2.data_global.atrial_rate=0;
      block2.data_global.QT_corrected=0;
      block2.data_global.formula_type=0;
      block2.data_global.number_tag=0;

      block2.header_lead.number_lead=0;
      block2.header_lead.number_lead_measurement=0;

      while(i<_NUM_SECTION)
      {
            if(section[i].ID)
                  switch(section[i].ID)
                  {
                        case 2: if(section[i].length)
                                          section_2(section[i],block1);       //HUFFMAN
                                    break;
                        case 3: if(section[i].length)
                                          section_3(section[i],block1,block3.des.acquiring.protocol_revision_number);      //lead
                                    break;
                        case 4: if(section[i].length)
                                    {
                                          if((block3.des.acquiring.protocol_revision_number>10) && section[6].length)      // by E.C. 27.02.2004 whole section to be included in {} !
                                          {
                                                ifseek(in,section[6].index+22,0);
                                                ReadByte(bimodal);
                                                block1.flag_Res.bimodal=bimodal;
                                          }
                                          else
                                                block1.flag_Res.bimodal=0;
                                          section_4(section[i],block1,block3.des.analyzing.protocol_revision_number);       // fiducial locations
                                    }
                                    break;
                        case 5: if(section[i].length)
                                          if (!section_5(section[i],block1,section[2].length)) section[i].length=0 ;       //type 0 median beat
                                    break;
                        case 6: if(section[i].length)
                                          section_6(section[i],block1,section[2].length);       //rhythm compressed data
                                    break;

#ifdef WITH_OBSOLETE_PARTS
/*
                        case 7: if(section[i].length)
                                          section_7(section[i],block2,block3.des.acquiring.protocol_revision_number);       //global measurements
                                    break;
                        case 8: if(section[i].length)
                                          section_8(section[i],block3);       //full text interpretative statements
                                    break;
                        case 10:if(section[i].length)
                                          section_10(section[i],block2,block3.des.acquiring.protocol_revision_number);      //lead measurement block
                                    break;
                        case 11:if(section[i].length)          //universal ECG interpretative statements
                        //                section_11(section[i],block3);
                                    break;
*/
#endif
                  }//end switch
            ++i;
      }//end while
}//end sectionsOptional

//______________________________________________________________________________
//                                sections
//______________________________________________________________________________

#ifdef WITH_OBSOLETE_PARTS

//______________________________________________________________________________
//                              section 0
//______________________________________________________________________________

void section_0(pointer_section *info, int size_max)
// section 0
//build info_sections with ID, offset and length of each section
{
      U_int_L pos, dim, ini;
      U_int_M ind;
      U_int_S i;
      int_S version;

      ifseek(in,6L,0);
      pos=ID_section(7L, version)+7L; //length + offset
      _COUNT_BYTE=7L+16L;

      for(i=0;i<_NUM_SECTION;i++)
      {
            info[i].ID=0;
            info[i].length=0L;
            info[i].index=0L;
      }
      while((_COUNT_BYTE+10)<=pos)
      {
            ReadByte(ind);
            if(ind>11U)
                  Skip(8U);
            else
            {
                  ReadByte(dim);
                  if(dim)
                  {
                        ReadByte(ini);
                        if (ini<(unsigned)size_max) {            // by E.C. may 2004 check overflow of file
                              info[ind].ID=ind;
                              info[ind].length=dim;
                              info[ind].index=ini;
                        }
                  }//end if dim
                  else
                        Skip(4U);
            }//end else
      }//end while
}//end section_0

//______________________________________________________________________________
//                              section 1
//______________________________________________________________________________

void Init_S1(DATA_INFO &inf)
{
      inf.ana.last_name=STR_NULL;
      inf.ana.first_name=STR_NULL;
      inf.ana.ID=STR_NULL;
      inf.ana.second_last_name=STR_NULL;
      inf.ana.age.value=0;
      inf.ana.age.unit=0;
      inf.ana.date_birth=STR_NULL;
      inf.ana.height.value=0;
      inf.ana.height.unit=0;
      inf.ana.weight.value=0;
      inf.ana.weight.unit=0;
      inf.ana.sex=0;
      inf.ana.race=0;
      inf.ana.systolic_pressure=0;
      inf.ana.diastolic_pressure=0;

      inf.cli.number_drug=0;
      inf.cli.text_drug=STR_NULL;
      inf.cli.number_diagnose=0;
      inf.cli.text_diagnose=STR_NULL;
      inf.cli.referring_physician=STR_NULL;
      inf.cli.latest_confirming_physician=STR_NULL;
      inf.cli.technician_description=STR_NULL;
      inf.cli.number_text=0;
      inf.cli.text_free_text=STR_NULL;
      inf.cli.number_hystory=0;
      inf.cli.number_free_hystory=0;
      inf.cli.text_free_medical_hystory=STR_NULL;

      inf.des.acquiring.institution_number=0;
      inf.des.acquiring.department_number=0;
      inf.des.acquiring.ID=0;
      inf.des.acquiring.type=2;
      inf.des.acquiring.manifacturer=0;
      inf.des.acquiring.model_description=STR_NULL;
      inf.des.acquiring.protocol_revision_number=0;
      inf.des.acquiring.category=255;
      inf.des.acquiring.language=255;
      inf.des.acquiring.capability[0]=1;
      inf.des.acquiring.capability[1]=2;
      inf.des.acquiring.capability[2]=3;
      inf.des.acquiring.capability[3]=4;
      inf.des.acquiring.AC=0;
      inf.des.acquiring.analysing_program_revision_number=STR_NULL;
      inf.des.acquiring.serial_number_device=STR_NULL;
      inf.des.acquiring.device_system_software=STR_NULL;
      inf.des.acquiring.device_SCP_implementation_software=STR_NULL;
      inf.des.acquiring.manifacturer_trade_name=STR_NULL;
      inf.des.analyzing.institution_number=0;
      inf.des.analyzing.department_number=0;
      inf.des.analyzing.ID=0;
      inf.des.analyzing.type=2;
      inf.des.analyzing.manifacturer=0;
      inf.des.analyzing.model_description=STR_NULL;
      inf.des.analyzing.protocol_revision_number=0;
      inf.des.analyzing.category=255;
      inf.des.analyzing.language=255;
      inf.des.analyzing.capability[0]=1;
      inf.des.analyzing.capability[1]=2;
      inf.des.analyzing.capability[2]=3;
      inf.des.analyzing.capability[3]=4;
      inf.des.analyzing.AC=0;
      inf.des.analyzing.analysing_program_revision_number=STR_NULL;
      inf.des.analyzing.serial_number_device=STR_NULL;
      inf.des.analyzing.device_system_software=STR_NULL;
      inf.des.analyzing.device_SCP_implementation_software=STR_NULL;
      inf.des.analyzing.manifacturer_trade_name=STR_NULL;
      inf.des.acquiring_institution=STR_NULL;
      inf.des.analyzing_institution=STR_NULL;
      inf.des.acquiring_department=STR_NULL;
      inf.des.analyzing_department=STR_NULL;
      inf.des.room=STR_NULL;
      inf.des.stat_code=0;

      inf.dev.date_acquisition=STR_NULL;
      inf.dev.time_acquisition=STR_NULL;
      inf.dev.baseline_filter=0;
      inf.dev.lowpass_filter=0;
      inf.dev.other_filter[0]=0;
      inf.dev.other_filter[1]=0;
      inf.dev.other_filter[2]=0;
      inf.dev.other_filter[3]=0;
      inf.dev.sequence_number=STR_NULL;
      inf.dev.electrode_configuration.value=0;
      inf.dev.electrode_configuration.unit=0;
      inf.dev.TZ.offset=0;
      inf.dev.TZ.index=0;
      inf.dev.TZ.description=STR_NULL;
}

void section_1(pointer_section info_sections, DATA_INFO &inf)
// section 1
{
      U_int_S tag;
      U_int_L num=info_sections.length+_COUNT_BYTE;
      U_int_M dim=0U;
      int_S version;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version);

      Init_S1(inf);

      do
      {
            ReadByte(tag);
            switch(tag)
            {
                  case 0:
                        section_1_0(inf.ana); break;
                  case 1:
                        section_1_1(inf.ana); break;
                  case 2:
                        section_1_2(inf.ana); break;
                  case 3:
                        section_1_3(inf.ana); break;
                  case 4:
                        section_1_4(inf.ana); break;
                  case 5:
                        section_1_5(inf.ana); break;
                  case 6:
                        section_1_6(inf.ana); break;
                  case 7:
                        section_1_7(inf.ana); break;
                  case 8:
                        section_1_8(inf.ana); break;
                  case 9:
                        section_1_9(inf.ana); break;
                  case 10:
                        if(!inf.cli.number_drug)
                        {
                              inf.cli.drug=NULL;
                              inf.cli.text_drug=NULL;
                              dim=0;
                        }
                        section_1_10(inf.cli,dim); break;
                  case 11:
                        section_1_11(inf.ana); break;
                  case 12:
                        section_1_12(inf.ana); break;
                  case 13:
                        if(!inf.cli.number_diagnose)
                        {
                              inf.cli.diagnose=NULL;
                              inf.cli.text_diagnose=NULL;
                              dim=0;
                        }
                        section_1_13(inf.cli,dim); break;
                  case 14:
                        section_1_14(inf.des); break;
                  case 15:
                        section_1_15(inf.des); break;
                  case 16:
                        section_1_16(inf.des); break;
                  case 17:
                        section_1_17(inf.des); break;
                  case 18:
                        section_1_18(inf.des); break;
                  case 19:
                        section_1_19(inf.des); break;
                  case 20:
                        section_1_20(inf.cli); break;
                  case 21:
                        section_1_21(inf.cli); break;
                  case 22:
                        section_1_22(inf.cli); break;
                  case 23:
                        section_1_23(inf.des); break;
                  case 24:
                        section_1_24(inf.des); break;
                  case 25:
                        section_1_25(inf.dev); break;
                  case 26:
                        section_1_26(inf.dev); break;
                  case 27:
                        section_1_27(inf.dev); break;
                  case 28:
                        section_1_28(inf.dev); break;
                  case 29:
                        section_1_29(inf.dev); break;
                  case 30:
                        if(!inf.cli.number_text)
                        {
                              inf.cli.free_text=NULL;
                              inf.cli.text_free_text=NULL;
                              dim=0;
                        }
                        section_1_30(inf.cli,dim); break;
                  case 31:
                        section_1_31(inf.dev); break;
                  case 32:
                        if(!inf.cli.number_hystory)
                        {
                              inf.cli.medical_hystory=NULL;
                              dim=0;
                        }
                        section_1_32(inf.cli,dim,inf.des.acquiring.protocol_revision_number); break;
                  case 33:
                        section_1_33(inf.dev); break;
                  case 34:
                        section_1_34(inf.dev); break;
                  case 35:
                        if(!inf.cli.number_free_hystory)
                        {
                              inf.cli.free_medical_hystory=NULL;
                              inf.cli.text_free_medical_hystory=NULL;
                              dim=0;
                        }
                        section_1_35(inf.cli,dim); break;
                  case 255:
                        section_1_255(); break;
                  default:
                        section_1_();
                        break;
            }//end switch
      }//end do
      while((tag!=255) && (_COUNT_BYTE<num));
      if ((inf.des.analyzing.protocol_revision_number==0) && (version>0))
            inf.des.analyzing.protocol_revision_number=version;  // by E.C. may 2004 CARDIOLINE 1.0
}//end section_1

void section_1_0(demographic &ana)
// section 1 tag 0
{
      U_int_M dim;

      ReadByte(dim);
      ana.last_name=ReadString(ana.last_name=NULL,dim);
}//end section_1_0

void section_1_1(demographic &ana)
// section 1 tag 1
{
      U_int_M dim;

      ReadByte(dim);
      ana.first_name=ReadString(ana.first_name=NULL,dim);
}//end section_1_1

void section_1_2(demographic &ana)
//section 1 tag 2
{
      U_int_M dim;

      ReadByte(dim);
      ana.ID=ReadString(ana.ID=NULL,dim);
}//end section_1_2

void section_1_3(demographic &ana)
// section 1 tag 3
{
      U_int_M dim;

      ReadByte(dim);
      ana.second_last_name=ReadString(ana.second_last_name=NULL,dim);
}//end section_1_3

void section_1_4(demographic &ana)
// section 1 tag 4
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(ana.age.value);
      ReadByte(ana.age.unit);
      if(ana.age.unit>5)
            ana.age.unit=0;
}//end section_1_4

void section_1_5(demographic &ana)
// section 1 tag 5
{
      U_int_M dim;

      char data[18]; // temp[18];
      U_int_S m, g, num;
      U_int_M a;

      ReadByte(dim);
      ReadByte(a);
      ReadByte(m);
      ReadByte(g);

      sprintf(data,"%u%s%u",g,_month[m].sentence,a);
      num=strlen(data);
      if(num!=0 && (ana.date_birth=(char*)mymalloc(num+1))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      strcpy(ana.date_birth,data);

        struct tm tmf;                      // by E.C. feb 2006
        tmf.tm_year = a - 1900;
        tmf.tm_mon  = m - 1;
        tmf.tm_mday = g;
        tmf.tm_hour = 0;
        tmf.tm_min  = 0;
        tmf.tm_sec  = 0;
        tmf.tm_isdst = 0;
        ana.date_birth2 = mktime(&tmf);    // store date in native format

}//end section_1_5

void section_1_6(demographic &ana)
// section 1 tag 6
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(ana.height.value);
      ReadByte(ana.height.unit);
      if(ana.height.unit>3)
            ana.height.unit=0;
}//end section_1_6

void section_1_7(demographic &ana)
// section 1 tag 7
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(ana.weight.value);
      ReadByte(ana.weight.unit);
      if(ana.weight.unit>4)
            ana.weight.unit=0;
}//end section_1_7

void section_1_8(demographic &ana)
// section 1 tag 8
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(ana.sex);
      if(ana.sex>2)
            ana.sex=3;
}//end section_1_8

void section_1_9(demographic &ana)
// section 1 tag 9
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(ana.race);
      if(ana.race>3)
            ana.race=0;
}//end section_1_9

void section_1_10(clinic &cli, U_int_M &dim)
// section 1 tag 10
{
      U_int_M val;
      U_int_S code_;
      char *temp_string, *pos_char;
      int_M pos;

      ReadByte(val);
      /*
            this tag may have more instances; each instance have a: table code (1 byte), class code (1 byte)
            drug code (1 byte), text description of the drug (at least 1 byte with NULL).
      */
      if(val)
      {
            if((cli.drug=(info_drug*)realloc(cli.drug,sizeof(info_drug)*(cli.number_drug+1)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            ReadByte(cli.drug[cli.number_drug].table);
            ReadByte(code_);
            if(!cli.drug[cli.number_drug].table)
            {
                  pos=Look(class_drug,0,15,code_);
                  if(pos<=0)
                        cli.drug[cli.number_drug].classes=0;
                  else
                        cli.drug[cli.number_drug].classes=pos;
            }
            else
                  cli.drug[cli.number_drug].classes=code_;
            ReadByte(cli.drug[cli.number_drug].drug_code );
            if(!cli.drug[cli.number_drug].table)
            {
                  code_=cli.drug[cli.number_drug].drug_code +256*cli.drug[cli.number_drug].classes;
                  pos=Look(class_drug,16,88,code_);
                  if(pos<0)
                        pos=0;
                  cli.drug[cli.number_drug].drug_code =pos;
            }
            cli.drug[cli.number_drug].length=val-3;        //string length + NULL
            if(cli.drug[cli.number_drug].length)
            {
                  temp_string=ReadString(temp_string=NULL,cli.drug[cli.number_drug].length);
                  strcat(temp_string,STR_END);
                  dim+=strlen(temp_string);
                  if((cli.text_drug=(char*)realloc(cli.text_drug,sizeof(char)*(dim+1)))==NULL)
                  {
                        fprintf(stderr,"Not enough memory");  // no, exit //
                        exit(2);
                  }
                  pos_char=cli.text_drug;
                  pos_char+=dim-strlen(temp_string);
                  strcpy(pos_char,temp_string);
                  free(temp_string);
            }
            cli.number_drug++;
      }
}//end section_1_10

void section_1_11(demographic &ana)
// section 1 tag 11
{
      U_int_M dim;

      ReadByte(dim);
      if(dim)
            ReadByte(ana.systolic_pressure);
      else
            ana.systolic_pressure=0;
}//end section_1_11

void section_1_12(demographic &ana)
// section 1 tag 12
{
      U_int_M dim;

      ReadByte(dim);
      if(dim)
            ReadByte(ana.diastolic_pressure);
      else
            ana.diastolic_pressure=0;
}//end section_1_12

void section_1_13(clinic &cli, U_int_M &dim)
// section 1 tag 13
{
      U_int_M val;
      char *temp_string, *pos_char;

      ReadByte(val);
      if(val)
      {
            if((cli.diagnose=(numeric*)realloc(cli.diagnose,sizeof(numeric)*(cli.number_diagnose+1)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            cli.diagnose[cli.number_diagnose].unit=cli.number_diagnose+1;
            cli.diagnose[cli.number_diagnose].value=val;
            temp_string=ReadString(temp_string=NULL,cli.diagnose[cli.number_diagnose].value);
            strcat(temp_string,STR_END);
            dim+=strlen(temp_string);
            if((cli.text_diagnose=(char*)realloc(cli.text_diagnose,dim+1))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            pos_char=cli.text_diagnose;
            pos_char+=dim-strlen(temp_string);
            strcpy(pos_char,temp_string);
            free(temp_string);
            cli.number_diagnose++;
      }
}//end section_1_13

void section_1_14(descriptive &des)
// section 1 tag 14
{
      U_int_M dim, dim_to_skip;
      U_int_S i, mask, code_;
      int_M pos;
      //fpos_t filepos, filepos_iniz;
      long filepos, filepos_iniz;

      ReadByte(dim);
      filepos = iftell(in); //FGETPOS(in,&filepos);
      //FGETPOS(in,&filepos_iniz);    // by E.C. may 2004 ESAOTE    save to reposition at the end of this section
      filepos_iniz=filepos;
      dim_to_skip=dim;
      dim+=filepos COMPAT;
      ReadByte(des.acquiring.institution_number);
      ReadByte(des.acquiring.department_number);
      ReadByte(des.acquiring.ID);
      ReadByte(des.acquiring.type);
      if(des.acquiring.type>1)
            des.acquiring.type=2;
      ReadByte(des.acquiring.manifacturer);
      if(des.acquiring.manifacturer>20 && des.acquiring.manifacturer!=255)
            des.acquiring.manifacturer=0;
      des.acquiring.model_description=ReadString(des.acquiring.model_description=NULL,6);
      ReadByte(des.acquiring.protocol_revision_number);
      ReadByte(des.acquiring.category);
      pos=Look(compatibility,0,3,des.acquiring.category);
      if(pos<0)
            pos=4;
      des.acquiring.category=pos;
      ReadByte(code_);
      if(code_<128U)
            pos=0;
      else if((code_<192U) && (code_>=128U))
            pos=1;
      else
      {
            pos=Look(language_code,2,15,code_);
            if(pos<0)
                  pos=16;
      }
      des.acquiring.language=pos;
      ReadByte(code_);
      mask=0x10;
      for(i=0;i<4;i++)
      {
            if(code_&mask)
                  des.acquiring.capability[i]=i+4;
            else
                  des.acquiring.capability[i]=i;
            mask<<=1;
      }
      ReadByte(des.acquiring.AC);
      if(des.acquiring.AC>2)
            des.acquiring.AC=0;
      Skip(16);
      des.acquiring.analysing_program_revision_number=NULL;
      des.acquiring.serial_number_device=NULL;
      des.acquiring.device_system_software=NULL;
      des.acquiring.device_SCP_implementation_software=NULL;
      des.acquiring.manifacturer_trade_name=NULL;
      ReadByte(i);
      if(!i)
            des.acquiring.analysing_program_revision_number=NULL;
      else
            des.acquiring.analysing_program_revision_number=ReadString(des.acquiring.analysing_program_revision_number=NULL,i);

      filepos = iftell(in); //FGETPOS(in,&filepos);
      des.acquiring.serial_number_device=FindString(dim-filepos COMPAT);
      if ((des.acquiring.protocol_revision_number==10) || (des.acquiring.protocol_revision_number==11))
                                                                               // by E.C. may 2004 CARDIOLINE 1.0 & ESAOTE 1.1
            ifseek(in,filepos_iniz COMPAT +dim_to_skip,0);   //  reposition file pointer
      else {
            filepos = iftell(in); //FGETPOS(in,&filepos);
            des.acquiring.device_system_software=FindString(dim-filepos COMPAT);
            filepos = iftell(in); //FGETPOS(in,&filepos);
            des.acquiring.device_SCP_implementation_software=FindString(dim-filepos COMPAT);
            filepos = iftell(in); //FGETPOS(in,&filepos);
            des.acquiring.manifacturer_trade_name=FindString(dim-filepos COMPAT);
      }
}//end section_1_14

void section_1_15(descriptive &des)
// section 1 tag 15
{
      U_int_M dim;
      U_int_S i, mask, code_;
      int_M pos;
      //fpos_t filepos;
      long filepos;

      ReadByte(dim);
      filepos = iftell(in); //FGETPOS(in,&filepos);
      dim+=filepos COMPAT;
      ReadByte(des.analyzing.institution_number);
      ReadByte(des.analyzing.department_number);
      ReadByte(des.analyzing.ID);
      ReadByte(des.analyzing.type);
      if(des.analyzing.type>1)
            des.analyzing.type=2;
      ReadByte(des.analyzing.manifacturer);
      if(des.analyzing.manifacturer>20 && des.analyzing.manifacturer!=255)
            des.analyzing.manifacturer=0;
      des.analyzing.model_description=ReadString(des.analyzing.model_description=NULL,6);
      ReadByte(des.analyzing.protocol_revision_number);
      ReadByte(des.analyzing.category);
      pos=Look(compatibility,0,3,des.analyzing.category);
      if(pos<0)
            pos=4;
      des.analyzing.category=pos;
      ReadByte(code_);
      if(code_<128U)
            pos=0;
      else if((code_<192U) && (code_>=128U))
            pos=1;
      else
      {
            pos=Look(language_code,2,15,code_);
            if(pos<0)
                  pos=16;
      }
      des.analyzing.language=pos;
      ReadByte(code_);
      mask=0x10;
      for(i=0;i<4;i++)
      {
            if(code_&mask)
                  des.analyzing.capability[i]=i+4;
            else
                  des.analyzing.capability[i]=i;
            mask<<=1;
      }
      ReadByte(des.analyzing.AC);
      if(des.analyzing.AC>2)
            des.analyzing.AC=0;
      Skip(16);
      des.analyzing.analysing_program_revision_number=NULL;
      des.analyzing.serial_number_device=NULL;
      des.analyzing.device_system_software=NULL;
      des.analyzing.device_SCP_implementation_software=NULL;
      des.analyzing.manifacturer_trade_name=NULL;

      ReadByte(i);
      if(!i)
            des.analyzing.analysing_program_revision_number=NULL;
      else
            des.analyzing.analysing_program_revision_number=ReadString(des.analyzing.analysing_program_revision_number=NULL,i);

      filepos = iftell(in); //FGETPOS(in,&filepos);
      des.analyzing.serial_number_device=FindString(dim-filepos COMPAT);
      filepos = iftell(in); //FGETPOS(in,&filepos);
      des.analyzing.device_system_software=FindString(dim-filepos COMPAT);
      filepos = iftell(in); //FGETPOS(in,&filepos);
      des.analyzing.device_SCP_implementation_software=FindString(dim-filepos COMPAT);
      filepos = iftell(in); //FGETPOS(in,&filepos);
      des.analyzing.manifacturer_trade_name=FindString(dim-filepos COMPAT);
}//end section_1_15

void section_1_16(descriptive &des)
// section 1 tag 16
{
      U_int_M dim;

      ReadByte(dim);
      des.acquiring_institution=ReadString(des.acquiring_institution=NULL,dim);
}//end section_1_16

void section_1_17(descriptive &des)
// section 1 tag 17
{
      U_int_M dim;

      ReadByte(dim);
      des.analyzing_institution=ReadString(des.analyzing_institution=NULL,dim);
}//end section_1_17

void section_1_18(descriptive &des)
// section 1 tag 18
{
      U_int_M dim;

      ReadByte(dim);
      des.acquiring_department=ReadString(des.acquiring_department=NULL,dim);
}//end section_1_18

void section_1_19(descriptive &des)
// section 1 tag 19
{
      U_int_M dim;

      ReadByte(dim);
      des.analyzing_department=ReadString(des.analyzing_department=NULL,dim);
}//end section_1_19

void section_1_20(clinic &cli)
// section 1 tag 20
{
      U_int_M dim;

      ReadByte(dim);
      cli.referring_physician=ReadString(cli.referring_physician=NULL,dim);
}//end section_1_20

void section_1_21(clinic &cli)
// section 1 tag 21
{
      U_int_M dim;

      ReadByte(dim);
      cli.latest_confirming_physician=ReadString(cli.latest_confirming_physician=NULL,dim);
}//end section_1_21

void section_1_22(clinic &cli)
// section 1 tag 22
{
      U_int_M dim;

      ReadByte(dim);
      cli.technician_description=ReadString(cli.technician_description=NULL,dim);
}//end section_1_22

void section_1_23(descriptive &des)
// section 1 tag 23
{
      U_int_M dim;

      ReadByte(dim);
      des.room=ReadString(des.room=NULL,dim);
}//end section_1_23

void section_1_24(descriptive &des)
// section 1 tag 24
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(des.stat_code);
}//end section_1_24

void section_1_25(device &dev)
// section 1 tag 25
{
      U_int_M dim;
      char data[18];
      U_int_S m, g, num;
      U_int_M a;

      ReadByte(dim);
      ReadByte(a);
      ReadByte(m);
      ReadByte(g);
      
      sprintf(data,"%u%s%u",g,_month[m].sentence,a);
      num=strlen(data);                                               // by E.C. may 2004
      if(num!=0 && (dev.date_acquisition=(char*)mymalloc(num+1))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      strcpy(dev.date_acquisition,data);

        struct tm tmf;                      // by E.C. feb 2006
        tmf.tm_year = a - 1900;
        tmf.tm_mon  = m - 1;
        tmf.tm_mday = g;
        tmf.tm_hour = 0;
        tmf.tm_min  = 0;
        tmf.tm_sec  = 0;
        tmf.tm_isdst = 0;
        dev.date_acquisition2 = mktime(&tmf);    // store date in native format

}//end section_1_25

void section_1_26(device &dev)
// section 1 tag 26
{
      U_int_M dim;
      char hour[9];
      U_int_S h, m, s, num;

      ReadByte(dim);
      ReadByte(h);
      ReadByte(m);
      ReadByte(s);
      
      sprintf(hour,"%u:%u:%u",h,m,s);
      num=strlen(hour);                                               // by E.C. may 2004
      if(num!=0 && (dev.time_acquisition=(char*)mymalloc(num+1))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      strcpy(dev.time_acquisition,hour);
        dev.time_acquisition2 = (time_t) (s + m*(60 + h*24));   // by E.C. feb 2006 time in seconds
}//end section_1_26

void section_1_27(device &dev)
// section 1 tag 27
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(dev.baseline_filter);
}//end section_1_27

void section_1_28(device &dev)
// section 1 tag 28
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(dev.lowpass_filter);
}//end section_1_28

void section_1_29(device &dev)
// section 1 tag 29
{
      U_int_M dim;
      U_int_S mask=0x1, val, i, max=4, ris=0;

      ReadByte(dim);
      ReadByte(val);
      for(i=0;i<max;i++)
      {
            if(val&mask)
                  dev.other_filter[i]=i+1;
            else
                  dev.other_filter[i]=0;
            ris|=val&mask;
            mask<<=1;
      }
      int w=dim;
      while (--w) ReadByte(val);        // by E.C. may 2004 CARDIOLINE 1.0
}//end section_1_29

void section_1_30(clinic &cli, U_int_M &dim)
// section 1 tag 30
{
      U_int_M val;
      char *temp_string, *pos_char;

      ReadByte(val);
      if(val)
      {
            if((cli.free_text=(numeric*)realloc(cli.free_text,sizeof(numeric)*(cli.number_text+1)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            cli.free_text[cli.number_text].unit=cli.number_text+1;
            cli.free_text[cli.number_text].value=val;
            temp_string=ReadString(temp_string=NULL,cli.free_text[cli.number_text].value);
            strcat(temp_string,STR_END);
            dim+=strlen(temp_string);
            if((cli.text_free_text=(char*)realloc(cli.text_free_text,dim+1))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            pos_char=cli.text_free_text;
            pos_char+=dim-strlen(temp_string);
            strcpy(pos_char,temp_string);
            free(temp_string);
            cli.number_text++;
      }
}//end section_1_30

void section_1_31(device &dev)
// section 1 tag 31
{
      U_int_M dim;

      ReadByte(dim);
      if(dim)
            dev.sequence_number=ReadString(dev.sequence_number=NULL,dim);
      else
            dev.sequence_number=STR_NULL;
}//end section_1_31

void section_1_32(clinic &cli, U_int_M &dim, int_S version)
// section 1 tag 32
{
      U_int_M val;
      U_int_S pos;
      int_M ris;

      ReadByte(val);
      if(val)
      {
            dim+=val;
            //first byte designates the Diagnostic Code Table which is applied; if 0 then the codes used are documented in the standard book.
            // second byte is the code
            if((cli.medical_hystory=(numeric*)realloc(cli.medical_hystory,sizeof(numeric)*(cli.number_hystory+1)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            ReadByte(pos);
            cli.medical_hystory[cli.number_hystory].value=pos;
            if (version != 10) {
                  ReadByte(pos);                 // 1 byte vers. 1.0; 2 byte vers. 2.0 by E.C. may 2004
                  ris=Look(_hystory,0,26,pos);
                  if(ris<0)
                        pos=26;
                  else
                        pos=ris;
                  cli.medical_hystory[cli.number_hystory].unit=pos;
            }
            cli.number_hystory++;
      }
}//end section_1_32

void section_1_33(device &dev)
// section 1 tag 33
{
      U_int_M dim;
      U_int_S pos;

      ReadByte(dim);
      ReadByte(pos);
      if(pos>6)
            pos=0;
      dev.electrode_configuration.value=pos;

      ReadByte(pos);
      if(pos>6)
            pos=0;
      dev.electrode_configuration.unit=pos;
}//end section_1_33

void section_1_34(device &dev)
// section 1 tag 34
{
      U_int_M dim;

      ReadByte(dim);
      ReadByte(dev.TZ.offset); //complemented if negative
      ReadByte(dev.TZ.index);
      if(dim-4)
            dev.TZ.description = FindString(dim-4);
      else
            dev.TZ.description = "-";
}//end section_1_34

void section_1_35(clinic &cli, U_int_M &dim)
// section 1 tag 35
{
      U_int_M val;
      char *temp_string, *pos_char;

      ReadByte(val);
      if(val)
      {
            if((cli.free_medical_hystory=(numeric*)realloc(cli.free_medical_hystory,sizeof(numeric)*(cli.number_free_hystory+1)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            cli.free_medical_hystory[cli.number_free_hystory].unit=cli.number_free_hystory+1;
            cli.free_medical_hystory[cli.number_free_hystory].value=val;
            temp_string=ReadString(temp_string=NULL,cli.free_medical_hystory[cli.number_free_hystory].value);
            strcat(temp_string,STR_END);
            dim+=strlen(temp_string);
            if((cli.text_free_medical_hystory=(char*)realloc(cli.text_free_medical_hystory,dim+1))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            pos_char=cli.text_free_medical_hystory;
            pos_char+=dim-strlen(temp_string);
            strcpy(pos_char,temp_string);
            free(temp_string);
            cli.number_free_hystory++;
      }
}//end section_1_35

void section_1_()
// section 1 tag 36..254 are manufacturer specifics and are not utilized
{
      U_int_M dim;

      ReadByte(dim);
      Skip(dim);
}//end section_1_

void section_1_255()
// section 1 tag 255
{
      U_int_M dim;

      ReadByte(dim);
}//end section_1_255
#endif 

//______________________________________________________________________________
//                              section 2
//______________________________________________________________________________

void section_2(pointer_section info_sections,DATA_DECODE &data)
//build Huffman tables if included in the file; if none then use del default one
//cannot read the dummy Huffman table
{
      U_int_M nt, i, j, ns=0, pos, dim;
      //fpos_t filepos;
      long filepos;
      int_S version;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version);
      dim=info_sections.length-16;

      ReadByte(nt);
      if(nt!=19999U)
      {
            if((data.flag_Huffman=(U_int_M*)mymalloc(sizeof(U_int_M)*(nt+1)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            data.flag_Huffman[0]=nt;
            filepos = iftell(in); //FGETPOS(in,&filepos);
            for(i=1;i<=data.flag_Huffman[0];i++)
            {
                  ReadByte(data.flag_Huffman[i]);
                  ns+=data.flag_Huffman[i];
                  Skip(9*data.flag_Huffman[i]);
            }
            ifseek(in,filepos COMPAT,0);
            if((ns*9)>dim || !ns)
            {
                  fprintf(stderr,"Cannot read data!!!");
                  exit(2);
            }
            if(ns!=0 && (data.t_Huffman=(table_H*)mymalloc(sizeof(table_H)*ns))==NULL)         //array of 5 columns and ns rows
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            pos=0;
            for(j=0;j<data.flag_Huffman[0];j++)
            {
                  Skip(2);
                  for(i=0;i<data.flag_Huffman[j+1];i++)
                  {
                        ReadByte(data.t_Huffman[pos+i].bit_prefix);
                        ReadByte(data.t_Huffman[pos+i].bit_code);
                        ReadByte(data.t_Huffman[pos+i].TMS);
                        ReadByte(data.t_Huffman[pos+i].base_value);
                        ReadByte(data.t_Huffman[pos+i].base_code);
                  }
                  pos+=data.flag_Huffman[j+1]*9;         // by E.C. may 2004
            }
      }
      else
      {
            if((data.flag_Huffman=(U_int_M*)mymalloc(sizeof(U_int_M)*2))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            data.flag_Huffman[0]=1;
            data.flag_Huffman[1]=19;      //number of rows of the default Huffman table
            if((data.t_Huffman=(table_H*)mymalloc(sizeof(table_H)*data.flag_Huffman[1]))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            InitHuffman(data.t_Huffman);
      }
}//end section_2

//______________________________________________________________________________
//                              section 3
//______________________________________________________________________________

void section_3(pointer_section info_sections,DATA_DECODE &data, int_S version)
{
      U_int_S val, mask=0x1, i;
      int_S version_loc;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version_loc);

      ReadByte(data.flag_lead.number);
      ReadByte(val);
      if(val&mask)
            data.flag_lead.subtraction=1;
      else
            data.flag_lead.subtraction=0;
      mask<<=2;
      if(val&mask)
            data.flag_lead.all_simultaneously=1;
      else
            data.flag_lead.all_simultaneously=0;
      data.flag_lead.number_simultaneously=(val&0xF8)>>3;

      if (version==11)                        // by E.C. may 2004 ESAOTE
            data.flag_lead.number_simultaneously=8;

      if(data.flag_lead.number!=0 && (data.data_lead=(lead*)mymalloc(sizeof(lead)*data.flag_lead.number))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      for(i=0;i<data.flag_lead.number;i++)
      {
            ReadByte(data.data_lead[i].start);
            ReadByte(data.data_lead[i].end);
            ReadByte(data.data_lead[i].ID);
            if(data.data_lead[i].ID>85)
                  data.data_lead[i].ID=0;
      }
}//end section_3

//______________________________________________________________________________
//                              section 4
//______________________________________________________________________________

void section_4(pointer_section info_sections,DATA_DECODE &data,int_S version)
{
      U_int_M i;
      int_S version_loc;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version_loc);

      ReadByte(data.flag_BdR0.length);
      ReadByte(data.flag_BdR0.fcM);
      ReadByte(data.flag_Res.number);
      if(data.flag_Res.bimodal || data.flag_lead.subtraction)     // by E.C. may 2004
      {
            if(data.flag_Res.number!=0 && (data.data_subtraction=(Subtraction_Zone*)mymalloc(sizeof(Subtraction_Zone)*data.flag_Res.number))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            for(i=0;i<data.flag_Res.number;i++)
            {
                  ReadByte(data.data_subtraction[i].beat_type);
                  ReadByte(data.data_subtraction[i].SB);
                  ReadByte(data.data_subtraction[i].fc);
                  ReadByte(data.data_subtraction[i].SE);
            }//end for
      }//end if
      if(data.flag_Res.bimodal || data.flag_lead.subtraction)     // by E.C. may 2004
      {
            if(data.flag_Res.number!=0 && (data.data_protected=(Protected_Area*)mymalloc(sizeof(Protected_Area)*data.flag_Res.number))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            for(i=0;i<data.flag_Res.number;i++)
                  if ((version==10) || (version==11)) {               // by E.C. may 2004 SCP 1.0 no data 
                        data.data_protected[i].QB=data.data_subtraction[i].SB;
                        data.data_protected[i].QE=data.data_subtraction[i].SE;
                  } else {
                        ReadByte(data.data_protected[i].QB);
                        ReadByte(data.data_protected[i].QE);
                  }//end if/for
      }//end if
}//end section_4

//______________________________________________________________________________
//                              section 5
//______________________________________________________________________________

bool section_5(pointer_section info_sections,DATA_DECODE &data, bool sez2)
{
      U_int_M i;
      U_int_L t, dim;
      U_int_M value;
      int_S version;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version);

      ReadByte(data.flag_BdR0.AVM);
      ReadByte(data.flag_BdR0.STM);
      ReadByte(data.flag_BdR0.encoding);
      if(data.flag_BdR0.encoding>2)
            data.flag_BdR0.encoding=0;
      Skip(1);
      if(data.flag_lead.number!=0 && (data.length_BdR0=(U_int_M*)mymalloc(sizeof(U_int_M)*data.flag_lead.number))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      dim=0;
      for(i=0;i<data.flag_lead.number;i++)
      {
            ReadByte(data.length_BdR0[i]);     //number of samples (2 bytes each) for each lead
            dim+=data.length_BdR0[i];
      }
        if (data.flag_BdR0.length==0) return false;      // by E.C. 12/09/2007
      if(sez2)
      {
            data.flag_BdR0.number_samples=(U_int_L)data.flag_BdR0.length*1000L/(U_int_L)data.flag_BdR0.STM;           //number di campioni per elettrodo
            dim*=sizeof(U_int_S);
            if(dim!=0 && (data.samples_BdR0=(U_int_S*)mymalloc(dim))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            ifread(data.samples_BdR0,sizeof(U_int_S),dim,in);
      }
      else
      {
            data.flag_BdR0.number_samples=dim/(sizeof(int_M)*data.flag_lead.number);       //number of samples per lead
            dim>>=1;
            dim*=sizeof(int_L);
            if(dim!=0 && (data.Median=(int_L*)mymalloc(dim))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            dim/=sizeof(int_L);
            for(t=0;t<dim;t++)
            {
                  ReadByte(value);
                  data.Median[t]=value;
                  if(value>0x7FFF)
                        data.Median[t]|=0xFFFF0000;
            }
      }
        return true;
}//end section_5

//______________________________________________________________________________
//                              section 6
//______________________________________________________________________________

void section_6(pointer_section info_sections,DATA_DECODE &data, bool sez2)
{
      U_int_M i;
      U_int_L t, dim;
      U_int_M value;
      int_S version;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version);

      ReadByte(data.flag_Res.AVM);
      ReadByte(data.flag_Res.STM);
      ReadByte(data.flag_Res.encoding);
      if(data.flag_Res.encoding>2)
            data.flag_Res.encoding=0;
      Skip(1);
      if(data.flag_lead.number!=0 && (data.length_Res=(U_int_M*)mymalloc(sizeof(U_int_M)*data.flag_lead.number))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      dim=0;
      for(i=0;i<data.flag_lead.number;i++)
      {
            ReadByte(data.length_Res[i]);     //number of bytes for each lead
            dim+=data.length_Res[i];
      }
      if(sez2)
      {
            data.flag_Res.number_samples=data.data_lead[1].end-data.data_lead[1].start+1; //number of samples after interpolation
            dim*=sizeof(U_int_S);
            if(dim!=0 && (data.samples_Res=(U_int_S*)mymalloc(dim))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            ifread(data.samples_Res,sizeof(U_int_S),dim,in);
      }
      else
      {
            data.flag_Res.number_samples=dim/(sizeof(int_M)*data.flag_lead.number);       //number of samples per lead
            dim>>=1;
            dim*=sizeof(int_L);
            if(dim!=0 && (data.Residual=(int_L*)mymalloc(dim))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            dim/=sizeof(int_L);
            for(t=0;t<dim;t++)
            {
                  ReadByte(value);
                  data.Residual[t]=value;
                  if(value>0x7FFF)
                        data.Residual[t]|=0xFFFF0000;
            }
      }
}//end section_6

#ifdef WITH_OBSOLETE_PARTS

//______________________________________________________________________________
//                              section 7
//______________________________________________________________________________

void section_7(pointer_section info_sections ,DATA_RECORD &data, int_S version)
{
      U_int_M i, j, dim;
      U_int_S lung;
      //fpos_t filepos;
      long filepos;
      int_S version_loc;
      int_L length_eval;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version_loc);

      ReadByte(data.data_global.number);
      //each value should be checked in _special!
      ReadByte(data.data_global.number_spike);
      if (version==11) ReadByte(data.data_global.number_spike);       // by E.C. may 2004 x ESAOTE!! This is an implementation error, for sure!
      ReadByte(data.data_global.average_RR);
      ReadByte(data.data_global.average_PP);
      if(Look(_special,0,3,data.data_global.number)<0)
      {
            if(data.data_global.number!=0 && (data.data_BdR=(BdR_measurement*)mymalloc(sizeof(BdR_measurement)*data.data_global.number))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            for(i=0;i<data.data_global.number;i++)
            {
                  ReadByte(data.data_BdR[i].P_onset);
                  ReadByte(data.data_BdR[i].P_offset);
                  ReadByte(data.data_BdR[i].QRS_onset);
                  ReadByte(data.data_BdR[i].QRS_offset);
                  ReadByte(data.data_BdR[i].T_offset);
                  ReadByte(data.data_BdR[i].P_axis);
                  ReadByte(data.data_BdR[i].QRS_axis);
                  ReadByte(data.data_BdR[i].T_axis);
            }//end for
      }
      if(Look(_special,0,3,data.data_global.number_spike)<0)
      {
            if(data.data_global.number_spike!=0 && (data.data_spike=(spike*)mymalloc(sizeof(spike)*data.data_global.number_spike))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            //spike time is in ms from the start of recording
            //amplitude is in signed uV
            for(i=0;i<data.data_global.number_spike;i++)
            {
                  ReadByte(data.data_spike[i].time);
                  ReadByte(data.data_spike[i].amplitude);
            }//end for
            for(i=0;i<data.data_global.number_spike;i++)
            {
                  ReadByte(data.data_spike[i].type);
                  if(data.data_spike[i].type>3)
                        data.data_spike[i].type=0;
                  ReadByte(data.data_spike[i].source);
                  if(data.data_spike[i].source>2)
                        data.data_spike[i].source=0;
                  ReadByte(data.data_spike[i].index);
                  ReadByte(data.data_spike[i].pulse_width);
            }//end for
      }//end if
      if (version<13) {          // by E.C. may 2004    CARDIOLINE & ESAOTE missing!!
            if ((data.data_global.average_RR>0) &&
                  (data.data_global.average_RR<10000))
                  data.data_global.ventricular_rate=60000.0/data.data_global.average_RR+0.5;
            return;
      }
// Insert by F.C.
      if (version>=13) {
            length_eval = 16 + 6 + data.data_global.number * 16 + data.data_global.number_spike * 4 + data.data_global.number_spike * 6;
            if (length_eval >= info_sections.length)
                  return;
      }
// End of F.C. insertion
      ReadByte(data.data_global.number_QRS);
        if (data.data_global.number_QRS==29999) return;    // by E.C.  12/09/2007
      if(Look(_special,0,3,data.data_global.number_QRS)<0)
      {
            filepos = iftell(in); //FGETPOS(in,&filepos);                         //necessary for ESAOTE and CARDIOLINE test files
            dim=info_sections.index+info_sections.length-filepos COMPAT+1;
            if(data.data_global.number_QRS>dim)
            {
                  fprintf(stderr,"Error: Cannot extract these data!!!");
                  exit(2);                                      //necessary for ESAOTE and CARDIOLINE test files
            } 
            if(data.data_global.number_QRS!=0 && (data.type_BdR=(U_int_S*)mymalloc(sizeof(U_int_S)*data.data_global.number_QRS))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            for(i=0;i<data.data_global.number_QRS;i++)
                  ReadByte(data.type_BdR[i]);
      }
// Insert by F.C.
      if (version>=13) {
            length_eval += (2 + data.data_global.number_QRS);
            if (length_eval >= info_sections.length)
                  return;
      }
// End of F.C. insertion
      ReadByte(data.data_global.ventricular_rate);
      ReadByte(data.data_global.atrial_rate);
      ReadByte(data.data_global.QT_corrected);
      ReadByte(data.data_global.formula_type);
      if(data.data_global.formula_type>2)
            data.data_global.formula_type=0;
      ReadByte(data.data_global.number_tag);
      if(data.data_global.number_tag)
      {
            data.data_global.number_tag-=2;
            data.data_global.number_tag/=7; // tag number 
            //warnig: this calculation is relative to the structure of STANDARD v2.0!
            if(data.data_global.number_tag!=0 && (data.data_additional=(additional_measurement*)mymalloc(sizeof(additional_measurement)*data.data_global.number_tag))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            for(i=0;i<data.data_global.number_tag;i++)
            {
                  ReadByte(data.data_additional[i].ID);
                  if(data.data_additional[i].ID==255)
                        break;
                  if(data.data_additional[i].ID>3)
                        data.data_additional[i].ID=4;
                  ReadByte(lung);
                  if(lung)
                  {
                        //warning:(255 is undefined)
                        for(j=0;j<5;j++)
                              ReadByte(data.data_additional[i].byte[j]);
                  }//end if
            }//end for
      }//end if
}//end section_7

//______________________________________________________________________________
//                              section 8
//______________________________________________________________________________

void section_8(pointer_section info_sections,DATA_INFO &data)
{
      U_int_S m, g, h, s, i;
      U_int_M a, num, dim;
      char dates[18], hour[9], *temp_string, *c;
      //fpos_t filepos;
      long filepos;
      int_S version;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version);

      ReadByte(data.flag_report.type);
      if(data.flag_report.type>2)
            data.flag_report.type=3;
      ReadByte(a);
      ReadByte(m);
      ReadByte(g);
      
      sprintf(dates,"%u%s%u",g,_month[m].sentence,a);
      num=strlen(dates);                                          // by E.C. may 2004
      if(num!=0 && (data.flag_report.date=(char*)mymalloc(num+1))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      strcpy(data.flag_report.date,dates);
      ReadByte(h);
      ReadByte(m);
      ReadByte(s);
      
      sprintf(hour,"%u:%u:%u",h,m,s);
      num=strlen(hour);                                              // by E.C. may 2004
      if(num!=0 && (data.flag_report.time=(char*)mymalloc(num+1))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      strcpy(data.flag_report.time,hour);
      ReadByte(data.flag_report.number);
      if(data.flag_report.number)
      {
            filepos = iftell(in); //FGETPOS(in,&filepos);
            if(data.flag_report.number!=0 && (data.text_dim=(numeric*)mymalloc(data.flag_report.number*sizeof(numeric)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            dim=0;
            for(i=0;i<data.flag_report.number;i++)
            {
                  //this should start with 1, but I documented 0!!
                  ReadByte(data.text_dim[i].unit);   //sequence number
                  ReadByte(data.text_dim[i].value);  //length
                  dim+=data.text_dim[i].value;
                  Skip(data.text_dim[i].value);
            }
            ifseek(in,filepos COMPAT,0);
            if(dim!=0 && (data.text_report=(char*)mymalloc((dim+1)*sizeof(char)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            c=data.text_report;
            for(i=0;i<data.flag_report.number;i++)
            {
                  Skip(3);
                  temp_string=ReadString(temp_string=NULL,data.text_dim[i].value);
                  strcat(temp_string,STR_END);
                  strcpy(c,temp_string);
                  c+=strlen(temp_string);
                  free(temp_string);
            }//end for
      }
}//end section_8

//______________________________________________________________________________
//                              section 10
//______________________________________________________________________________

void section_10(pointer_section info_sections, DATA_RECORD &data, int_S version)
{
      U_int_M dim, n1, n2, i, j, k, id, val, mask;
      int_M skip;
      int_S version_loc;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version_loc);

      ReadByte(data.header_lead.number_lead);
      ReadByte(dim);
      if(dim<6)      //no measures
      {
            if (version != 10) {
                  fprintf(stderr,"Error: no measures or cannot extract section 10 data!!!");
                  return;       // by E.C. 12/09/2007
            }
      }
      n1=(dim>>1)-2;
      if(n1>31)     // for now 33 are defined
            n1=31;       //ignore next bytes
      data.header_lead.number_lead_measurement=n1; //max number of statements by the manufacturer (2 bytes each)
      if(data.header_lead.number_lead)                // by E.C. 17.11.2003   deleted "!" in the if
      {
            if((data.lead_block=(lead_measurement_block*)mymalloc(data.header_lead.number_lead*sizeof(lead_measurement_block)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            for(i=0;i<data.header_lead.number_lead;i++)
            {
                  if(data.header_lead.number_lead_measurement)        // by E.C. 17.11.2003   deleted "!" in the if
                  {
                        ReadByte(id);
                        if(id>85)
                              id=0;
                        ReadByte(dim);
                        n2=(dim>>1);
                        if(n2>n1)
                              skip=(n2-n1)<<1;     // bytes to skip
                        else
                              skip=0;
                        data.lead_block[i].ID=id;
                        //warnig: values relative to _SPECIAL
                        for(j=1;j<=data.header_lead.number_lead_measurement;j++)
                        {
                              switch(j)
                              {
                                    case  1:    ReadByte(data.lead_block[i].P_duration);
                                                      break;
                                    case  2:    ReadByte(data.lead_block[i].PR_interval);
                                                      break;
                                    case  3:    ReadByte(data.lead_block[i].QRS_duration);
                                                      break;
                                    case  4:    ReadByte(data.lead_block[i].QT_interval);
                                                      break;
                                    case  5:    ReadByte(data.lead_block[i].Q_duration);
                                                      break;
                                    case  6:    ReadByte(data.lead_block[i].R_duration);
                                                      break;
                                    case  7:    ReadByte(data.lead_block[i].S_duration);
                                                      break;
                                    case  8:    ReadByte(data.lead_block[i].R1_duration);
                                                      break;
                                    case  9:    ReadByte(data.lead_block[i].S1_duration);
                                                      break;
                                    case 10:    ReadByte(data.lead_block[i].Q_amplitude);
                                                      break;
                                    case 11:    ReadByte(data.lead_block[i].R_amplitude);
                                                      break;
                                    case 12:    ReadByte(data.lead_block[i].S_amplitude);
                                                      break;
                                    case 13:    ReadByte(data.lead_block[i].R1_amplitude);
                                                      break;
                                    case 14:    ReadByte(data.lead_block[i].S1_amplitude);
                                                      break;
                                    case 15:    ReadByte(data.lead_block[i].J_point_amplitude);
                                                      break;
                                    case 16:    ReadByte(data.lead_block[i].Pp_amplitude);
                                                      break;
                                    case 17:    ReadByte(data.lead_block[i].Pm_amplitude);
                                                      break;
                                    case 18:    ReadByte(data.lead_block[i].Tp_amplitude);
                                                      break;
                                    case 19:    ReadByte(data.lead_block[i].Tm_amplitude);
                                                      break;
                                    case 20:    ReadByte(data.lead_block[i].ST_slope);
                                                      break;
                                    case 21:    ReadByte(data.lead_block[i].P_morphology);
                                                      if(data.lead_block[i].P_morphology)
                                                            data.lead_block[i].P_morphology=0;
                                                      break;
                                    case 22:    ReadByte(data.lead_block[i].T_morphology);
                                                      if(data.lead_block[i].T_morphology)
                                                            data.lead_block[i].T_morphology=0;
                                                      break;
                                    case 23:    ReadByte(data.lead_block[i].iso_electric_segment_onset_QRS);
                                                      break;
                                    case 24:    ReadByte(data.lead_block[i].iso_electric_segment_offset_QRS);
                                                      break;
                                    case 25:    ReadByte(data.lead_block[i].intrinsicoid_deflection);
                                                      break;
                                    case 26:    ReadByte(val);
                                                      mask=0x3;
                                                      for(k=0;k<8;k++)
                                                      {
                                                            data.lead_block[i].quality_recording[k]=mask&val;
                                                            mask<<2;
                                                      }
                                                      break;
                                    case 27:    ReadByte(data.lead_block[i].ST_amplitude_Jplus20);
                                                      break;
                                    case 28:    ReadByte(data.lead_block[i].ST_amplitude_Jplus60);
                                                      break;
                                    case 29:    ReadByte(data.lead_block[i].ST_amplitude_Jplus80);
                                                      break;
                                    case 30:    ReadByte(data.lead_block[i].ST_amplitude_JplusRR16);
                                                      break;
                                    case 31:    ReadByte(data.lead_block[i].ST_amplitude_JplusRR8);
                                                      break;
                              }//end switch
                        }//end for
                        if(skip)
                              Skip(skip);
                  }//end if
            }//end for
      }//end if
}//end section_10

//______________________________________________________________________________
//                              section 11
//______________________________________________________________________________

void section_11(pointer_section info_sections,DATA_INFO &data)
/*
      expressions (ASCII) should be either:
            1) diagnostic statement_probability _modifiers;
            2) diagnostic statement_probability _modifier_conjunctive term_diagnostic statement_probability _modifier...;
      in the test files I found only 1 diagnostic statement per expression, ending with a NULL.
*/
{
      U_int_S m, g, h, s, i, j;
      U_int_M a, num, dim;
      char dates[8], hour[9], *temp_string, *punt, c;
      //fpos_t filepos;
      long filepos;
      int_S version;

      _COUNT_BYTE=info_sections.index;
      ifseek(in,info_sections.index-1,0);
      ID_section(info_sections.index, version);

      ReadByte(data.flag_statement.type);
      if(data.flag_statement.type>2)
            data.flag_statement.type=3;
      ReadByte(a);
      ReadByte(m);
      ReadByte(g);
      
      sprintf(dates,"%u%s%u",g,_month[m].sentence,a);
      num=strlen(dates);                                      // by E.C. may 2004
      if(num!=0 && (data.flag_statement.date=(char*)mymalloc(num+1))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      strcpy(data.flag_statement.date,dates);
      ReadByte(h);
      ReadByte(m);
      ReadByte(s);
      
      sprintf(hour,"%u:%u:%u",h,m,s);     
      num=strlen(hour);                                           // by E.C. may 2004
      if(num!=0 && (data.flag_statement.time=(char*)mymalloc(num+1))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      strcpy(data.flag_statement.time,hour);

      ReadByte(data.flag_statement.number); //number of expressions
      if(!data.flag_statement.number)
      {
            filepos = iftell(in); //FGETPOS(in,&filepos);
            if(data.flag_statement.number!=0 && (data.data_statement=(statement_coded*)mymalloc(data.flag_statement.number*sizeof(statement_coded)))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            dim=0;
            for(i=0;i<data.flag_statement.number;i++)
            {
                  ReadByte(data.data_statement[i].sequence_number);
                  ReadByte(data.data_statement[i].length);
                  dim+=data.data_statement[i].length-1;
                  ReadByte(data.data_statement[i].type);
                  data.data_statement[i].number_field=1;
                  if(data.data_statement[i].type==1)
                  {
                        for(j=1;j<(data.data_statement[i].length-1);j++)
                        {
                              c=ifgetc(in);
                              if(c=='\0')
                                    ++data.data_statement[i].number_field;
                        }
                  }
                  else
                        Skip(data.data_statement[i].length-1);
            }
            ifseek(in,filepos COMPAT,0);
            if(dim!=0 && (data.text_statement=(char*)mymalloc(dim))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            punt=data.text_statement;
            for(i=0;i<data.flag_statement.number;i++)
            {
                  Skip(4);
                  if(data.data_statement[i].type==1)
                  {
                        dim=data.data_statement[i].length;
                        for(j=0;j<data.data_statement[i].number_field;j++)
                        {
                              temp_string=FindString(dim);
                              strcat(temp_string,STR_END);
                              strcpy(punt,temp_string);
                              punt+=strlen(temp_string);
                              dim-=strlen(temp_string);
                              free(temp_string);
                        }
                  }
                  else
                  {
                        temp_string=ReadString(temp_string=NULL,data.data_statement[i].length);
                        strcat(temp_string,STR_END);
                        strcpy(punt,temp_string);
                        punt+=strlen(temp_string);
                        free(temp_string);
                  }
            }//end for
      }//end if
}//end section_11

#endif 

//______________________________________________________________________________
//                              CALCULATIONS
//______________________________________________________________________________

//______________________________________________________________________________
//                      MULTIPLICATION BY AVM
void Multiply(int_L *dati, U_int_L num, U_int_M AVM)
{
      U_int_L i;


      for(i=0;i<num;i++)
            dati[i]=dati[i]*AVM;   // AS 2007: scale in nV - no round of errors
}//end Multiply

//______________________________________________________________________________
//                      FIRST AND SECOND DIFFERENCES
template<class t1>
void Differences(int_L *dati, t1 flag, U_int_S num)
{
      U_int_S i;
      U_int_M j;

      for(i=0;i<num;i++)
            for(j=flag.encoding;j<flag.number_samples;j++)
                  if(flag.encoding==1)
                        dati[(j+flag.number_samples*i)]+=dati[(j+flag.number_samples*i)-1];
                  else
                        dati[(j+flag.number_samples*i)]+=(dati[(j+flag.number_samples*i)-1]<<1)-dati[(j+flag.number_samples*i)-2];
}//end Differences

//______________________________________________________________________________
//                              HUFFMAN DECODING
void Tree_Destroy(TREE_NODE *radix)
{
      if (radix!=NULL)
      {
            Tree_Destroy(radix->next_0);
            Tree_Destroy(radix->next_1);
            free(radix);
      }
      return;
}

TREE_NODE *Tree_Create(TREE_NODE *tree, U_int_M n_of_struct, table_H *table, U_int_M pos)
//build a tree
{
      U_int_S i,j;
      U_int_L mask;
      TREE_NODE *temp;

      //build the root
      if((tree=(TREE_NODE *)mymalloc(sizeof(TREE_NODE)))==NULL)
      {
            fprintf(stderr,"Not enough memory");  // no, exit //
            exit(2);
      }
      tree->next_0=NULL;
      tree->next_1=NULL;
      tree->row=-1;     //-1 means no row in the table

      for (j=0;j<n_of_struct;j++)
      {
            temp=tree;
            mask=0x00000001;
            for (i=0;i<table[j+pos].bit_prefix;i++)
            {
                  if (table[j+pos].base_code & mask)
                  {
                        if (temp->next_1==NULL)
                        {
                              if((temp->next_1=(TREE_NODE *)mymalloc(sizeof(TREE_NODE)))==NULL)
                              {
                                    fprintf(stderr,"Not enough memory");  // no, exit //
                                    exit(2);
                              }
                              temp->next_1->next_0=NULL;
                              temp->next_1->next_1=NULL;
                              temp->next_1->row=-1;
                        }
                        temp=temp->next_1;
                  }//end if
                  else
                  {
                        if (temp->next_0==NULL)
                        {
                              if((temp->next_0=(TREE_NODE *)mymalloc(sizeof(TREE_NODE)))==NULL)
                              {
                                    fprintf(stderr,"Not enough memory");  // no, exit //
                                    exit(2);
                              }
                              temp->next_0->next_0=NULL;
                              temp->next_0->next_1=NULL;
                              temp->next_0->row=-1;
                        }
                        temp=temp->next_0;
                  }//end else
                  mask <<=1;
            }//end for i
            temp->row=j;            //marks the j row in the table
      }//end for j

      return tree;
}//end Tree_Create

U_int_S Input_Bit(U_int_S *raw, U_int_M &pos, U_int_M max, U_int_S &mask, bool &err)
{
      U_int_S value;

      if(pos==max)
      {
            err=1;
            return 0;
      }

      value=raw[pos]&mask;
      mask>>=1;
      if(!mask)
      {
            mask=0x80;
            ++pos;
      }

      return( value ? 1 : 0 );
}//end Input_Bit

int_M Input_Bits(U_int_S *raw, U_int_M &pos, U_int_M max, U_int_S &mask, U_int_S bit_count, bool &err)
{
      U_int_M temp;
      int_M value;

      if(pos==max)
      {
            err=1;
            return 0;
      }

      temp=1<<(bit_count-1);
      value=0;
      do
      {
            if(raw[pos]&mask)
                  value |= temp;
            temp>>=1;
            mask>>=1;
            if(!mask)
            {
                  mask=0x80;
                  ++pos;
                  if(pos==max) {
                        mask=0;                // by E.C. may 2004
                        break;
                  }
            }
      } while(temp);
      if(temp)
            err=1;

      if (value & (1<<(bit_count-1)))       // by E.C. may 2004 negative value. extend to the left
            value|=(-1<<bit_count);        // this approach is good for any number of bits

      return value;
}//end InputBits

void decompress(TREE_NODE *tree, U_int_S *raw_in, U_int_M &pos_in, U_int_M max_in, int_L *raw_out, U_int_M &pos_out, U_int_M &max_out, table_H *table ,U_int_M *flag, U_int_M &pos_tH)
{
      U_int_M i, j;
      U_int_S nbits;
      TREE_NODE *temp;
      U_int_S mask=0x80;
      bool err;
      U_int_M maxIN=max_in+pos_in;

      j=0;
      while(pos_in<maxIN)    //check number of bytes
      {
            temp=tree;
            for (;;)
            {
                  err=0;
                  if (Input_Bit(raw_in,pos_in,maxIN,mask,err))    // for each bit read follow the tree
                        temp=temp->next_1;
                  else
                        temp=temp->next_0;
                  if (temp==NULL)
                  {
                        fprintf(stderr,"Tree overflow");
                        err=1;
                        break;
                  }
                  if (temp->row > -1)          // row found in the table:  exit for
                        break;
                  if(pos_in==maxIN)
                        err=1;
                  if(err)
                        break;
            }//end for
            if(err)       // check for error conditions and if exit while
            {
                  break;            // by E.C. may 2004
            }
            if(table[temp->row+pos_tH].TMS!=1)    // switch to another table
            {
                  Tree_Destroy(tree);                  // destroy the tree and rebuild with the new table
                  pos_tH=0;
                  for(i=1;i<table[temp->row+pos_tH].base_value;i++)
                        pos_tH+=flag[i];    // offset of the table
                  tree=Tree_Create(tree,flag[table[temp->row+pos_tH].base_value],table,pos_tH);
                  continue;
            }//end if table
            else
            {
                  nbits=table[temp->row+pos_tH].bit_code-table[temp->row+pos_tH].bit_prefix;
                  if (nbits)           // bit of the code != bit of the prefix
                  {
                        if(pos_in==maxIN)
                        {
                              err=1;
                              break;            // by E.C. may 2004
                        }
                        raw_out[pos_out]=Input_Bits(raw_in,pos_in,maxIN,mask,nbits,err);  // take value from the stream
                        if(err)       // check for error conditions and if exit while
                        {
                              break;          // by E.C. may 2004
                        }
                        ++pos_out;
                  }//end if nbits
                  else         // bit of the code = bit of the prefix
                  {
                        raw_out[pos_out]=table[temp->row+pos_tH].base_value;   // take value from the table
                        ++pos_out;
                  }
            }//end else if table
            ++j;
            if (j==max_out) break;        // by E.C. may 2004
      } //end while
      pos_in=maxIN;          // by E.C. 23.02.2004: align for safety
      max_out=j;             //                     flows here anyhow!
      if (max_out>4900) {
            max_out=5000;                           // by E.C. may 2004 ESAOTE
            pos_out=(pos_out+100)/max_out*max_out;  // align pointer
      }
}//end decompress

//data.data_BdR0 , data.length_BdR0 , data.samples_BdR0 , data.flag_BdR0.number_samples , data.flag_lead.number , data.t_Huffman , data.flag_Huffman
//out_data       , length           , in_data           , n_samples                     , n_lead                , t_Huffman      , flag_Huffman
void Huffman(int_L *out_data, U_int_M *length, U_int_S *in_data, U_int_M &n_samples, U_int_M n_lead, table_H *t_Huffman, U_int_M *flag_Huffman)
{
      TREE_NODE *tree;
      U_int_M pos_in, pos_out, pos_tH;
      U_int_S i;

      pos_in=0;
      pos_out=0;
      pos_tH=0;
      tree=Tree_Create(tree,flag_Huffman[1],t_Huffman,pos_tH);
      for(i=0;i<n_lead;i++)
      {
            pos_tH=0;
            if(pos_tH)
            {
                  Tree_Destroy(tree);
                  tree=Tree_Create(tree,flag_Huffman[1],t_Huffman,pos_tH);
            }
            decompress(tree,in_data,pos_in,length[i],out_data,pos_out,n_samples,t_Huffman,flag_Huffman,pos_tH);
      }
}//end Huffman

void Decode_Data(pointer_section *section, DATA_DECODE &data, bool &add_filter)
{
      U_int_L t;
      U_int_L dim_B, dim_R, dim_R_, number_samples_;

      int_L *dati_Res_;

      //Decode the reference beat
      if(section[5].length)
      {
            if(section[2].length && data.flag_Huffman[0])
            {
                  dim_B=data.flag_BdR0.number_samples*sizeof(int_L)*data.flag_lead.number;   //whole number of bytes
                  if(dim_B!=0 && (data.Median=(int_L*)mymalloc(dim_B))==NULL)
                  {
                        fprintf(stderr,"Not enough memory");  // no, exit //
                        exit(2);
                  }
                  Huffman(data.Median,data.length_BdR0,data.samples_BdR0,data.flag_BdR0.number_samples,data.flag_lead.number,data.t_Huffman,data.flag_Huffman);
                  free(data.samples_BdR0);
                  free(data.length_BdR0);
            }
            else
            {
                  dim_B=data.flag_BdR0.number_samples*sizeof(int_M)*data.flag_lead.number;   //number of samples of all leads
                  //they shuld be equal!!!
                  free(data.length_BdR0);
            }
            if(data.flag_BdR0.encoding)
                  Differences(data.Median,data.flag_BdR0,data.flag_lead.number);

            Multiply(data.Median,data.flag_BdR0.number_samples*data.flag_lead.number,data.flag_BdR0.AVM);
      }//end if

      //Decode rhythm data
      if(section[6].length)
      {
            dim_R_=data.flag_Res.number_samples*data.flag_lead.number*sizeof(int_L);      //whole number of bytes
            number_samples_=data.flag_Res.number_samples;                //number of samples per lead after interpolation
            if(dim_R_!=0 && (data.Residual=(int_L*)mymalloc(dim_R_))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
            if(section[2].length && data.flag_Huffman[0])
                  Huffman(data.Residual,data.length_Res,data.samples_Res,data.flag_Res.number_samples,data.flag_lead.number,data.t_Huffman,data.flag_Huffman);

            dim_R=data.flag_Res.number_samples*sizeof(int_L)*data.flag_lead.number;   //number of bytes of all leads before interpolation (also, data.flag_Res.number_samples has been changed to the number of samples from HUffman)
            free(data.samples_Res);
            free(data.length_Res);

            if(data.flag_Res.encoding)
            Differences(data.Residual,data.flag_Res,data.flag_lead.number);

            //calculate resampling rate
            if(data.flag_Res.bimodal || data.flag_lead.subtraction)     // by E.C. 19.02.2004  (i.e. to open p120n00)
            {
                  if(section[5].length)
                        data.flag_Res.decimation_factor=data.flag_Res.STM/data.flag_BdR0.STM;
                  else
                        data.flag_Res.decimation_factor=0; //no interpolation!!
                  //exec interpolation
                  if(data.flag_Res.decimation_factor>1)                // by E.C. 19.02.2004  (i.e. to open pd3471)
                  {
//dim_R = number of bytes of decimated signal (4 bytes (int_L) )
//data.flag_Res.number_samples = samples of the decimated signal
//dim_R_ = number of bytes of the reconstructed signal (4 bytes (int_L) )
//number_samples_ = samples of the reconstructed signal

                        data.flag_Res.number_samples=number_samples_;     //number of samples per lead
                        number_samples_=dim_R/(sizeof(int_L)*data.flag_lead.number);
                        dim_R=dim_R_;
                        dim_R_=(dim_R/sizeof(int_L))*sizeof(dec_S)*2;

//dim_R_ = number of bytes of decimated signal (4 bytes (int_L) )
//number_samples_ = samples of the decimated signal
//dim_R = number of bytes of the reconstructed signal (4 bytes (int_L) )
//data.flag_Res.number_samples = samples of the reconstructed signal

                        if(dim_R_!=0 && (dati_Res_=(int_L*)mymalloc(dim_R_))==NULL)
                        {
                              fprintf(stderr,"Not enough memory");  // no, exit //
                              exit(2);
                        }
                        Interpolate(dati_Res_,data.Residual,data.flag_lead,data.data_lead,data.flag_Res,data.data_protected,number_samples_);
                        DoFilter(data.Residual,dati_Res_,data.flag_Res,data.flag_lead,data.data_lead,data.data_protected,data.data_subtraction);
                        free(dati_Res_);
                        //dim_R modifies
                  }
            }
            Multiply(data.Residual,data.flag_Res.number_samples*data.flag_lead.number,data.flag_Res.AVM);

/* AS 2007-10-23: for some (unknown) reason, sometimes the memory allocation has the wrong size
      doing the memory allocation in sopen_scp_read does it correctly. 
      Number of files with SegFaults is reduced by 3.  
      
            if(dim_R!=0 && (data.Reconstructed=(int_L*)mymalloc(dim_R))==NULL)
            {
                  fprintf(stderr,"Not enough memory");  // no, exit //
                  exit(2);
            }
*/
            int dim_RR=dim_R/sizeof(int_L);       // by E.C. 15.10.2003   This to correct a trivial error
            for(t=0;t<dim_RR;t++)                 // of array overflow!!
                  data.Reconstructed[t]=data.Residual[t];   // by E.C. 19.02.2004: first copy rhythm then add the reference beat

            if(section[3].length && section[5].length && data.flag_lead.subtraction)
            {
                  DoAdd(data.Reconstructed,data.Residual,data.flag_Res,data.Median,data.flag_BdR0,data.data_subtraction,data.flag_lead,data.data_lead);
                  if (add_filter && (data.flag_Res.decimation_factor>1)){                  // by E.C. 25.02.2004
                              //  now that the signal is completely reconstructructed, and if decimation was performed
                              //  during the compression phase, do an extra low-pass filter outside protected zones !
                              //  This shows lower RMS values of about 0.5 - 1.0
                              //  If you don't like this extra filtering please uncheck the menu option and reopen
                        for(t=0;t<dim_RR;t++)
                              data.Residual[t]=data.Reconstructed[t];       // reuse array as temp storage
                        Opt_Filter(data.Reconstructed,data.Residual,data.flag_Res,data.flag_lead,data.data_lead,data.data_protected);
                        for(t=0;t<dim_RR;t++)
                              data.Residual[t]=data.Reconstructed[t];       // reuse array as temp storage
                        Opt_Filter(data.Reconstructed,data.Residual,data.flag_Res,data.flag_lead,data.data_lead,data.data_protected);
                  }
                  else add_filter=false;
            }
            else add_filter=false;
      }
}

//______________________________________________________________________________
//                      sections 3, 4, 5, and 6
//                  dati_Res_ ,data.Residual     ,dim_R   ,data.flag_lead.number  ,data.flag_Res, data.data_lead ,data.data_protected)

void Interpolate(int_L *raw_out, int_L *raw_in, f_lead flag_L, lead *marker_A, f_Res flag, Protected_Area *marker_Z, U_int_L sample_Huff)
//dim_out  = n byte in raw_out
//dim_in   =    "      raw_in
//marker_Z = no-subtraction zones
//marker_A =  start/end for each lead
//dec      = decimation factor
//
//for each lead, copy the first and the last two samples, then insert max 3 samples
// between each couple (this means that starting from the first and excluded the last,
// I create 4 samples).
//marker_Z contains the start (marker_Z->info.start=QB) and the end (marker_Z->info..end=QE)
//of all the no-subtraction zones.
//marker_A contains the start (marker_A.start = fist sample) and the end (marker_A.end = last sample)
//of lead data.
/*  given the interval [a,b] where to perform the interpolation, assumed that
    b>=a, the algorithm does:
        - mINS=((QB(k)-1)-(QE(k-1)+1)+1)/dec=(b-a+1)/dec (# of samples to expand)
        - mCOPY=(b-a+1)%dec (# of samples left)
        - in a "normal" situation where (b-a+1) is a multiple of dec (and mCOPY is 0) the algorithm does:
        - insert two samples as found in a and a+1
        - insert dec samples according to the formula:
                Z[i]=Va+j*D with D=(Vb-Va)/dec and i=0,1,2,3
                (where Va=a and Vb=a+1)
          i.e. between two samples I insert 3 samples.
          Finally, I insert two samples b-1 and b.
        - in "not normal" conditions, I do:
          for num=(b-a+1)<4: mCOPY may be from 1 to 3.
          samples are copied as they are;

  If a>b : may be
        - the first sample is the first of the first protected zone (a=b+1=1)
        - empty no-protection zone (a=b+1)
        - the last sample is the last of the last protected zone (a=b+1)
        in these situations samples are copied as they are.
*/
{
      U_int_M a, b;          //interpolation range
      float v;               //interpolation value
      U_int_S j;             //working variable
      U_int_M dim;           //number of samples (to skip) into a protected zone
      U_int_M mINS, mCOPY;   //number of samples to insert, copy
      int_M num;             //number of samples to interpolate
      U_int_L pos_in, pos_out;
      U_int_M nz;            //index of protected zones, i.e. index of QRS
      U_int_S ne;            //index of lead

      pos_in=0;
      pos_out=0;
      for(ne=0;ne<flag_L.number;ne++)      // by E.C. 19.02.2004  loop on leads
      {
            for (nz=0;nz<=flag.number;nz++)    //  loop on QRS for each lead
            {
            //set limits for interpolation
                  if(nz==0)
                  {
                        a=marker_A[ne].start;       // first interval  1 - QB[0]
                        b=marker_Z[nz].QB-1;
                  }
                  else if (nz==flag.number)
                  {
                        a=marker_Z[nz-1].QE+1;      // last interval QE[flag.number-1] - 5000
                        b=marker_A[ne].end;
                  }
                  else
                  {
                        a=marker_Z[nz-1].QE+1;       // interval between two QRS
                        b=marker_Z[nz].QB-1;
                  }
                  //number of samples
                  num=b-a+1;
                  if(num>0)
                  {
                        mINS=num/flag.decimation_factor;  //number to interpolate
                        mCOPY=num%flag.decimation_factor;  //if, residual number to copy
                        if(mINS)
                        {
                              //store first two samples equal to the first value in the list ...
                              raw_out[pos_out++]=raw_in[pos_in];
                              raw_out[pos_out++]=raw_in[pos_in];
                        }
                        // ... then proceed with interpolation
                        dim=mINS;
                        while((dim--)>1)
                        {
                              v=1.0*(raw_in[pos_in+1]-raw_in[pos_in])/flag.decimation_factor;   // by E.C. 23.02.2004 (float v)
                                                                                                                              // rounding improves RMS!
                              for(j=0;j<flag.decimation_factor;j++)
                                    raw_out[pos_out++]=raw_in[pos_in]+j*v;
                              if(pos_in<(sample_Huff*(ne+1)))        // by E.C. 19.02.2004  check overflow
                                    ++pos_in;
                        }//end while
                        if(pos_in>=(sample_Huff*(ne+1)))       //check overflow
                              break;
                        if(mINS)
                        {
                              raw_out[pos_out++]=raw_in[pos_in];
                              raw_out[pos_out++]=raw_in[pos_in];
                              if(pos_in<(sample_Huff*(ne+1)))        // by E.C. 19.02.2004  check overflow
                                    ++pos_in;
                        }
                        //not normal situation? insert mCOPY samples
                        while((mCOPY--)>0)
                              if(pos_in<(sample_Huff*(ne+1)))              // by E.C. 19.02.2004  check overflow
                                    raw_out[pos_out++]=raw_in[pos_in++];
                              else
                                    raw_out[pos_out++]=0;
                  }//end if num>0

                  if (nz<flag.number) {
                        dim=marker_Z[nz].QE-marker_Z[nz].QB+1;    // copy protected zone
                        while((dim--)>0)
                              raw_out[pos_out++]=raw_in[pos_in++];
                  }
            }//for nz
            pos_in=sample_Huff*(ne+1);      // by E.C. 19.02.2004  align, never mind!!
            pos_out=(pos_out+100)/5000*5000;     // by E.C. may 2004  for testing purposes only
      }//for ne
}//end Interpolate

void ExecFilter(int_L *raw_in, int_L *raw_out, U_int_L &pos, U_int_M dim)
//filter from pos for dim samples
{
      int_L v;               //value
      U_int_M i;

      if (dim>0)
      {
            //fist sample = unchanged
            raw_out[pos]=raw_in[pos];  pos++;
            if(dim>2)
                  for(i=2;i<dim;i++)                   // do filter
                  {                                    // as mean of three samples
                        v=raw_in[pos-1]+raw_in[pos]+raw_in[pos+1];

                        if(v>=0)         // as suggested by the standard for rounding
                              v+=1;
                        else
                              v-=1;

                        raw_out[pos++]=v/3;    // by E.C. 24.02.2004  in this case, declaring v as float doesn't change results
                  }
      }
      //last sample = unchanged
      if(dim>1) {
            raw_out[pos]=raw_in[pos];  pos++; }
}//end ExecFilter

void DoFilter(int_L *raw_out, int_L *raw_in, f_Res flag, f_lead flag_L, lead *marker_A, Protected_Area *marker_P, Subtraction_Zone *marker_S)
//filter low-pass outside the proteced zones (marker_Z) for each lead (marker_A)
// but taking into account transients at the boundaries of the subtraction zones (marker_S)
//It's included rounding.
{
      U_int_M a, b;         //interval
      int_M num;
      U_int_L pos;
      U_int_M nz;
      U_int_S ne;            //index of lead

      pos=0;                               // by E.C. 19.02.2004  function redefined such as Interpolate()
      for(ne=0;ne<flag_L.number;ne++)      // loop on leads
      {
            for (nz=0;nz<=flag.number;nz++)     // loop on QRS of each lead
            {
                  //set interval to filter
                  if(nz==0)
                  {
                        a=marker_A[ne].start;
                        if (marker_S[nz].beat_type==0) {
                              b=marker_S[nz].SB-1;
                              num=b-a+1;
                              ExecFilter(raw_in,raw_out,pos,num);      // if, 1 - SB[0]-1
                              a=marker_S[nz].SB;                       // by E.C. may 2004 (handle open and close intervals)
                        }
                        b=marker_P[nz].QB;
                        num=b-a+1;
                        ExecFilter(raw_in,raw_out,pos,num);      // (1 or) SB[0] - QB[0]
                  }
                  else if (nz==flag.number)
                  {
                        a=marker_P[nz-1].QE;
                        if (marker_S[nz-1].beat_type==0) {
                              b=marker_S[nz-1].SE;
                              num=b-a+1;
                              ExecFilter(raw_in,raw_out,pos,num);      // if, QE[last] - SE[last]
                              a=marker_S[nz-1].SE+1;
                        }
                        b=marker_A[ne].end;
                        num=b-a+1;
                        ExecFilter(raw_in,raw_out,pos,num);      // (QE[last] or) SE[last]+1 - 5000
                  }
                  else
                  {
                        a=b+1;
                        if (marker_S[nz-1].beat_type==0) {
                              b=marker_S[nz-1].SE;
                              num=b-a+1;
                              ExecFilter(raw_in,raw_out,pos,num);      // in between
                              a=marker_S[nz-1].SE+1;
                        }
                        if (marker_S[nz].beat_type==0) {
                              b=marker_S[nz].SB-1;
                              num=b-a+1;
                              ExecFilter(raw_in,raw_out,pos,num);
                              a=marker_S[nz].SB;
                        }
                        b=marker_P[nz].QB;
                        num=b-a+1;
                        ExecFilter(raw_in,raw_out,pos,num);
                  }

                  if (nz<flag.number) {
                  a=marker_P[nz].QB+1;
                  b=marker_P[nz].QE-1;
                  num=b-a+1;    // copy protected zone
                  while((num--)>0) {
                        raw_out[pos]=raw_in[pos]; pos++; }
                  }
            }//for nz
      }  // for ne/ng
}//end DoFilter

void DoAdd(int_L *raw_out, int_L *raw_R, f_Res flag_R, int_L *raw_B, f_BdR0 flag_B, Subtraction_Zone *marker_S, f_lead flag_L, lead *marker_A)
//add BdR0 with the rhythm data for all leads
{
      U_int_M pos_B;
      U_int_L pos_R, pos_out;
      U_int_M ns, a , b, num;
      U_int_S ne;            //index of leads

      pos_R=0;                             // by E.C. 19.02.2004  add reference beat to rhythm
      for(ne=0;ne<flag_L.number;ne++)      //  loop on lead
            for (ns=0;ns<flag_R.number;ns++)   //  loop on QRS
                  if(marker_S[ns].beat_type==0)      //  only reference beat!
                  {
                        pos_B=(flag_B.fcM-1)-(marker_S[ns].fc-marker_S[ns].SB);  //initial position in reference beat
                        a= marker_S[ns].SB;
                        b= marker_S[ns].SE;
                        num=b-a+1;     //number of samples to add
                        pos_out= a-1;
                        pos_out+= ne*flag_R.number_samples;
                        pos_B+= ne*flag_B.number_samples;
                        while((num--)>0)
                        {
                              raw_out[pos_out]+=raw_B[pos_B];
                              pos_out++;
                              pos_B++;
                              pos_R++;
                        }
                  }//end for/if
}//end DoAdd

void Opt_Filter(int_L *raw_out, int_L *raw_in, f_Res flag, f_lead flag_L, lead *marker_A, Protected_Area *marker_P)
// by E.C. 25.02.2004
// do an extra low-pass filter outside protected zones (marker_P)
// in the range of the signal (marker_A) for each lead
// this is simpler than DoFilter()
{
      U_int_M a, b;         //interval for filtering
      int_M num;
      U_int_L pos;
      U_int_M nz;
      U_int_S ne;            //lead index

      pos=0;
      for(ne=0;ne<flag_L.number;ne++)      // loop on leads
      {
            for (nz=0;nz<=flag.number;nz++)     // loop on QRS of each lead
            {
                  // establish the interval
                  if(nz==0)
                  {
                        a=marker_A[ne].start;
                        b=marker_P[nz].QB;
                        num=b-a+1;
                        ExecFilter(raw_in,raw_out,pos,num);      // from start to first protected zone
                  }
                  else if (nz==flag.number)
                  {
                        a=marker_P[nz-1].QE;
                        b=marker_A[ne].end;
                        num=b-a+1;
                        ExecFilter(raw_in,raw_out,pos,num);      // from last protected zone to end
                  }
                  else
                  {
                        a=b+1;
                        b=marker_P[nz].QB;
                        num=b-a+1;
                        ExecFilter(raw_in,raw_out,pos,num);      // between two protected zones
                  }

                  if (nz<flag.number) {
                        a=marker_P[nz].QB+1;
                        b=marker_P[nz].QE-1;
                        num=b-a+1;                              // copy the protected zone as is
                        while((num--)>0) {
                              raw_out[pos]=raw_in[pos]; pos++; }
                  }
            }//for nz
      }  // for ne
}//end Opt_Filter

Generated by  Doxygen 1.6.0   Back to index