blSignal::SampleType blGDFUtils::ConvertUCHAR2Float( blGDFChannel &channel, unsigned char* buffer, bool littleEndian ) { // byte order-> Do we need to swap? #if (__BYTE_ORDER == __BIG_ENDIAN) char SWAP = littleEndian; #elif (__BYTE_ORDER == __LITTLE_ENDIAN) char SWAP = !littleEndian; #endif // Switch for each type of sample union {int16_t i16; uint16_t u16; uint32_t i32; float f32; uint64_t i64; double f64;} u; uint8_t bitoff = 0; blSignal::SampleType sampleValue = 0; size_t k5 = 0,SZ = 0; int32_t int32_value; switch ( channel.GDFTYP ) { case blGDFTYPCode_int8: sampleValue = (blSignal::SampleType)(*(int8_t*)buffer);break; case blGDFTYPCode_uint8: sampleValue = (blSignal::SampleType)(*(uint8_t*)buffer);break; case blGDFTYPCode_int16: if (SWAP) { sampleValue = (blSignal::SampleType)(int16_t)bswap_16(*(int16_t*)buffer); } else { sampleValue = (blSignal::SampleType)(*(int16_t*)buffer); } break; case blGDFTYPCode_uint16: if (SWAP) { sampleValue = (blSignal::SampleType)(uint16_t)bswap_16(*(uint16_t*)buffer); } else { sampleValue = (blSignal::SampleType)(*(uint16_t*)buffer); } break; case blGDFTYPCode_int32: if (SWAP) { sampleValue = (blSignal::SampleType)(int32_t)bswap_32(*(int32_t*)buffer); } else { sampleValue = (blSignal::SampleType)(*(int32_t*)buffer); } break; case blGDFTYPCode_uint32: if (SWAP) { sampleValue = (blSignal::SampleType)(uint32_t)bswap_32(*(uint32_t*)buffer); } else { sampleValue = (blSignal::SampleType)(*(uint32_t*)buffer); } break; case blGDFTYPCode_int64: if (SWAP) { sampleValue = (blSignal::SampleType)(int64_t)bswap_64(*(int64_t*)buffer); } else { sampleValue = (blSignal::SampleType)(*(int64_t*)buffer); } break; case blGDFTYPCode_uint64: if (SWAP) { sampleValue = (blSignal::SampleType)(uint64_t)bswap_64(*(uint64_t*)buffer); } else { sampleValue = (blSignal::SampleType)(*(uint64_t*)buffer); } break; case blGDFTYPCode_float32: if (SWAP) { u.i32 = bswap_32(*(uint32_t*)(buffer)); sampleValue = (blSignal::SampleType)(u.f32); } else { sampleValue = (blSignal::SampleType)(*(float*)(buffer)); } break; case blGDFTYPCode_float64: if (SWAP) { u.i64 = bswap_64(*(uint64_t*)(buffer)); sampleValue = (blSignal::SampleType)(u.f64); } else { sampleValue = (blSignal::SampleType)(*(double*)(buffer)); } break; case blGDFTYPCode_float128: break; case 128: // Nihon-Kohden little-endian int16 format u.u16 = leu16p(buffer) + 0x8000; sampleValue = (blSignal::SampleType) (u.i16); break; case 255+12: if ( littleEndian ) { bitoff = k5*SZ & 0x07; #if __BYTE_ORDER == __BIG_ENDIAN u.i16 = (leu16p(buffer) >> (4-bitoff)) & 0x0FFF; #elif __BYTE_ORDER == __LITTLE_ENDIAN u.i16 = (leu16p(buffer)>>bitoff) & 0x0FFF; #endif if (u.i16 & 0x0800) u.i16 -= 0x1000; sampleValue = (blSignal::SampleType)u.i16; } else { bitoff = k5*SZ & 0x07; #if __BYTE_ORDER == __BIG_ENDIAN u.i16 = (beu16p(buffer) >> (4-bitoff)) & 0x0FFF; #elif __BYTE_ORDER == __LITTLE_ENDIAN u.i16 = (beu16p(buffer) >> (4-bitoff)) & 0x0FFF; #endif if (u.i16 & 0x0800) u.i16 -= 0x1000; sampleValue = (blSignal::SampleType)u.i16; } break; case 511+12: bitoff = k5*SZ & 0x07; if (littleEndian) { #if __BYTE_ORDER == __BIG_ENDIAN sampleValue = (blSignal::SampleType)((leu16p(buffer) >> (4-bitoff)) & 0x0FFF); #elif __BYTE_ORDER == __LITTLE_ENDIAN sampleValue = (blSignal::SampleType)((leu16p(buffer) >> bitoff) & 0x0FFF); #endif } else {
EXTERN_C int sopen_SCP_write(HDRTYPE* hdr) { /* this function is a stub or placeholder and need to be defined in order to be useful. It will be called by the function SOPEN in "biosig.c" Input: char* Header // contains the file content Output: HDRTYPE *hdr // defines the HDR structure accoring to "biosig.h" */ uint8_t* ptr; // pointer to memory mapping of the file layout uint8_t* PtrCurSect; // point to current section int curSect; uint32_t len; uint16_t crc; uint32_t i; uint32_t sectionStart; struct tm* T0_tm; double AVM, avm; uint16_t avm16; struct aecg* aECG; if (VERBOSE_LEVEL>7) fprintf(stdout,"SOPEN_SCP_WRITE 101\n"); if ((fabs(hdr->VERSION - 1.3)<0.01) && (fabs(hdr->VERSION-2.0)<0.01)) fprintf(stderr,"Warning SOPEN (SCP-WRITE): Version %f not supported\n",hdr->VERSION); uint8_t VERSION = 20; // (uint8_t)round(hdr->VERSION*10); // implemented version number if (hdr->aECG==NULL) { fprintf(stderr,"Warning SOPEN_SCP_WRITE: No aECG info defined\n"); hdr->aECG = malloc(sizeof(struct aecg)); aECG = (struct aecg*)hdr->aECG; aECG->diastolicBloodPressure=0.0; aECG->systolicBloodPressure=0.0; aECG->MedicationDrugs="/0"; aECG->ReferringPhysician="/0"; aECG->LatestConfirmingPhysician="/0"; aECG->Diagnosis="/0"; aECG->EmergencyLevel=0; #if (BIOSIG_VERSION < 10500) aECG->Section8.NumberOfStatements = 0; aECG->Section8.Statements = NULL; aECG->Section11.NumberOfStatements = 0; aECG->Section11.Statements = NULL; #endif } else aECG = (struct aecg*)hdr->aECG; //fprintf(stdout,"SCP-Write: IIb %s\n",hdr->aECG->ReferringPhysician); /* predefined values */ aECG->Section1.Tag14.INST_NUMBER = 0; // tag 14, byte 1-2 aECG->Section1.Tag14.DEPT_NUMBER = 0; // tag 14, byte 3-4 aECG->Section1.Tag14.DEVICE_ID = 0; // tag 14, byte 5-6 aECG->Section1.Tag14.DeviceType = 0; // tag 14, byte 7: 0: Cart, 1: System (or Host) aECG->Section1.Tag14.MANUF_CODE = 255; // tag 14, byte 8 (MANUF_CODE has to be 255) aECG->Section1.Tag14.MOD_DESC = "Cart1"; // tag 14, byte 9 (MOD_DESC has to be "Cart1") aECG->Section1.Tag14.VERSION = VERSION; // tag 14, byte 15 (VERSION * 10) aECG->Section1.Tag14.PROT_COMP_LEVEL = 0xA0; // tag 14, byte 16 (PROT_COMP_LEVEL has to be 0xA0 => level II) aECG->Section1.Tag14.LANG_SUPP_CODE = 0x00; // tag 14, byte 17 (LANG_SUPP_CODE has to be 0x00 => Ascii only, latin and 1-byte code) aECG->Section1.Tag14.ECG_CAP_DEV = 0xD0; // tag 14, byte 18 (ECG_CAP_DEV has to be 0xD0 => Acquire, (No Analysis), Print and Store) aECG->Section1.Tag14.MAINS_FREQ = 0; // tag 14, byte 19 (MAINS_FREQ has to be 0: unspecified, 1: 50 Hz, 2: 60Hz) aECG->Section1.Tag14.ANAL_PROG_REV_NUM = ""; aECG->Section1.Tag14.SERIAL_NUMBER_ACQ_DEV = ""; aECG->Section1.Tag14.ACQ_DEV_SYS_SW_ID = ""; aECG->Section1.Tag14.ACQ_DEV_SCP_SW = "OpenECG XML-SCP 1.00"; // tag 14, byte 38 (SCP_IMPL_SW has to be "OpenECG XML-SCP 1.00") aECG->Section1.Tag14.ACQ_DEV_MANUF = "Manufacturer"; // tag 14, byte 38 (ACQ_DEV_MANUF has to be "Manufacturer") aECG->Section5.Length = 0; aECG->Section6.Length = 0; /* */ aECG->FLAG.HUFFMAN = 0; aECG->FLAG.REF_BEAT= 0; aECG->FLAG.DIFF = 0; aECG->FLAG.BIMODAL = 0; if (VERBOSE_LEVEL>7) fprintf(stdout,"SOPEN_SCP_WRITE 111\n"); ptr = (uint8_t*)hdr->AS.Header; int NSections = 12; // initialize section 0 sectionStart = 6+16+NSections*10; ptr = (uint8_t*)realloc(ptr,sectionStart); memset(ptr,0,sectionStart); uint32_t curSectLen = 0; // current section length for (curSect=NSections-1; curSect>=0; curSect--) { curSectLen = 0; // current section length //ptr = (uint8_t*)realloc(ptr,sectionStart+curSectLen); if (VERBOSE_LEVEL>7) fprintf(stdout,"Section %i %p\n",curSect,ptr); if (curSect==0) // SECTION 0 { hdr->HeadLen = sectionStart; // length of all other blocks together ptr = (uint8_t*)realloc(ptr,hdr->HeadLen); // total file length curSectLen = 16; // current section length sectionStart = 6; memcpy(ptr+16,"SCPECG",6); // reserved curSectLen += NSections*10; } else if (curSect==1) // SECTION 1 { ptr = (uint8_t*)realloc(ptr,sectionStart+10000); PtrCurSect = ptr+sectionStart; curSectLen = 16; // current section length if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 0 \n"); // Tag 0 (max len = 64) if (!hdr->FLAG.ANONYMOUS && (hdr->Patient.Name != NULL)) { *(ptr+sectionStart+curSectLen) = 0; // tag len = strlen(hdr->Patient.Name) + 1; leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy((char*)ptr+sectionStart+curSectLen+3,hdr->Patient.Name,len); // field curSectLen += len+3; } if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 1 \n"); // Tag 1 (max len = 64) Firstname /* *(ptr+sectionStart+curSectLen) = 1; // tag len = strlen(hdr->Patient.Name) + 1; leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy((char*)ptr+sectionStart+curSectLen+3,hdr->Patient.Name,len); // field curSectLen += len+3; */ // Tag 2 (max len = 64) Patient ID if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 2 \n"); // if (hdr->Patient.Id != NULL) { if (strlen(hdr->Patient.Id)>0) { *(ptr+sectionStart+curSectLen) = 2; // tag len = strlen(hdr->Patient.Id) + 1; leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy((char*)ptr+sectionStart+curSectLen+3,hdr->Patient.Id,len); // field curSectLen += len+3; } // fprintf(stdout,"Section %i Len %i %x\n",curSect,curSectLen,sectionStart); // Tag 3 (max len = 64) Second Last Name /* *(ptr+sectionStart+curSectLen) = 3; // tag len = strlen(hdr->Patient.Name) + 1; leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy(ptr+sectionStart+curSectLen+3,hdr->Patient.Name,len); // field curSectLen += len+3; */ // Tag 5 (len = 4) if ((hdr->Patient.Birthday) > 0) { T0_tm = gdf_time2tm_time(hdr->Patient.Birthday); *(ptr+sectionStart+curSectLen) = 5; // tag leu16a(4, ptr+sectionStart+curSectLen+1); // length leu16a(T0_tm->tm_year+1900, ptr+sectionStart+curSectLen+3);// year *(ptr+sectionStart+curSectLen+5) = (uint8_t)(T0_tm->tm_mon + 1); // month *(ptr+sectionStart+curSectLen+6) = (uint8_t)(T0_tm->tm_mday); // day curSectLen += 7; } // Tag 6 (len = 3) Height if (hdr->Patient.Height>0.0) { *(ptr+sectionStart+curSectLen) = 6; // tag leu16a(3, ptr+sectionStart+curSectLen+1); // length leu16a(hdr->Patient.Height, ptr+sectionStart+curSectLen+3); // value *(ptr+sectionStart+curSectLen+5) = 1; // cm curSectLen += 6; } // Tag 7 (len = 3) Weight if (hdr->Patient.Weight>0.0) { *(ptr+sectionStart+curSectLen) = 7; // tag leu16a(3, ptr+sectionStart+curSectLen+1); // length leu16a(hdr->Patient.Weight, ptr+sectionStart+curSectLen+3); // value *(ptr+sectionStart+curSectLen+5) = 1; // kg curSectLen += 6; } // Tag 8 (len = 1) if (hdr->Patient.Sex != 0) { *(ptr+sectionStart+curSectLen) = 8; // tag leu16a(1, ptr+sectionStart+curSectLen+1); // length *(ptr+sectionStart+curSectLen+3) = hdr->Patient.Sex; // value curSectLen += 4; } // Tag 11 (len = 2) if (aECG->systolicBloodPressure>0.0) { *(ptr+sectionStart+curSectLen) = 11; // tag leu16a(2, ptr+sectionStart+curSectLen+1); // length leu16a((uint16_t)aECG->systolicBloodPressure, ptr+sectionStart+curSectLen+3); // value curSectLen += 5; }; // Tag 12 (len = 2) if (aECG->diastolicBloodPressure>0.0) { *(ptr+sectionStart+curSectLen) = 12; // tag leu16a(2, ptr+sectionStart+curSectLen+1); // length leu16a((uint16_t)aECG->diastolicBloodPressure, ptr+sectionStart+curSectLen+3); // value curSectLen += 5; }; // Tag 13 (max len = 80) aECG->Diagnosis=""; len = strlen(aECG->Diagnosis); if (len>0) { *(ptr+sectionStart+curSectLen) = 13; // tag len = min(64,len+1); leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy((char*)(ptr+sectionStart+curSectLen+3),aECG->Diagnosis,len); curSectLen += 3+len; }; // Tag 14 (max len = 2 + 2 + 2 + 1 + 1 + 6 + 1 + 1 + 1 + 1 + 1 + 16 + 1 + 25 + 25 + 25 + 25 + 25) if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 14 \n"); // Total = 161 (max value) *(ptr+sectionStart+curSectLen) = 14; // tag //len = 41; // minimum length // leu16a(len, ptr+sectionStart+curSectLen+1); // length memset(ptr+sectionStart+curSectLen+3,0,41); // dummy value curSectLen += 3; leu16a(aECG->Section1.Tag14.INST_NUMBER, ptr+sectionStart+curSectLen); leu16a(aECG->Section1.Tag14.DEPT_NUMBER, ptr+sectionStart+curSectLen+2); leu16a(aECG->Section1.Tag14.DEVICE_ID, ptr+sectionStart+curSectLen+4); *(ptr+sectionStart+curSectLen+ 6) = aECG->Section1.Tag14.DeviceType; *(ptr+sectionStart+curSectLen+ 7) = aECG->Section1.Tag14.MANUF_CODE; // tag 14, byte 7 (MANUF_CODE has to be 255) strncpy((char*)(ptr+sectionStart+curSectLen+8), aECG->Section1.Tag14.MOD_DESC, 6); // tag 14, byte 7 (MOD_DESC has to be "Cart1") *(ptr+sectionStart+curSectLen+14) = VERSION; // tag 14, byte 14 (VERSION has to be 20) *(ptr+sectionStart+curSectLen+14) = aECG->Section1.Tag14.VERSION; *(ptr+sectionStart+curSectLen+15) = aECG->Section1.Tag14.PROT_COMP_LEVEL; // tag 14, byte 15 (PROT_COMP_LEVEL has to be 0xA0 => level II) *(ptr+sectionStart+curSectLen+16) = aECG->Section1.Tag14.LANG_SUPP_CODE; // tag 14, byte 16 (LANG_SUPP_CODE has to be 0x00 => Ascii only, latin and 1-byte code) *(ptr+sectionStart+curSectLen+17) = aECG->Section1.Tag14.ECG_CAP_DEV; // tag 14, byte 17 (ECG_CAP_DEV has to be 0xD0 => Acquire, (No Analysis), Print and Store) *(ptr+sectionStart+curSectLen+18) = aECG->Section1.Tag14.MAINS_FREQ; // tag 14, byte 18 (MAINS_FREQ has to be 0: unspecified, 1: 50 Hz, 2: 60Hz) *(ptr+sectionStart+curSectLen+35) = strlen(aECG->Section1.Tag14.ANAL_PROG_REV_NUM)+1; // tag 14, byte 34 => length of ANAL_PROG_REV_NUM + 1 = 1 uint16_t len1 = 36; char* tmp; tmp = aECG->Section1.Tag14.ANAL_PROG_REV_NUM; len = min(25, strlen(tmp) + 1); strncpy((char*)(ptr+sectionStart+curSectLen+len1), tmp, len); len1 += len; tmp = aECG->Section1.Tag14.SERIAL_NUMBER_ACQ_DEV; len = min(25, strlen(tmp) + 1); strncpy((char*)(ptr+sectionStart+curSectLen+len1), tmp, len); len1 += len; tmp = aECG->Section1.Tag14.ACQ_DEV_SYS_SW_ID; len = min(25, strlen(tmp) + 1); strncpy((char*)(ptr+sectionStart+curSectLen+len1), tmp, len); len1 += len; tmp = aECG->Section1.Tag14.ACQ_DEV_SCP_SW; len = min(25, strlen(tmp) + 1); strncpy((char*)(ptr+sectionStart+curSectLen+len1), tmp, len); len1 += len; tmp = aECG->Section1.Tag14.ACQ_DEV_MANUF; len = min(25, strlen(tmp) + 1); strncpy((char*)(ptr+sectionStart+curSectLen+len1), tmp, len); len1 += len; leu16a(len1, ptr+sectionStart+curSectLen+1-3); // length curSectLen += len1; // Tag 16 (max len = 80) if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 16 \n"); len = hdr->ID.Hospital ? strlen(hdr->ID.Hospital) : 0; if (len > 0) { *(ptr+sectionStart+curSectLen) = 16; // tag len = min(64,len+1); leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy((char*)(ptr+sectionStart+curSectLen+3),hdr->ID.Hospital,len); curSectLen += 3+len; } // Tag 20 (max len = 64 ) if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 20 \n"); len = aECG->ReferringPhysician ? strlen(aECG->ReferringPhysician) : 0; if (len > 0) { *(ptr+sectionStart+curSectLen) = 20; // tag len = min(64,len+1); leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy((char*)(ptr+sectionStart+curSectLen+3),aECG->ReferringPhysician,len); curSectLen += 3+len; }; // Tag 21 (max len = 64 ) if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 21 \n"); len = aECG->MedicationDrugs ? strlen(aECG->MedicationDrugs) : 0; if (len>0) { *(ptr+sectionStart+curSectLen) = 21; // tag len = min(64,len+1); leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy((char*)(ptr+sectionStart+curSectLen+3),aECG->MedicationDrugs,len); curSectLen += 3+len; }; // Tag 22 (max len = 40 ) if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 22 \n"); len = hdr->ID.Technician ? strlen(hdr->ID.Technician) : 0; if (len > 0) { *(ptr+sectionStart+curSectLen) = 22; // tag len = min(64,len+1); leu16a(len, ptr+sectionStart+curSectLen+1); // length strncpy((char*)(ptr+sectionStart+curSectLen+3),hdr->ID.Technician,len); curSectLen += 3+len; } // Tag 24 ( len = 1 ) if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 24 \n"); *(ptr+sectionStart+curSectLen) = 24; // tag leu16a(1, ptr+sectionStart+curSectLen+1); // length *(ptr+sectionStart+curSectLen+3) = aECG->EmergencyLevel; curSectLen += 4; // Tag 25 (len = 4) if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 25 \n"); gdf_time T1 = hdr->T0; #ifndef __APPLE__ T1 += (int32_t)ldexp(timezone/86400.0,32); #endif T0_tm = gdf_time2tm_time(T1); *(ptr+sectionStart+curSectLen) = 25; // tag leu16a(4, ptr+sectionStart+curSectLen+1); // length leu16a(T0_tm->tm_year+1900, ptr+sectionStart+curSectLen+3);// year *(ptr+sectionStart+curSectLen+5) = (uint8_t)(T0_tm->tm_mon + 1);// month *(ptr+sectionStart+curSectLen+6) = (uint8_t)T0_tm->tm_mday; // day curSectLen += 7; // Tag 26 (len = 3) *(ptr+sectionStart+curSectLen) = 26; // tag leu16a(3, ptr+sectionStart+curSectLen+1); // length *(ptr+sectionStart+curSectLen+3) = (uint8_t)T0_tm->tm_hour; // hour *(ptr+sectionStart+curSectLen+4) = (uint8_t)T0_tm->tm_min; // minute *(ptr+sectionStart+curSectLen+5) = (uint8_t)T0_tm->tm_sec; // second curSectLen += 6; if (hdr->NS>0) { // Tag 27 (len = 3) highpass filter *(ptr+sectionStart+curSectLen) = 27; // tag leu16a(2, ptr+sectionStart+curSectLen+1); // length leu16a((uint16_t)hdr->CHANNEL[1].HighPass, ptr+sectionStart+curSectLen+3); // hour curSectLen += 5; // Tag 28 (len = 3) lowpass filter *(ptr+sectionStart+curSectLen) = 28; // tag leu16a(2, ptr+sectionStart+curSectLen+1); // length leu16a((uint16_t)hdr->CHANNEL[1].LowPass, ptr+sectionStart+curSectLen+3); // hour curSectLen += 5; // Tag 29 (len = 1) filter bitmap uint8_t bitmap = 0; if (fabs(hdr->CHANNEL[1].LowPass-60.0)<0.01) bitmap = 1; else if (fabs(hdr->CHANNEL[1].LowPass-50.0)<0.01) bitmap = 2; else bitmap = 0; *(ptr+sectionStart+curSectLen) = 29; // tag leu16a(1, ptr+sectionStart+curSectLen+1); // length *(ptr+sectionStart+curSectLen+3) = bitmap; curSectLen += 4; } // Tag 32 (len = 5) if (VERBOSE_LEVEL>7) fprintf(stdout,"Section 1 Tag 32 \n"); *(ptr+sectionStart+curSectLen) = 32; // tag leu16a(2, ptr+sectionStart+curSectLen+1); // length if (hdr->Patient.Impairment.Heart==1) { *(ptr+sectionStart+curSectLen+3) = 0; *(ptr+sectionStart+curSectLen+4) = 1; // Apparently healthy curSectLen += 5; } else if (hdr->Patient.Impairment.Heart==3) { *(ptr+sectionStart+curSectLen+3) = 0; *(ptr+sectionStart+curSectLen+4) = 42; // Implanted cardiac pacemaker curSectLen += 5; } // Tag 34 (len = 5) *(ptr+sectionStart+curSectLen) = 34; // tag leu16a(5, ptr+sectionStart+curSectLen+1); // length lei16a(hdr->tzmin, ptr+sectionStart+curSectLen+3); lei16a(0, ptr+sectionStart+curSectLen+5); curSectLen += 8; // Tag 255 (len = 0) *(ptr+sectionStart+curSectLen) = 255; // tag leu16a(0, ptr+sectionStart+curSectLen+1); // length curSectLen += 3; // Evaluate the size and correct it if odd if (curSectLen & 1) { *(ptr+sectionStart+curSectLen++) = 0; } if (VERBOSE_LEVEL>7) fprintf(stdout,"End-of-Section %i %p\n",curSect,ptr); } else if (curSect==2) // SECTION 2 { } else if (curSect==3) // SECTION 3 { ptr = (uint8_t*)realloc(ptr,sectionStart+16+2+9*hdr->NS+1); PtrCurSect = ptr+sectionStart; curSectLen = 16; // current section length // Number of leads enclosed *(ptr+sectionStart+curSectLen++) = hdr->NS; // ### Situations with reference beat subtraction are not supported // Situations with not all the leads simultaneously recorded are not supported // Situations number of leads simultaneouly recorded != total number of leads are not supported // We assume all the leads are recorded simultaneously *(ptr+sectionStart+curSectLen++) = (hdr->NS<<3) | 0x04; for (i = 0; i < hdr->NS; i++) { leu32a(1L, ptr+sectionStart+curSectLen); leu32a(hdr->data.size[0], ptr+sectionStart+curSectLen+4); *(ptr+sectionStart+curSectLen+8) = (uint8_t)hdr->CHANNEL[i].LeadIdCode; curSectLen += 9; } // Evaluate the size and correct it if odd if ((curSectLen % 2) != 0) { *(ptr+sectionStart+curSectLen++) = 0; } memset(ptr+sectionStart+10,0,6); // reserved } else if (curSect==4) // SECTION 4 { } else if (curSect==5) // SECTION 5 { curSectLen = 0; // current section length aECG->Section5.StartPtr = sectionStart; aECG->Section5.Length = curSectLen; } else if (curSect==6) // SECTION 6 { uint16_t GDFTYP = 3; size_t SZ = GDFTYP_BITS[GDFTYP]>>3; for (i = 0; i < hdr->NS; i++) hdr->CHANNEL[i].GDFTYP = GDFTYP; ptr = (uint8_t*)realloc(ptr,sectionStart+16+6+2*hdr->NS+SZ*(hdr->data.size[0]*hdr->data.size[1])); PtrCurSect = ptr+sectionStart; curSectLen = 16; // current section length // Create all the fields // Amplitude Value Multiplier (AVM) i = 0; AVM = hdr->CHANNEL[i].Cal * 1e9 * PhysDimScale(hdr->CHANNEL[i].PhysDimCode); for (i = 1; i < hdr->NS; i++) { // check for physical dimension and adjust scaling factor to "nV" avm = hdr->CHANNEL[i].Cal * 1e9 * PhysDimScale(hdr->CHANNEL[i].PhysDimCode); // check whether all channels have the same scaling factor if (fabs((AVM - avm)/AVM) > 1e-14) fprintf(stderr,"Warning SOPEN (SCP-WRITE): scaling factors differ between channel #1 and #%i. Scaling factor of 1st channel is used.\n",i+1); }; avm16 = lrint(AVM); leu16a(avm16, ptr+sectionStart+curSectLen); avm = leu16p(ptr+sectionStart+curSectLen); curSectLen += 2; if (fabs((AVM - avm)/AVM)>1e-14) fprintf(stderr,"Warning SOPEN (SCP-WRITE): Scaling factor has been truncated (%f instead %f).\n",avm,AVM); // Sample interval AVM = 1e6/hdr->SampleRate; avm16 = lrint(AVM); leu16a(avm16, ptr+sectionStart+curSectLen); avm = leu16p(ptr+sectionStart+curSectLen); curSectLen += 2; if (fabs((AVM - avm)/AVM)>1e-14) fprintf(stderr,"Warning SOPEN (SCP-WRITE): Sampling interval has been truncated (%f instead %f us).\n",avm,AVM); // Diff used *(ptr+sectionStart+curSectLen++) = 0; // Bimodal/Non-bimodal *(ptr+sectionStart+curSectLen++) = 0; /* DATA COMPRESSION currently, no compression method is supported. In case of data compression, the data compression can happen here. */ // Fill the length block for (i = 0; i < hdr->NS; i++) { leu16a((uint16_t)hdr->data.size[0]*2, ptr+sectionStart+curSectLen); avm = leu16p(ptr+sectionStart+curSectLen); AVM = hdr->data.size[0]*2; if (fabs((AVM - avm)/AVM)>1e-14) fprintf(stderr,"Warning SOPEN (SCP-WRITE): Block length truncated (%f instead %f us).\n",avm,AVM); curSectLen += 2; } /* data in channel multiplexed order */ for (i = 0; i < hdr->NS; i++) { hdr->CHANNEL[i].SPR *= hdr->NRec; }; hdr->NRec = 1; // Prepare filling the data block with the ECG samples by SWRITE // free(hdr->AS.rawdata); // hdr->AS.rawdata = PtrCurSect+16+6+2*hdr->NS; curSectLen += SZ*(hdr->data.size[0]*hdr->data.size[1]); // Evaluate the size and correct it if odd if ((curSectLen % 2) != 0) { fprintf(stderr,"Warning Section 6 has an odd length\n"); *(ptr+sectionStart+curSectLen++) = 0; } memset(ptr+sectionStart+10,0,6); // reserved aECG->Section6.StartPtr = sectionStart; aECG->Section6.Length = curSectLen; } #if (BIOSIG_VERSION >= 10500) else if (curSect==7) // SECTION 7