scp-decode.cpp

来自「c++编写的用于生物信号处理的软件库」· C++ 代码 · 共 2,178 行 · 第 1/5 页

CPP
2,178
字号
/*    $Id: scp-decode.cpp,v 1.23 2008/03/14 08:30:42 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 originalCopyright and comments follow.This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 3of 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, 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/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, 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 TRUE 1#define FALSE 0#define COMPAT//______________________________________________________________________________#include <iostream>#include <cstring>    //strcat, strcpy#include <cstdio>using namespace std;//______________________________________________________________________________//               FILE POINTERS#include "../biosig-dev.h"#include "types.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 readstatic U_int_L _DIM_FILE;                      // file length in bytestatic const U_int_S _NUM_SECTION=12U;     // sections over 11 are not considered//______________________________________________________________________________//                      section 2U_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 6template<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 FUNCTIONSchar*           ReadString(char*,U_int_M);                          //read a stringchar            *FindString(U_int_M);                         // calculate the length of a string and write it downint_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 streamvoid            Skip(U_int_M);        //skip some bytes//______________________________________________________________________________U_int_M         ReadCRC();                             //read first 6 bytes of the filebool            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 headervoid            sectionsOptional(pointer_section*,DATA_DECODE&,DATA_RECORD&,DATA_INFO&);       //handles optional sections#ifdef WITH_OBSOLETE_PARTSvoid            section_0(pointer_section*, int size_max);                    //read section 0void            Init_S1(DATA_INFO &inf);void            section_1(pointer_section,DATA_INFO&);    //read section 1 datavoid            section_1_0(demographic&);                        //read tag 0 of section 1void            section_1_1(demographic&);                        //read tag 1 of section 1void            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 1void            section_1_255();                                //read tag 255 of section 1void            section_7(pointer_section,DATA_RECORD&, int_S version); //read section 7void            section_8(pointer_section,DATA_INFO&);          //read section 8void            section_10(pointer_section,DATA_RECORD&, int_S version); //read section 10void            section_11(pointer_section,DATA_INFO&);         //read section 11#endifvoid            section_2(pointer_section,DATA_DECODE&);        //read section 2void            section_3(pointer_section,DATA_DECODE&, int_S version); //read section 3void            section_4(pointer_section,DATA_DECODE&, int_S version); //read section 4bool            section_5(pointer_section,DATA_DECODE&,bool);   //read section 5void            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//                      MAINint 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 "";	_COUNT_BYTE+=num;	ifread(temp_string,sizeof(char),num,in);	if (temp_string[num-1]!='\0')		temp_string[num]='\0';	return temp_string;}//end ReadStringint_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 Lookchar *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 "";	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 "";	_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#endifvoid Skip(U_int_M num)//skip num bytes from the stream{	if(num>0U)		ifseek(in,num,1U);	_COUNT_BYTE+=num;}//end Skip//______________________________________________________________________________//                         INITIALIZATION FUNCTIONSvoid 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

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?