⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 biosig.c

📁 BIOSIG is an open source software library for biomedical signal processing. Library works well with
💻 C
📖 第 1 页 / 共 4 页
字号:
/*    $Id: biosig.c,v 1.46 2006/05/15 09:49:21 schloegl Exp $    Copyright (C) 2005,2006 Alois Schloegl <a.schloegl@ieee.org>    This function is part of the "BioSig for C/C++" repository     (biosig4c++) at http://biosig.sf.net/     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 *//* 	reading and writing of GDF files is demonstrated 		Features: 	- reading and writing of EDF, BDF and GDF2.0pre files 	- reading of GDF1.x, BKR, CFWB, CNT files 		implemented functions: 	- SOPEN, SREAD, SWRITE, SCLOSE, SEOF, SSEEK, STELL, SREWIND 	*/#include <stdio.h>#include <stdlib.h>#include <string.h>//#include <libxml/xmlreader.h>#include "biosig.h"//#include "zlib.h"const int16_t GDFTYP_BYTE[] = {	1, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 0, 0, 0, 0, 0,   /* 0  */ 	4, 8,16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 16 */ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 32 */ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 48 */ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 64 */ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* 128 */ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,    /* 256 */  	0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,    /* 255+24 = bit24, 3 byte */ 	0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 	0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 	0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,10, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* 384 */ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,    /* 512 */ 	0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 	0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 	0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 	0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,10  };/****************************************************************************//**                                                                        **//**                      INTERNAL FUNCTIONS                                **//**                                                                        **//****************************************************************************/ // greatest common divisor size_t gcd(size_t A,size_t B) {	size_t t; 	while (!B) {		t = B; 		B = A%B;		A = t; 	}	return(A);};// least common multiplesize_t lcm(size_t A,size_t B) {	return(A*B/gcd(A,B));};#if __BYTE_ORDER == __BIG_ENDIANfloat l_endian_f32(float x) {	union {		float f32;		uint32_t u32;	} b1,b2; 	b1.f32 = x; 	b2 = b1; 	b2.u32 = bswap_32(b1.u32);	return(b2.f32);}double l_endian_f64(double x) {	union {		double f64;		uint32_t u32[2];	} b1,b2; 	b1.f64 = x; 	b2 = b1; 	b2.u32[0] = bswap_32(b1.u32[1]);	b2.u32[1] = bswap_32(b1.u32[0]);	return(b2.f64);}#endif/****************************************************************************//**                                                                        **//**                     EXPORTED FUNCTIONS                                 **//**                                                                        **//****************************************************************************//****************************************************************************//**                     INIT HDR                                           **//****************************************************************************/HDRTYPE* create_default_hdr(const unsigned NS, const unsigned N_EVENT){/*	HDR is initialized, memory is allocated for 	NS channels and N_EVENT number of events. 	The purpose is to set the define all parameters at an initial step. 	No parameters must remain undefined. */	HDRTYPE* hdr = (HDRTYPE*)malloc(sizeof(HDRTYPE));	union {		uint32_t testword;		uint8_t  testbyte[sizeof(uint32_t)];	} EndianTest;     	int k,k1;	EndianTest.testword = 0x4a3b2c1d; 	hdr->FILE.LittleEndian = (EndianTest.testbyte[0]==0x1d); 		if  ((hdr->FILE.LittleEndian) && (__BYTE_ORDER == __BIG_ENDIAN))	{		fprintf(stderr,"Panic: mixed results on Endianity test.\n"); 		exit(-1); 	}			if  ((!hdr->FILE.LittleEndian) && (__BYTE_ORDER == __LITTLE_ENDIAN))	{		fprintf(stderr,"Panic: mixed results on Endianity test.\n"); 		exit(-1); 	}		hdr->FILE.OPEN = 0;	hdr->FILE.FID = 0;	hdr->AS.Header1 = NULL;      	hdr->TYPE = GDF;       	hdr->VERSION = 1.94;      	hdr->AS.rawdata = (uint8_t*) malloc(10);      	hdr->NRec = 0;       	hdr->NS = NS;		hdr->SampleRate = 4321.5;      	memset(hdr->AS.PID,32,81);       	hdr->AS.RID = "GRAZ"; 	hdr->AS.bi = (uint32_t*)calloc(hdr->NS+1,sizeof(uint32_t));	hdr->data.size[0] = 0; 	// rows 	hdr->data.size[1] = 0;  // columns 	hdr->data.block = (biosig_data_type*)malloc(410);       	hdr->T0 = t_time2gdf_time(time(NULL));      	hdr->ID.Equipment = *(uint64_t*)&"b4c_0.35";	hdr->Patient.Name 	= "X";	hdr->Patient.Id 	= "X";	hdr->Patient.Birthday 	= (gdf_time)0;        // Unknown;      	hdr->Patient.Medication = 0;	// 0:Unknown, 1: NO, 2: YES      	hdr->Patient.DrugAbuse 	= 0;	// 0:Unknown, 1: NO, 2: YES      	hdr->Patient.AlcoholAbuse= 0;	// 0:Unknown, 1: NO, 2: YES      	hdr->Patient.Smoking 	= 0;	// 0:Unknown, 1: NO, 2: YES      	hdr->Patient.Sex 	= 0;	// 0:Unknown, 1: Male, 2: Female      	hdr->Patient.Handedness = 0;	// 0:Unknown, 1: Right, 2: Left, 3: Equal      	hdr->Patient.Impairment.Visual = 0;	// 0:Unknown, 1: NO, 2: YES, 3: Corrected      	hdr->Patient.Weight 	= 0;	// 0:Unknown      	hdr->Patient.Height 	= 0;	// 0:Unknown      	hdr->Dur[0] = 1;      	hdr->Dur[1] = 1;	memset(&hdr->IPaddr,0,6);      	for (k1=0; k1<3; k1++) {      		hdr->Patient.Headsize[k1] = 0;        // Unknown;      		hdr->ELEC.REF[k1] = 0.0;      		hdr->ELEC.GND[k1] = 0.0;      	}	hdr->LOC[0] = 0x00292929; 			hdr->LOC[1] = 48*3600000+(1<<31); 	// latitude	hdr->LOC[2] = 15*3600000+(1<<31); 	// longitude 	hdr->LOC[3] = 35000; 	 	//altitude in centimeter above sea level	hdr->FLAG.UCAL = 0; 		// un-calibration OFF (auto-scaling ON) 	hdr->FLAG.OVERFLOWDETECTION = 1; 		// overflow detection ON	       	// define variable header 	hdr->CHANNEL = (CHANNEL_TYPE*)calloc(hdr->NS,sizeof(CHANNEL_TYPE));	for (k=0;k<hdr->NS;k++)	{	      	hdr->CHANNEL[k].Label     = "C4";	      	hdr->CHANNEL[k].Transducer= "EEG: Ag-AgCl electrodes";	      	hdr->CHANNEL[k].PhysDim   = "uV";	      	hdr->CHANNEL[k].PhysDimCode = 19+4256; // uV	      	hdr->CHANNEL[k].PhysMax   = +100;	      	hdr->CHANNEL[k].PhysMin   = -100;	      	hdr->CHANNEL[k].DigMax    = +2047;	      	hdr->CHANNEL[k].DigMin    = -2048;	      	hdr->CHANNEL[k].GDFTYP    = 3;	// int16 		      	hdr->CHANNEL[k].SPR       = 1;	// one sample per block	      	hdr->CHANNEL[k].HighPass  = 0.16;	      	hdr->CHANNEL[k].LowPass   = 70.0;	      	hdr->CHANNEL[k].Notch     = 50;	      	hdr->CHANNEL[k].Impedance = INF;	      	for (k1=0; k1<3; hdr->CHANNEL[k].XYZ[k1++] = 0.0);	}      		// define EVENT structure	hdr->EVENT.N = N_EVENT; 	hdr->EVENT.SampleRate = hdr->SampleRate; 	hdr->EVENT.POS = (uint32_t*) calloc(hdr->EVENT.N,sizeof(*hdr->EVENT.POS));	hdr->EVENT.TYP = (uint16_t*) calloc(hdr->EVENT.N,sizeof(*hdr->EVENT.TYP));	hdr->EVENT.DUR = (uint32_t*) calloc(hdr->EVENT.N,sizeof(*hdr->EVENT.DUR));	hdr->EVENT.CHN = (uint16_t*) calloc(hdr->EVENT.N,sizeof(*hdr->EVENT.CHN));		// initialize "Annotated ECG structure"	hdr->aECG = NULL; 	return(hdr);}/****************************************************************************//**                     SOPEN                                              **//****************************************************************************/HDRTYPE* sopen(const char* FileName, const char* MODE, HDRTYPE* hdr)/*	MODE="r" 		reads file and returns HDR 	MODE="w" 		writes HDR into file  */{    	    	const char*	GENDER = "XMFX";      	const uint16_t	CFWB_GDFTYP[] = {17,16,3};  	const float	CNT_SETTINGS_NOTCH[] = {0.0, 50.0, 60.0}; 	const float	CNT_SETTINGS_LOWPASS[] = {30, 40, 50, 70, 100, 200, 500, 1000, 1500, 2000, 2500, 3000};	const float	CNT_SETTINGS_HIGHPASS[] = {NaN, 0, .05, .1, .15, .3, 1, 5, 10, 30, 100, 150, 300};#ifdef __XML_XMLREADER_H__	xmlTextReaderPtr reader;	xmlDocPtr doc; /* the resulting document tree */	int ret;#endif    	int 		k,id;    	uint32_t	k32u;     	size_t	 	count,len,pos;    	uint8_t 	buf[81];    	char 		tmp[81];    	char 		cmd[256];    	double 		Dur; 	char* 		Header1;	char* 		Header2;	char*		ptr_str;	struct tm 	tm_time; 	time_t		tt;	unsigned	EventChannel = 0;	struct	{		int	number_of_sections;	} SCP;if (!strcmp(MODE,"r"))	{	hdr = create_default_hdr(0,0);	// initializes fields that may stay undefined during SOPEN #ifdef ZLIB_H	hdr->FILE.FID = fopen(FileName,"rb");#else	hdr->FILE.FID = fopen(FileName,"rb");#endif	hdr->FileName = FileName;     	if (hdr->FILE.FID == NULL)     	{ 	    		free(hdr);    				return(NULL);    	}	            	/******** read 1st (fixed)  header  *******/	 	Header1 = (char*)malloc(256);/*#ifdef ZLIB_H    	count   = gzread(hdr->FILE.FID,Header1,256);#else*/    	count   = fread(Header1,1,256,hdr->FILE.FID);//#endif	    	if (0);    	else if (!memcmp(Header1+1,"BIOSEMI",7)) {    		hdr->TYPE = BDF;    		hdr->VERSION = -1;     	}	    	else if ((Header1[0]==(char)207) & (!Header1[1]) & (!Header1[154]) & (!Header1[155]))	    	hdr->TYPE = BKR;    	else if (!memcmp(Header1,"CFWB\1\0\0\0",8))	    	hdr->TYPE = CFWB;    	else if (!memcmp(Header1,"Version 3.0",11))	    	hdr->TYPE = CNT;    	else if (!memcmp(Header1,"DEMG",4))	    	hdr->TYPE = DEMG;    	else if (!memcmp(Header1,"0       ",8)) {	    	hdr->TYPE = EDF;	    	hdr->VERSION = 0; 	}    	    	else if (!memcmp(Header1,"fLaC",4))	    	hdr->TYPE = FLAC;    	else if (!memcmp(Header1,"GDF",3))	    	hdr->TYPE = GDF;     	else if (!memcmp(Header1,"@  MFER ",8))	    	hdr->TYPE = MFER;    	else if (!memcmp(Header1,"@ MFR ",6))	    	hdr->TYPE = MFER;    	else if (!memcmp(Header1,"NEX1",4))	    	hdr->TYPE = NEX1;    	else if (!memcmp(Header1,"PLEX",4))	    	hdr->TYPE = PLEXON;    	else if (!memcmp(Header1+16,"SCPECG",6))	    	hdr->TYPE = SCP_ECG;    	else {		fclose(hdr->FILE.FID); 		free(Header1);#ifdef __XML_XMLREADER_H__		LIBXML_TEST_VERSION    		reader = xmlReaderForFile(hdr->FileName, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);     			// XML_PARSE_DTDVALID cannot be used in aECG 		if (reader != NULL) {		        ret = xmlTextReaderRead(reader);        		while (ret == 1) {//            			processNode(reader);

⌨️ 快捷键说明

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