1 /*
2 
3     Copyright (C) 2012-2018 Alois Schloegl <alois.schloegl@gmail.com>
4     This file is part of the "BioSig for C/C++" repository
5     (biosig4c++) at http://biosig.sf.net/
6 
7 
8     BioSig is free software; you can redistribute it and/or
9     modify it under the terms of the GNU General Public License
10     as published by the Free Software Foundation; either version 3
11     of the License, or (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License
19     along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 
24 #include <assert.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "biosig.h"
29 
30 
31 /* =============================================================
32 	setter and getter functions for accessing fields of HDRTYPE
33    ============================================================= */
34 
biosig_get_filetype(HDRTYPE * hdr)35 enum FileFormat biosig_get_filetype(HDRTYPE *hdr) {
36 	if (hdr==NULL) return noFile;
37 	return hdr->TYPE;
38 }
biosig_set_filetype(HDRTYPE * hdr,enum FileFormat format)39 int biosig_set_filetype(HDRTYPE *hdr, enum FileFormat format) {
40 	if (hdr==NULL) return -1;
41 	hdr->TYPE=format;
42 	if (format==GDF)
43 	    hdr->VERSION = 1.0/0.0; // use latest version
44 	return 0;
45 }
46 
47 #if (BIOSIG_VERSION < 10700)
biosig_set_flags(HDRTYPE * hdr,char compression,char ucal,char overflowdetection)48 ATT_DEPREC int biosig_set_flags(HDRTYPE *hdr, char compression, char ucal, char overflowdetection) {
49 	fprintf(stderr,"Warning libbiosig2: function biosig_set_flags() is deprecated, use biosig_(re)set_flag() instead\n");
50 	if (hdr==NULL) return -1;
51 	hdr->FLAG.UCAL = ucal;
52 	hdr->FLAG.OVERFLOWDETECTION = overflowdetection;
53 	hdr->FILE.COMPRESSION = compression;
54 	return 0;
55 }
56 #endif
57 
biosig_get_flag(HDRTYPE * hdr,unsigned flags)58 int biosig_get_flag(HDRTYPE *hdr, unsigned flags) {
59 	if (hdr==NULL) return -1;
60 	return flags & ( \
61 		(!!hdr->FLAG.OVERFLOWDETECTION) * (unsigned)BIOSIG_FLAG_OVERFLOWDETECTION \
62 		+ (!!hdr->FLAG.UCAL) * (unsigned)BIOSIG_FLAG_UCAL \
63 		+ (!!hdr->FILE.COMPRESSION) * (unsigned)BIOSIG_FLAG_COMPRESSION \
64 		+ (!!hdr->FLAG.UCAL) * (unsigned)BIOSIG_FLAG_UCAL \
65 		+ (!!hdr->FLAG.ROW_BASED_CHANNELS)* (unsigned)BIOSIG_FLAG_ROW_BASED_CHANNELS \
66 		) ;
67 }
68 
biosig_set_flag(HDRTYPE * hdr,unsigned flags)69 int biosig_set_flag(HDRTYPE *hdr, unsigned flags) {
70 	if (hdr==NULL) return -1;
71 	hdr->FLAG.UCAL               |= !!(flags & BIOSIG_FLAG_UCAL);
72 	hdr->FLAG.OVERFLOWDETECTION  |= !!(flags & BIOSIG_FLAG_OVERFLOWDETECTION);
73 	hdr->FILE.COMPRESSION        |= !!(flags & BIOSIG_FLAG_COMPRESSION);
74 	hdr->FLAG.ROW_BASED_CHANNELS |= !!(flags & BIOSIG_FLAG_ROW_BASED_CHANNELS);
75 	return 0;
76 };
77 
biosig_reset_flag(HDRTYPE * hdr,unsigned flags)78 int biosig_reset_flag(HDRTYPE *hdr, unsigned flags) {
79 	if (hdr==NULL) return -1;
80 	hdr->FLAG.UCAL               &= !(flags & BIOSIG_FLAG_UCAL);
81 	hdr->FLAG.OVERFLOWDETECTION  &= !(flags & BIOSIG_FLAG_OVERFLOWDETECTION);
82 	hdr->FILE.COMPRESSION        &= !(flags & BIOSIG_FLAG_COMPRESSION);
83 	hdr->FLAG.ROW_BASED_CHANNELS &= !(flags & BIOSIG_FLAG_ROW_BASED_CHANNELS);
84 	return 0;
85 };
86 
biosig_get_targetsegment(HDRTYPE * hdr)87 int biosig_get_targetsegment(HDRTYPE *hdr) {
88 	if (hdr==NULL) return -1;
89 	return hdr->FLAG.TARGETSEGMENT;
90 };
91 
biosig_get_filename(HDRTYPE * hdr)92 const char* biosig_get_filename(HDRTYPE *hdr) {
93 	if (hdr==NULL) return NULL;
94 	return hdr->FileName;
95 };
biosig_get_version(HDRTYPE * hdr)96 float biosig_get_version(HDRTYPE *hdr) {
97 	if (hdr==NULL) return NAN;
98 	return hdr->VERSION;
99 };
100 
101 
biosig_set_targetsegment(HDRTYPE * hdr,unsigned targetsegment)102 int biosig_set_targetsegment(HDRTYPE *hdr, unsigned targetsegment) {
103 	return biosig_set_segment_selection(hdr, 0, targetsegment);
104 };
biosig_set_segment_selection(HDRTYPE * hdr,int k,uint32_t argSweepSel)105 int biosig_set_segment_selection(HDRTYPE *hdr, int k, uint32_t argSweepSel) {;
106 	if (hdr==NULL) return -1;
107 	if (k>5 || k<0) return -3;
108 	if (k==0) {
109 		if (argSweepSel > 127) {
110 			fprintf(stderr,"Warning libbiosig2: biosig_set_targetsegment is larger than 127 (%i)\n", argSweepSel);
111 			return -2;
112 		}
113 		hdr->FLAG.TARGETSEGMENT = argSweepSel;
114 	}
115 	else
116 		hdr->AS.SegSel[k-1] = argSweepSel;
117 	return 0;
118 }
biosig_get_segment_selection(HDRTYPE * hdr)119 uint32_t* biosig_get_segment_selection(HDRTYPE *hdr) {
120 	if (hdr==NULL) return NULL;
121 	return (uint32_t*)&(hdr->AS.SegSel);
122 };
123 
biosig_get_number_of_channels(HDRTYPE * hdr)124 long biosig_get_number_of_channels(HDRTYPE *hdr) {
125 	if (hdr==NULL) return -1;
126 	long k,m;
127 	for (k=0,m=0; k<hdr->NS; k++)
128 		if (hdr->CHANNEL[k].OnOff==1) {
129 			m++;
130 		}
131 	return m;
132 }
biosig_get_number_of_records(HDRTYPE * hdr)133 size_t biosig_get_number_of_records(HDRTYPE *hdr) {
134 	if (hdr==NULL) return -1;
135 	return hdr->NRec;
136 }
biosig_get_number_of_samples(HDRTYPE * hdr)137 size_t biosig_get_number_of_samples(HDRTYPE *hdr) {
138 	if (hdr==NULL) return -1;
139 	return hdr->NRec*hdr->SPR;
140 }
biosig_get_number_of_samples_per_record(HDRTYPE * hdr)141 size_t biosig_get_number_of_samples_per_record(HDRTYPE *hdr) {
142 	if (hdr==NULL) return -1;
143 	return hdr->SPR;
144 }
biosig_get_number_of_segments(HDRTYPE * hdr)145 size_t biosig_get_number_of_segments(HDRTYPE *hdr) {
146 	if (hdr==NULL) return 0;
147 	if (hdr->SPR==0) return 0;
148 	size_t k, n;
149 	for (k=0, n=1; k<hdr->EVENT.N; k++)
150 		if (hdr->EVENT.TYP[k]==0x7ffe) n++;
151 	return n;
152 }
153 
biosig_set_number_of_channels(HDRTYPE * hdr,int ns)154 int biosig_set_number_of_channels(HDRTYPE *hdr, int ns) {
155 	if (hdr==NULL) return -1;
156 	// define variable header
157 	void *ptr = realloc(hdr->CHANNEL, ns*sizeof(CHANNEL_TYPE));
158 	if (ptr==NULL) return -1;
159 	hdr->CHANNEL = (CHANNEL_TYPE*)ptr;
160 	int k;
161 	for (k=hdr->NS; k < ns; k++) {
162 		// initialize new channels
163 		CHANNEL_TYPE *hc = hdr->CHANNEL+k;
164 		hc->Label[0]  = 0;
165 		hc->LeadIdCode= 0;
166 		strcpy(hc->Transducer, "EEG: Ag-AgCl electrodes");
167 		hc->PhysDimCode = 19+4256; // uV
168 		hc->PhysMax   = +100;
169 		hc->PhysMin   = -100;
170 		hc->DigMax    = +2047;
171 		hc->DigMin    = -2048;
172 		hc->Cal	      = NAN;
173 		hc->Off	      = 0.0;
174 		hc->TOffset   = 0.0;
175 		hc->GDFTYP    = 3;	// int16
176 		hc->SPR       = 1;	// one sample per block
177 		hc->bi 	      = 2*k;
178 		hc->bi8	      = 16*k;
179 		hc->OnOff     = 1;
180 		hc->HighPass  = 0.16;
181 		hc->LowPass   = 70.0;
182 		hc->Notch     = 50;
183 		hc->Impedance = INFINITY;
184 		hc->fZ        = NAN;
185 		hc->XYZ[0] 	= 0.0;
186 		hc->XYZ[1] 	= 0.0;
187 		hc->XYZ[2] 	= 0.0;
188 	}
189 	hdr->NS = ns;
190 	return 0;
191 }
biosig_set_number_of_samples(HDRTYPE * hdr,ssize_t nrec,ssize_t spr)192 int biosig_set_number_of_samples(HDRTYPE *hdr, ssize_t nrec, ssize_t spr) {
193 	if (hdr==NULL) return -1;
194 	if (nrec >= 0) hdr->NRec = nrec;
195 	if (spr  >= 0) hdr->SPR  = spr;
196 	return 0;
197 }
198 //ATT_DEPREC int biosig_set_number_of_segments(HDRTYPE *hdr, )
199 
biosig_get_datablock(HDRTYPE * hdr,double ** data,size_t * rows,size_t * columns)200 int biosig_get_datablock(HDRTYPE *hdr, double **data, size_t *rows, size_t *columns ) {
201 	if (hdr==NULL) return -1;
202 	*data = hdr->data.block;
203 	*rows = hdr->data.size[0];
204 	*columns = hdr->data.size[1];
205 	return 0;
206 }
biosig_get_data(HDRTYPE * hdr,char flag)207 biosig_data_type* biosig_get_data(HDRTYPE *hdr, char flag ) {
208 	if (hdr==NULL) return NULL;
209         hdr->FLAG.ROW_BASED_CHANNELS = flag;
210         sread(NULL, 0, hdr->NRec, hdr);
211 	return hdr->data.block;
212 }
biosig_get_samplerate(HDRTYPE * hdr)213 double biosig_get_samplerate(HDRTYPE *hdr) {
214 	if (hdr==NULL) return NAN;
215 	return hdr->SampleRate;
216 }
biosig_set_samplerate(HDRTYPE * hdr,double fs)217 int biosig_set_samplerate(HDRTYPE *hdr, double fs) {
218 	if (hdr==NULL) return -1;
219 	hdr->SampleRate=fs;
220 	return 0;
221 }
222 
223 
biosig_get_number_of_events(HDRTYPE * hdr)224 size_t biosig_get_number_of_events(HDRTYPE *hdr) {
225 	if (hdr==NULL) return 0;
226 	return hdr->EVENT.N;
227 }
biosig_set_number_of_events(HDRTYPE * hdr,size_t N)228 size_t biosig_set_number_of_events(HDRTYPE *hdr, size_t N) {
229 	if (hdr==NULL) return 0;
230 	size_t k;
231 	hdr->EVENT.POS = (uint32_t*) realloc(hdr->EVENT.POS, N * 4 );
232 	hdr->EVENT.TYP = (uint16_t*) realloc(hdr->EVENT.TYP, N * 2 );
233 	for (k = hdr->EVENT.N; k<N; k++) {
234 		hdr->EVENT.POS[k] = 0;
235 		hdr->EVENT.TYP[k] = 0;
236 	}
237 	k = ( (hdr->EVENT.DUR==NULL) || (hdr->EVENT.CHN==NULL) ) ? 0 : hdr->EVENT.N;
238 	hdr->EVENT.DUR = (uint32_t*) realloc(hdr->EVENT.DUR, N * 4 );
239 	hdr->EVENT.CHN = (uint16_t*) realloc(hdr->EVENT.CHN, N * 2 );
240 	for (; k<N; k++) {
241 		hdr->EVENT.CHN[k] = 0;
242 		hdr->EVENT.DUR[k] = 0;
243 	}
244 	k = (hdr->EVENT.TimeStamp==NULL) ? 0 : hdr->EVENT.N;
245 	hdr->EVENT.TimeStamp = (gdf_time*) realloc(hdr->EVENT.TimeStamp, N * 8 );
246 	for (; k<N; k++) {
247 		hdr->EVENT.TimeStamp[k] = 0;
248 	}
249 	hdr->EVENT.N = N;
250 	return hdr->EVENT.N;
251 }
252 
biosig_get_nth_event(HDRTYPE * hdr,size_t n,uint16_t * typ,uint32_t * pos,uint16_t * chn,uint32_t * dur,gdf_time * timestamp,const char ** desc)253 int biosig_get_nth_event(HDRTYPE *hdr, size_t n, uint16_t *typ, uint32_t *pos, uint16_t *chn, uint32_t *dur, gdf_time *timestamp, const char **desc) {
254 	if (hdr==NULL) return -1;
255 	if (hdr->EVENT.N <= n) return -1;
256 	uint16_t TYP=hdr->EVENT.TYP[n];
257 	if (typ != NULL)
258 		*typ = TYP;
259 	if (pos != NULL)
260 		*pos = hdr->EVENT.POS[n];
261 	if (chn != NULL)
262 		*chn = (hdr->EVENT.CHN==NULL) ? 0 : hdr->EVENT.CHN[n];
263 	if (dur != NULL)
264 		*dur = (hdr->EVENT.DUR==NULL) ? 0 : hdr->EVENT.DUR[n];
265 	if (timestamp != NULL)
266 		*timestamp = (hdr->EVENT.TimeStamp==NULL) ? 0 : hdr->EVENT.TimeStamp[n];
267 	if ( (desc != NULL) )
268 		*desc = (TYP < hdr->EVENT.LenCodeDesc) ? hdr->EVENT.CodeDesc[TYP] : NULL;
269 	return 0;
270 }
biosig_set_nth_event(HDRTYPE * hdr,size_t n,uint16_t * typ,uint32_t * pos,uint16_t * chn,uint32_t * dur,gdf_time * timestamp,char * Desc)271 int biosig_set_nth_event(HDRTYPE *hdr, size_t n, uint16_t* typ, uint32_t *pos, uint16_t *chn, uint32_t *dur, gdf_time *timestamp, char *Desc) {
272 	if (hdr==NULL) return -1;
273 	if (hdr->EVENT.N <= n)
274 		biosig_set_number_of_events(hdr, n+1);
275 
276 	if (typ != NULL)
277 		hdr->EVENT.TYP[n] = *typ;
278 	else if (typ == NULL)
279 		FreeTextEvent(hdr, n, Desc);   // sets hdr->EVENT.TYP[n]
280 
281 	if (pos != NULL)
282 		hdr->EVENT.POS[n] = *pos;
283 	if (chn != NULL)
284 		hdr->EVENT.CHN[n] = *chn;
285 	if (dur != NULL)
286 		hdr->EVENT.DUR[n] = *dur;
287 	if (timestamp != NULL)
288 		hdr->EVENT.TimeStamp[n] = *timestamp;
289 
290 	return 0;
291 }
292 
biosig_get_eventtable_samplerate(HDRTYPE * hdr)293 double biosig_get_eventtable_samplerate(HDRTYPE *hdr) {
294 	if (hdr==NULL) return NAN;
295 	return hdr->EVENT.SampleRate;
296 }
biosig_set_eventtable_samplerate(HDRTYPE * hdr,double fs)297 int biosig_set_eventtable_samplerate(HDRTYPE *hdr, double fs) {
298 	if (hdr==NULL) return -1;
299 	hdr->EVENT.SampleRate=fs;
300 	return 0;
301 }
biosig_change_eventtable_samplerate(HDRTYPE * hdr,double fs)302 int biosig_change_eventtable_samplerate(HDRTYPE *hdr, double fs) {
303 	if (hdr==NULL) return -1;
304 	if (hdr->EVENT.SampleRate==fs) return 0;
305 	size_t k;
306 	double ratio = fs/hdr->EVENT.SampleRate;
307 	for (k = 0; k < hdr->EVENT.N; k++) {
308 		uint32_t POS = hdr->EVENT.POS[k];
309 		hdr->EVENT.POS[k] = ratio*POS;
310 		if (hdr->EVENT.DUR != NULL)
311 			hdr->EVENT.DUR[k] = (POS + hdr->EVENT.DUR[k]) * ratio - hdr->EVENT.POS[k];
312 	}
313 	hdr->EVENT.SampleRate=fs;
314 	return 0;
315 }
316 
317 // deprecated because time resolution is lost, use gdftime and its tools instead.
biosig_get_startdatetime(HDRTYPE * hdr,struct tm * T)318 __attribute__ ((deprecated)) int biosig_get_startdatetime(HDRTYPE *hdr, struct tm *T) {
319 	if (hdr==NULL) return -1;
320 	gdf_time2tm_time_r(hdr->T0, T);
321 	return (ldexp(hdr->T0,-32)<100.0);
322 }
biosig_set_startdatetime(HDRTYPE * hdr,struct tm T)323 int biosig_set_startdatetime(HDRTYPE *hdr, struct tm T) {
324 	if (hdr==NULL) return -1;
325 	hdr->T0 = tm_time2gdf_time(&T);
326 	return (ldexp(hdr->T0,-32)<100.0);
327 }
328 
biosig_get_startdatetime_gdf(HDRTYPE * hdr)329 gdf_time biosig_get_startdatetime_gdf(HDRTYPE *hdr) {
330 	if (hdr==NULL) return 0;
331 	return(hdr->T0);
332 }
biosig_set_startdatetime_gdf(HDRTYPE * hdr,gdf_time T)333 int biosig_set_startdatetime_gdf(HDRTYPE *hdr, gdf_time T) {
334 	if (hdr==NULL) return -1;
335 	hdr->T0 = T;
336 	return (ldexp(hdr->T0,-32)<100.0);
337 }
338 
339 // deprecated because time resolution is lost, use gdftime and its tools instead.
biosig_get_birthdate(HDRTYPE * hdr,struct tm * T)340 __attribute__ ((deprecated)) int biosig_get_birthdate(HDRTYPE *hdr, struct tm *T) {
341 	if (hdr==NULL) return -1;
342 	gdf_time2tm_time_r(hdr->Patient.Birthday, T);
343 	return (ldexp(hdr->Patient.Birthday,-32)<100.0);
344 }
biosig_set_birthdate(HDRTYPE * hdr,struct tm T)345 int biosig_set_birthdate(HDRTYPE *hdr, struct tm T) {
346 	if (hdr==NULL) return -1;
347 	hdr->Patient.Birthday = tm_time2gdf_time(&T);
348 	return (ldexp(hdr->Patient.Birthday,-32)<100.0);
349 }
350 
biosig_get_patient_name(HDRTYPE * hdr)351 const char* biosig_get_patient_name(HDRTYPE *hdr) {
352 	if (hdr==NULL) return NULL;
353 	return hdr->Patient.Name;
354 }
355 
biosig_get_patient_lastname(HDRTYPE * hdr,size_t * LengthLastName)356 const char* biosig_get_patient_lastname(HDRTYPE *hdr, size_t *LengthLastName) {
357 	if (hdr==NULL) return NULL;
358 	*LengthLastName	=  strcspn(hdr->Patient.Name, "\x1f");
359 	return hdr->Patient.Name;
360 }
biosig_get_patient_firstname(HDRTYPE * hdr,size_t * LengthFirstName)361 const char* biosig_get_patient_firstname(HDRTYPE *hdr, size_t *LengthFirstName) {
362 	if (hdr==NULL) return NULL;
363 	char *tmpstr = strchr(hdr->Patient.Name, 0x1f);
364 	if (tmpstr==NULL) {
365 		*LengthFirstName = 0;
366 		return NULL;
367 	}
368 	*LengthFirstName = strcspn(tmpstr, "\x1f");
369 	return tmpstr;
370 }
biosig_get_patient_secondlastname(HDRTYPE * hdr,size_t * LengthSecondLastName)371 const char* biosig_get_patient_secondlastname(HDRTYPE *hdr, size_t *LengthSecondLastName) {
372 	if (hdr==NULL) return NULL;
373 	char *tmpstr = strchr(hdr->Patient.Name, 0x1f);
374 	if (tmpstr != NULL)
375 		tmpstr = strchr(tmpstr, 0x1f);
376 	if (tmpstr==NULL) {
377 		*LengthSecondLastName = 0;
378 		return NULL;
379 	}
380 	*LengthSecondLastName = strcspn(tmpstr, "\x1f");
381 	return tmpstr;
382 }
383 
384 
biosig_get_patient_id(HDRTYPE * hdr)385 const char* biosig_get_patient_id(HDRTYPE *hdr) {
386 	if (hdr==NULL) return NULL;
387 	return hdr->Patient.Id;
388 }
biosig_get_recording_id(HDRTYPE * hdr)389 const char* biosig_get_recording_id(HDRTYPE *hdr) {
390 	if (hdr==NULL) return NULL;
391 	return hdr->ID.Recording;
392 }
biosig_get_technician(HDRTYPE * hdr)393 const char* biosig_get_technician(HDRTYPE *hdr) {
394 	if (hdr==NULL) return NULL;
395 	return hdr->ID.Technician;
396 }
biosig_get_manufacturer_name(HDRTYPE * hdr)397 const char* biosig_get_manufacturer_name(HDRTYPE *hdr) {
398 	if (hdr==NULL) return NULL;
399 	return hdr->ID.Manufacturer.Name;
400 }
biosig_get_manufacturer_model(HDRTYPE * hdr)401 const char* biosig_get_manufacturer_model(HDRTYPE *hdr) {
402 	if (hdr==NULL) return NULL;
403 	return hdr->ID.Manufacturer.Model;
404 }
biosig_get_manufacturer_version(HDRTYPE * hdr)405 const char* biosig_get_manufacturer_version(HDRTYPE *hdr) {
406 	if (hdr==NULL) return NULL;
407 	return hdr->ID.Manufacturer.Version;
408 }
biosig_get_manufacturer_serial_number(HDRTYPE * hdr)409 const char* biosig_get_manufacturer_serial_number(HDRTYPE *hdr) {
410 	if (hdr==NULL) return NULL;
411 	return hdr->ID.Manufacturer.SerialNumber;
412 }
biosig_get_application_specific_information(HDRTYPE * hdr)413 const char* biosig_get_application_specific_information(HDRTYPE *hdr) {
414 	if (hdr==NULL) return NULL;
415 	return hdr->AS.bci2000;
416 }
417 
biosig_set_patient_name(HDRTYPE * hdr,const char * name)418 int biosig_set_patient_name(HDRTYPE *hdr, const char* name) {
419 	if (hdr==NULL) return -1;
420 	strncpy(hdr->Patient.Name, name, MAX_LENGTH_NAME);
421 	hdr->Patient.Name[MAX_LENGTH_NAME]=0;
422 }
423 
biosig_set_patient_name_structured(HDRTYPE * hdr,const char * LastName,const char * FirstName,const char * SecondLastName)424 int biosig_set_patient_name_structured(HDRTYPE *hdr, const char* LastName, const char* FirstName, const char* SecondLastName) {
425 	if (hdr==NULL) return -1;
426 	size_t len1 = (LastName ? strlen(LastName) : 0 );
427 	size_t len2 = (FirstName ? strlen(FirstName) : 0 );
428 	size_t len3 = (SecondLastName ? strlen(SecondLastName) : 0 );
429 	if (len1+len2+len3+2 > MAX_LENGTH_NAME) {
430 		fprintf(stderr,"Error in function %s(...): total length of name too large (%i > %i)\n",__func__, (int)(len1+len2+len3+2), MAX_LENGTH_NAME);
431 		return -1;
432 	}
433 	strcpy(hdr->Patient.Name, LastName);					// Flawfinder: ignore
434 	if (FirstName != NULL) {
435 		hdr->Patient.Name[len1]=0x1f;
436 		strcpy(hdr->Patient.Name+len1+1, FirstName);			// Flawfinder: ignore
437 	}
438 	if (SecondLastName != NULL) {
439 		hdr->Patient.Name[len1+len2+1]=0x1f;
440 		strcpy(hdr->Patient.Name+len1+len2+2, SecondLastName);		// Flawfinder: ignore
441 	}
442 	return 0;
443 }
biosig_set_patient_id(HDRTYPE * hdr,const char * id)444 int biosig_set_patient_id(HDRTYPE *hdr, const char* id) {
445 	if (hdr==NULL) return -1;
446 	strncpy(hdr->Patient.Id, id, MAX_LENGTH_PID);
447 	hdr->Patient.Id[MAX_LENGTH_PID]=0;
448 	return 0;
449 }
biosig_set_recording_id(HDRTYPE * hdr,const char * rid)450 int biosig_set_recording_id(HDRTYPE *hdr, const char* rid) {
451 	if (hdr==NULL) return -1;
452 	strncpy(hdr->ID.Recording, rid, MAX_LENGTH_RID);
453 	hdr->ID.Recording[MAX_LENGTH_RID]=0;
454 	return 0;
455 }
biosig_set_technician(HDRTYPE * hdr,const char * technician)456 int biosig_set_technician(HDRTYPE *hdr, const char* technician) {
457 	if (hdr==NULL) return -1;
458 	hdr->ID.Technician = (char*)technician;
459 	return 0;
460 }
biosig_set_manufacturer_name(HDRTYPE * hdr,const char * rid)461 int biosig_set_manufacturer_name(HDRTYPE *hdr, const char* rid) {
462 	if (hdr==NULL) return -1;
463 	hdr->ID.Manufacturer.Name = (char*)rid;
464 	return 0;
465 }
biosig_set_manufacturer_model(HDRTYPE * hdr,const char * rid)466 int biosig_set_manufacturer_model(HDRTYPE *hdr, const char* rid) {
467 	if (hdr==NULL) return -1;
468 	hdr->ID.Manufacturer.Model = rid;
469 	return 0;
470 }
biosig_set_manufacturer_version(HDRTYPE * hdr,const char * rid)471 int biosig_set_manufacturer_version(HDRTYPE *hdr, const char* rid) {
472 	if (hdr==NULL) return -1;
473 	hdr->ID.Manufacturer.Version = rid;
474 	return 0;
475 }
biosig_set_manufacturer_serial_number(HDRTYPE * hdr,const char * rid)476 int biosig_set_manufacturer_serial_number(HDRTYPE *hdr, const char* rid) {
477 	if (hdr==NULL) return -1;
478 	hdr->ID.Manufacturer.SerialNumber = rid;
479 	return 0;
480 }
biosig_set_application_specific_information(HDRTYPE * hdr,const char * appinfo)481 int biosig_set_application_specific_information(HDRTYPE *hdr, const char* appinfo) {
482 	if (hdr==NULL) return -1;
483 	hdr->AS.bci2000 = strdup(appinfo);
484 	return 0;
485 }
486 
487 // returns M-th channel, M is 0-based
biosig_get_channel(HDRTYPE * hdr,int M)488 CHANNEL_TYPE* biosig_get_channel(HDRTYPE *hdr, int M) {
489 	if (hdr==NULL) return NULL;
490 	typeof(hdr->NS) k,m;
491 	for (k=0,m=0; k<hdr->NS; k++)
492 		if (hdr->CHANNEL[k].OnOff==1) {
493 			if (M==m) return hdr->CHANNEL+k;
494 			m++;
495 		}
496 	return NULL;
497 }
498 
biosig_channel_change_scale_to_physdimcode(CHANNEL_TYPE * hc,uint16_t physdimcode)499 int biosig_channel_change_scale_to_physdimcode(CHANNEL_TYPE *hc, uint16_t physdimcode) {
500 	if (hc==NULL) return -1;
501 	if (hc->PhysDimCode == physdimcode) return 0; 	// nothing to do
502 	if ( (hc->PhysDimCode & 0xffe0) != (physdimcode & 0xffe0) ) return -2; 	// units do not match
503         double scale = PhysDimScale(hc->PhysDimCode);
504         scale /= PhysDimScale(physdimcode);
505 	hc->PhysDimCode = physdimcode;
506         hc->PhysMax *= scale;
507         hc->PhysMin *= scale;
508         hc->Cal *= scale;
509         hc->Off *= scale;
510 	return(0);
511 }
biosig_channel_get_label(CHANNEL_TYPE * hc)512 const char* biosig_channel_get_label(CHANNEL_TYPE *hc) {
513 	if (hc==NULL) return NULL;
514 	return hc->Label;
515 }
biosig_channel_get_physdimcode(CHANNEL_TYPE * hc)516 uint16_t biosig_channel_get_physdimcode(CHANNEL_TYPE *hc) {
517 	if (hc==NULL) return 0;
518 	return hc->PhysDimCode;
519 }
biosig_channel_get_physdim(CHANNEL_TYPE * hc)520 const char* biosig_channel_get_physdim(CHANNEL_TYPE *hc) {
521 	if (hc==NULL) return NULL;
522 	return PhysDim3(hc->PhysDimCode);
523 }
biosig_channel_set_label(CHANNEL_TYPE * hc,const char * label)524 int biosig_channel_set_label(CHANNEL_TYPE *hc, const char* label) {
525 	if (hc==NULL) return -1;
526 	strncpy(hc->Label, label, MAX_LENGTH_LABEL);
527 	hc->Label[MAX_LENGTH_LABEL]=0;
528 	return 0;
529 }
biosig_channel_set_physdimcode(CHANNEL_TYPE * hc,uint16_t physdimcode)530 int biosig_channel_set_physdimcode(CHANNEL_TYPE *hc, uint16_t physdimcode) {
531 	if (hc==NULL) return -1;
532 	hc->PhysDimCode = physdimcode;
533 	return 0;
534 }
535 
536 
biosig_channel_get_scaling(CHANNEL_TYPE * hc,double * PhysMax,double * PhysMin,double * DigMax,double * DigMin)537 int biosig_channel_get_scaling(CHANNEL_TYPE *hc, double *PhysMax, double *PhysMin, double *DigMax, double *DigMin) {
538 	if (hc==NULL) return -1;
539 	if (PhysMax != NULL)
540 		*PhysMax = hc->PhysMax;
541 	if (PhysMin != NULL)
542 		*PhysMax = hc->PhysMin;
543 	if (DigMax != NULL)
544 		*DigMax = hc->DigMax;
545 	if (DigMin != NULL)
546 		*DigMin = hc->DigMin;
547 	return 0;
548 }
biosig_channel_set_scaling(CHANNEL_TYPE * hc,double PhysMax,double PhysMin,double DigMax,double DigMin)549 int biosig_channel_set_scaling(CHANNEL_TYPE *hc, double PhysMax, double PhysMin, double DigMax, double DigMin) {
550 	if (hc==NULL) return -1;
551 	hc->PhysMax = PhysMax;
552 	hc->PhysMin = PhysMin;
553 	hc->DigMax = DigMax;
554 	hc->DigMin = DigMin;
555 	hc->Cal    = ( PhysMax - PhysMin) / ( DigMax - DigMin );
556 	hc->Off    = PhysMin - DigMin * hc->Cal;
557 	return 0;
558 }
559 
biosig_channel_get_cal(CHANNEL_TYPE * hc)560 double biosig_channel_get_cal(CHANNEL_TYPE *hc) {
561 	if (hc==NULL) return -1;
562 	double cal = ( hc->PhysMax - hc->PhysMin) / ( hc->DigMax - hc->DigMin );
563 	assert(cal==hc->Cal);
564 	return (cal);
565 }
biosig_channel_get_off(CHANNEL_TYPE * hc)566 double biosig_channel_get_off(CHANNEL_TYPE *hc) {
567 	if (hc==NULL) return -1;
568 	double off = hc->PhysMin - hc->DigMin * hc->Cal;
569 	assert(off==hc->Off);
570 	return off;
571 }
572 
biosig_channel_set_cal(CHANNEL_TYPE * hc,double cal)573 int biosig_channel_set_cal(CHANNEL_TYPE *hc, double cal) {
574 	if (hc==NULL) return -1;
575 	hc->Cal = cal;
576 	return 0;
577 }
biosig_channel_set_off(CHANNEL_TYPE * hc,double off)578 int biosig_channel_set_off(CHANNEL_TYPE *hc, double off) {
579 	if (hc==NULL) return -1;
580 	hc->Off = off;
581 	return 0;
582 }
583 
biosig_channel_get_filter(CHANNEL_TYPE * hc,double * LowPass,double * HighPass,double * Notch)584 int biosig_channel_get_filter(CHANNEL_TYPE *hc, double *LowPass, double *HighPass, double *Notch) {
585 	if (hc==NULL) return -1;
586 	if (LowPass != NULL)
587 		*LowPass = hc->LowPass;
588 	if (HighPass != NULL)
589 		*HighPass = hc->HighPass;
590 	if (Notch != NULL)
591 		*Notch = hc->Notch;
592 	return 0;
593 }
biosig_channel_set_filter(CHANNEL_TYPE * hc,double LowPass,double HighPass,double Notch)594 int biosig_channel_set_filter(CHANNEL_TYPE *hc, double LowPass, double HighPass, double Notch) {
595 	if (hc==NULL) return -1;
596 	hc->LowPass = LowPass;
597 	hc->HighPass = HighPass;
598 	hc->Notch = Notch;
599 	return 0;
600 }
601 
biosig_channel_get_timing_offset(CHANNEL_TYPE * hc)602 double biosig_channel_get_timing_offset(CHANNEL_TYPE *hc) {
603 	if (hc==NULL) return -1;
604 	return hc->TOffset;
605 }
biosig_channel_set_timing_offset(CHANNEL_TYPE * hc,double off)606 int biosig_channel_set_timing_offset(CHANNEL_TYPE *hc, double off) {
607 	if (hc==NULL) return -1;
608 	hc->TOffset = off;
609 	return 0;
610 }
611 
biosig_channel_get_impedance(CHANNEL_TYPE * hc)612 double biosig_channel_get_impedance(CHANNEL_TYPE *hc) {
613 	if (hc==NULL) return -1;
614 	return ( (hc->PhysDimCode & 0x7ffe) == 4256 ) ? hc->Impedance : NAN;
615 }
biosig_channel_set_impedance(CHANNEL_TYPE * hc,double val)616 int biosig_channel_set_impedance(CHANNEL_TYPE *hc, double val) {
617 	if (hc==NULL) return -1;
618 	if ( (hc->PhysDimCode & 0x7ffe) != 4256 ) return -1;
619 	hc->Impedance = val;
620 	return 0;
621 }
622 
biosig_channel_get_datatype(CHANNEL_TYPE * hc)623 uint16_t biosig_channel_get_datatype(CHANNEL_TYPE *hc) {
624 	if (hc==NULL) return -1;
625 	return hc->GDFTYP;
626 }
biosig_channel_set_datatype(CHANNEL_TYPE * hc,uint16_t gdftyp)627 int biosig_channel_set_datatype(CHANNEL_TYPE *hc, uint16_t gdftyp) {
628 	if (hc==NULL) return -1;
629 	hc->GDFTYP = gdftyp;
630 	return 0;
631 }
632 
biosig_get_channel_samplerate(HDRTYPE * hdr,int chan)633 double biosig_get_channel_samplerate(HDRTYPE *hdr, int chan) {
634 	CHANNEL_TYPE *hc = biosig_get_channel(hdr, chan);
635 	if (hc==NULL) return -1;
636 	if (hdr==NULL) return -1;
637 	return (hdr->SampleRate * hc->SPR / hdr->SPR);
638 }
biosig_channel_get_samples_per_record(CHANNEL_TYPE * hc)639 size_t biosig_channel_get_samples_per_record(CHANNEL_TYPE *hc) {
640 	if (hc==NULL) return -1;
641 	return hc->SPR;
642 }
biosig_channel_set_samples_per_record(CHANNEL_TYPE * hc,size_t spr)643 int	biosig_channel_set_samples_per_record(CHANNEL_TYPE *hc, size_t spr)  {
644 	if (hc==NULL) return -1;
645 	hc->SPR = spr;
646 	return 0;
647 }
648 
biosig_set_channel_samplerate_and_samples_per_record(HDRTYPE * hdr,int chan,ssize_t spr,double fs)649 int  biosig_set_channel_samplerate_and_samples_per_record(HDRTYPE *hdr, int chan, ssize_t spr, double fs)  {
650 	CHANNEL_TYPE *hc = biosig_get_channel(hdr,chan);
651 	if (hc==NULL) return -1;
652 	if ((spr <= 0) && (fs >= 0.0)) {
653 		hc->SPR = hdr->SPR * fs / hdr->SampleRate;
654 		return 0;
655 	}
656 	if ((spr >= 0) && (fs != fs)) {
657 		hc->SPR = spr;
658 		return 0;
659 	}
660 	assert (hdr->SampleRate * hc->SPR == fs * hdr->SPR);
661 	return (hdr->SampleRate * hc->SPR != fs * hdr->SPR);
662 }
663 
biosig_channel_get_transducer(CHANNEL_TYPE * hc)664 const char *biosig_channel_get_transducer(CHANNEL_TYPE *hc) {
665 
666 	if (hc==NULL) return(NULL);
667 	return (hc->Transducer);
668 }
669 
biosig_channel_set_transducer(CHANNEL_TYPE * hc,const char * transducer)670 int biosig_channel_set_transducer(CHANNEL_TYPE *hc, const char *transducer) {
671 
672 	if (hc==NULL) return(-1);
673 	strncpy(hc->Transducer, transducer, MAX_LENGTH_TRANSDUCER+1);
674 
675 	return (0);
676 }
677 
678 
679 
680 
681 /*
682         DO NOT USE         DO NOT USE         DO NOT USE         DO NOT USE
683 
684         the functions below are experimental and have not been used so far
685         in any productions system
686         They will be removed or significantly changed .
687 
688         DO NOT USE         DO NOT USE         DO NOT USE         DO NOT USE
689 */
690 
691 #define hdrlistlen 64
692 struct hdrlist_t {
693 	HDRTYPE *hdr;		// header information as defined in level 1 interface
694 	//const char *filename; // name of file, is always hdr->FileName
695 	uint16_t NS; 	        // number of effective channels, only CHANNEL[].OnOff==1 are considered
696 	size_t *chanpos; 	// position of file handle for each channel
697 } ;
698 
699 struct hdrlist_t hdrlist[hdrlistlen];
700 
getChannelHeader(HDRTYPE * hdr,uint16_t channel)701 CHANNEL_TYPE *getChannelHeader(HDRTYPE *hdr, uint16_t channel) {
702 	// returns channel header - skip Off-channels
703 	CHANNEL_TYPE *hc = hdr->CHANNEL;
704 	typeof(hdr->NS) chan = 0;
705 	while (1) {
706 		if (hc->OnOff==1) {
707 			if (chan==channel) return hc;
708 			chan++;
709 		}
710 		hc++;
711 	}
712 	return NULL;
713 }
714 
715 
biosig_lib_version(void)716 int biosig_lib_version(void) {
717 	return (BIOSIG_VERSION);
718 }
719 
biosig2_open_file_readonly(const char * path,int read_annotations)720 biosig_handle_t biosig2_open_file_readonly(const char *path, int read_annotations) {
721 /*
722 
723 	on success returns handle.
724 */
725 	HDRTYPE *hdr = sopen(path,"r",NULL);
726 	if (serror2(hdr)) {
727 		destructHDR(hdr);
728 		return(NULL);
729 	}
730 	if (read_annotations)
731 	        sort_eventtable(hdr);
732 	return(hdr);
733 }
734 
biosig_open_file_readonly(const char * path,int read_annotations)735 int biosig_open_file_readonly(const char *path, int read_annotations) {
736 /*
737 
738 	on success returns handle.
739 */
740 	int k = 0;
741 	while (k < hdrlistlen && hdrlist[k].hdr != NULL) k++;
742 	if (k >= hdrlistlen) return(-1);
743 	HDRTYPE *hdr = sopen(path,"r",NULL);
744 	hdrlist[k].hdr = hdr;
745 	//hdrlist[k].filename = hdr->FileName;
746 	hdrlist[k].NS  = 0;
747 	hdrlist[k].chanpos  = calloc(hdrlist[k].NS,sizeof(size_t));
748 
749         if (read_annotations)
750                 sort_eventtable(hdrlist[k].hdr);
751 
752 	return(k);
753 }
754 
biosig2_close_file(biosig_handle_t hdr)755 int biosig2_close_file(biosig_handle_t hdr) {
756 	destructHDR(hdr);
757 	return(0);
758 }
759 
biosig_close_file(int handle)760 int biosig_close_file(int handle) {
761 	destructHDR(hdrlist[handle].hdr);
762 	hdrlist[handle].hdr = NULL;
763 	if (hdrlist[handle].chanpos) free(hdrlist[handle].chanpos);
764 	hdrlist[handle].NS  = 0;
765 	//hdrlist[handle].filename = NULL;
766 
767 #if 0
768 	int k;
769 	for (k=0; k<hdrlistlen; k++)
770 		if (hdrlist[k].hdr!=NULL) return(0);
771 	free(hdrlist);
772 #endif
773 	return(0);
774 }
775 
biosig_read_samples(int handle,size_t channel,size_t n,double * buf,unsigned char UCAL)776 int biosig_read_samples(int handle, size_t channel, size_t n, double *buf, unsigned char UCAL) {
777 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL || hdrlist[handle].NS<=channel ) return(-1);
778 	HDRTYPE *hdr = hdrlist[handle].hdr;
779 
780 	CHANNEL_TYPE *hc = getChannelHeader(hdr,channel);
781 
782 	size_t stride = 1; // stride between consecutive samples of same channel, depends on data orientation hdr->FLAG.ROW_BASED_CHANNELS
783 	size_t div = hdr->SPR/hc->SPR; 	// stride if sample rate of channel is smaller than the overall sampling rate
784 
785 	size_t POS = hdrlist[handle].chanpos[channel]*div;	//
786 	size_t LEN = n*div;
787 	size_t startpos = POS/hdr->SPR;  // round towards 0
788 	size_t endpos = (POS+LEN)/hdr->SPR + ((POS+LEN)%hdr->SPR != 0);  // round towards infinity
789 
790 	if (hdr->AS.first > startpos || (endpos-startpos) > hdr->AS.length || hdr->FLAG.UCAL!=UCAL) {
791 		// read data when not in data buffer hdr->data.block
792 		hdr->FLAG.UCAL = UCAL;
793 		sread(NULL, startpos, endpos - startpos, hdr);
794 	}
795 
796 	// when starting position is not aligned with start of data
797 	size_t offset = hdr->AS.first * hdr->SPR - POS;
798 
799 	// find starting position and stride of data
800 	double *data = hdr->data.block;
801 	if (hdr->FLAG.ROW_BASED_CHANNELS) {
802 		stride = hdr->data.size[0];
803 		data = hdr->data.block + channel + offset * stride;
804 	}
805 	else {
806 		data = hdr->data.block + offset + channel * hdr->data.size[0];
807 	}
808 	size_t k;
809 	for (k = 0; k < n; k++) {
810 		buf[k] = data[k*div*stride];	// copy data into output buffer
811 	}
812 	hdrlist[handle].chanpos[channel] += n; // update position pointer of channel chan
813 	return (0);
814 }
815 
816 /*
817 int biosig_read_physical_samples(int handle, size_t biosig_signal, size_t n, double *buf) {
818 	return biosig_read_samples(handle, biosig_signal, n, buf, (unsigned char)(0));
819 }
820 
821 int biosig_read_digital_samples(int handle, size_t biosig_signal, size_t n, double *buf) {
822 	return biosig_read_samples(handle, biosig_signal, n, buf, (unsigned char)(1));
823 }
824 */
825 
biosig_seek(int handle,long long offset,int whence)826 size_t biosig_seek(int handle, long long offset, int whence) {
827 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
828 	HDRTYPE *hdr = hdrlist[handle].hdr;
829 	sseek(hdr, offset, whence);
830 	return (hdr->FILE.POS);
831 }
832 
biosig_tell(int handle)833 size_t biosig_tell(int handle) {
834 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
835 	return(stell(hdrlist[handle].hdr));
836 }
837 
biosig_rewind(int handle,int biosig_signal)838 void biosig_rewind(int handle, int biosig_signal) {
839 /* It is equivalent to: (void) biosig_seek(int handle, int biosig_signal, 0LL, biosig_SEEK_SET) */
840 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return;
841 	srewind(hdrlist[handle].hdr);
842 }
843 
biosig2_open_file_writeonly(const char * path,enum FileFormat filetype,int number_of_signals)844 biosig_handle_t biosig2_open_file_writeonly(const char *path, enum FileFormat filetype, int number_of_signals) {
845 
846         /* TODO: does not open file and write to file */
847 	HDRTYPE *hdr = constructHDR(number_of_signals,0);
848         hdr->FLAG.UCAL = 0;
849         hdr->FLAG.OVERFLOWDETECTION = 0;
850         hdr->FILE.COMPRESSION = 0;
851 
852 	return(hdr);
853 }
854 
biosig_open_file_writeonly(const char * path,enum FileFormat filetype,int number_of_signals)855 int biosig_open_file_writeonly(const char *path, enum FileFormat filetype, int number_of_signals) {
856 
857         /* TODO: does not open file and write to file */
858 #if 1
859 	int k = 0;
860 	while (k < hdrlistlen && hdrlist[k].hdr != NULL) k++;
861 	if (k>=hdrlistlen) return -1;
862 
863 	HDRTYPE *hdr = constructHDR(number_of_signals,0);
864 #else
865 	HDRTYPE *hdr = constructHDR(number_of_signals,0);
866 	if (hdr==NULL) return (-1);
867 
868 	hdr->FileName = strdup(path);
869 	hdr->TYPE = filetype;
870 	int k = 0;
871 	while (k < hdrlistlen && hdrlist[k].hdr != NULL) k++;
872 	if (k>=hdrlistlen) {
873 		void *ptr = realloc(hdrlist, (k+1)*sizeof(*hdrlist));
874 		if (ptr==NULL) return (-1);
875 		hdrlist = (struct hdrlist_t*) ptr;
876 		hdrlistlen = k+1;
877 	}
878 #endif
879         hdr->FLAG.UCAL = 0;
880         hdr->FLAG.OVERFLOWDETECTION = 0;
881         hdr->FILE.COMPRESSION = 0;
882 
883 	hdrlist[k].hdr  = hdr;
884 	return(0);
885 }
886 
biosig_get_global_samplefrequency(int handle)887 double biosig_get_global_samplefrequency(int handle) {
888 
889 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NAN);
890 	return (hdrlist[handle].hdr->SampleRate);
891 }
892 
biosig_set_global_samplefrequency(int handle,double samplefrequency)893 int biosig_set_global_samplefrequency(int handle, double samplefrequency) {
894 
895 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
896 	hdrlist[handle].hdr->SampleRate = samplefrequency;
897 
898 	return 0;
899 }
900 
biosig_get_samplefrequency(int handle,int biosig_signal)901 double biosig_get_samplefrequency(int handle, int biosig_signal) {
902 
903 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NAN);
904 	HDRTYPE *hdr = hdrlist[handle].hdr;
905 	typeof(hdr->NS) ns = hdr->NS;
906 	if (biosig_signal >= ns) return(NAN);
907 
908 	return (hdr->SampleRate*hdr->CHANNEL[biosig_signal].SPR/hdr->SPR);
909 }
910 
biosig_set_samplefrequency(int handle,int biosig_signal,double samplefrequency)911 int biosig_set_samplefrequency(int handle, int biosig_signal, double samplefrequency) {
912 
913 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
914 	HDRTYPE *hdr = hdrlist[handle].hdr;
915 	typeof(hdr->NS) ns = 0;
916 	int ch;
917         for (ch = 0; ch < hdr->NS; ch++) {
918                 if (hdr->CHANNEL[ch].OnOff==1) {
919                         if (ns==biosig_signal) break;
920                         ns++;
921                 }
922         }
923 	if (ch >= hdr->NS) return(-1);
924 
925 	// FIXME: resulting sampling rate might depend on calling order; what's the overall sampling rate ?
926 	if (samplefrequency != hdr->SampleRate) {
927 		double spr = samplefrequency * hdr->SPR / hdr->SampleRate;
928 		hdr->CHANNEL[biosig_signal].SPR = spr;
929 		if (spr != ceil(spr)) return (-2);
930 		return 0;
931 	}
932 	hdr->CHANNEL[ch].SPR = hdr->SPR;
933 	return 0;
934 }
935 
biosig_get_physical_maximum(int handle,int biosig_signal)936 double biosig_get_physical_maximum(int handle, int biosig_signal) {
937 
938 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NAN);
939 	HDRTYPE *hdr = hdrlist[handle].hdr;
940 	typeof(hdr->NS) ns = hdr->NS;
941 	if (biosig_signal >= ns) return(NAN);
942 
943 	return (hdr->CHANNEL[biosig_signal].PhysMax);
944 }
945 
biosig_set_physical_maximum(int handle,int biosig_signal,double phys_max)946 int biosig_set_physical_maximum(int handle, int biosig_signal, double phys_max) {
947 
948 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
949 	HDRTYPE *hdr = hdrlist[handle].hdr;
950 	typeof(hdr->NS) ns = hdr->NS;
951 	if (biosig_signal >= ns) return(-1);
952 
953 	hdr->CHANNEL[biosig_signal].PhysMax = phys_max;
954 	return (0);
955 }
956 
biosig_get_physical_minimum(int handle,int biosig_signal)957 double biosig_get_physical_minimum(int handle, int biosig_signal) {
958 
959 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NAN);
960 	HDRTYPE *hdr = hdrlist[handle].hdr;
961 	typeof(hdr->NS) ns = hdr->NS;
962 	if (biosig_signal >= ns) return(NAN);
963 
964 	return (hdr->CHANNEL[biosig_signal].PhysMin);
965 }
966 
biosig_set_physical_minimum(int handle,int biosig_signal,double phys_min)967 int biosig_set_physical_minimum(int handle, int biosig_signal, double phys_min) {
968 
969 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
970 	HDRTYPE *hdr = hdrlist[handle].hdr;
971 	typeof(hdr->NS) ns = hdr->NS;
972 	if (biosig_signal >= ns) return(-1);
973 
974 	hdr->CHANNEL[biosig_signal].PhysMin = phys_min;
975 	return (0);
976 }
977 
biosig_get_digital_maximum(int handle,int biosig_signal)978 double biosig_get_digital_maximum(int handle, int biosig_signal) {
979 
980 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NAN);
981 	HDRTYPE *hdr = hdrlist[handle].hdr;
982 	typeof(hdr->NS) ns = hdr->NS;
983 	if (biosig_signal >= ns) return(NAN);
984 
985 	return (hdr->CHANNEL[biosig_signal].DigMax);
986 }
987 
biosig_set_digital_maximum(int handle,int biosig_signal,double dig_max)988 int biosig_set_digital_maximum(int handle, int biosig_signal, double dig_max) {
989 
990 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
991 	HDRTYPE *hdr = hdrlist[handle].hdr;
992 	typeof(hdr->NS) ns = hdr->NS;
993 	if (biosig_signal >= ns) return(-1);
994 
995 	hdr->CHANNEL[biosig_signal].DigMax = dig_max;
996 	return (0);
997 }
998 
biosig_get_digital_minimum(int handle,int biosig_signal)999 double biosig_get_digital_minimum(int handle, int biosig_signal) {
1000 
1001 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NAN);
1002 	HDRTYPE *hdr = hdrlist[handle].hdr;
1003 	typeof(hdr->NS) ns = hdr->NS;
1004 	if (biosig_signal >= ns) return(NAN);
1005 
1006 	return (hdr->CHANNEL[biosig_signal].DigMin);
1007 }
1008 
biosig_set_digital_minimum(int handle,int biosig_signal,double dig_min)1009 int biosig_set_digital_minimum(int handle, int biosig_signal, double dig_min) {
1010 
1011 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1012 	HDRTYPE *hdr = hdrlist[handle].hdr;
1013 	typeof(hdr->NS) ns = hdr->NS;
1014 	if (biosig_signal >= ns) return(-1);
1015 
1016 	hdr->CHANNEL[biosig_signal].DigMin = dig_min;
1017 	return (0);
1018 }
1019 
biosig_get_label(int handle,int biosig_signal)1020 const char *biosig_get_label(int handle, int biosig_signal) {
1021 
1022 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NULL);
1023 	HDRTYPE *hdr = hdrlist[handle].hdr;
1024 	typeof(hdr->NS) ns = hdr->NS;
1025 	if (biosig_signal >= ns) return(NULL);
1026 
1027 	return (hdr->CHANNEL[biosig_signal].Label);
1028 }
1029 
biosig_set_label(int handle,int biosig_signal,const char * label)1030 int biosig_set_label(int handle, int biosig_signal, const char *label) {
1031 
1032 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1033 	HDRTYPE *hdr = hdrlist[handle].hdr;
1034 	typeof(hdr->NS) ns = hdr->NS;
1035 	if (biosig_signal >= ns) return(-1);
1036 
1037 	strncpy(hdr->CHANNEL[biosig_signal].Label, label, MAX_LENGTH_LABEL);
1038 	return (0);
1039 }
1040 
1041 
biosig_set_prefilter(int handle,int biosig_signal,const char * prefilter)1042 int biosig_set_prefilter(int handle, int biosig_signal, const char *prefilter) {
1043         // TODO: parse prefilter and call biosig_set_{highpass,lowpass,notch}filter
1044         return fprintf(stderr,"Warning: biosig_set_prefilter(...) is not implemented, use instead biosig_set_highpassfilter(),biosig_set_lowpassfilter(),biosig_set_notchfilter().\n");
1045 }
1046 
biosig_set_highpassfilter(int handle,int biosig_signal,double frequency)1047 int biosig_set_highpassfilter(int handle, int biosig_signal, double frequency) {
1048 
1049 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1050 	HDRTYPE *hdr = hdrlist[handle].hdr;
1051 	typeof(hdr->NS) ns = hdr->NS;
1052 	if (biosig_signal >= ns) return(-1);
1053 
1054 	hdr->CHANNEL[biosig_signal].HighPass = frequency;
1055 
1056 	return 0;
1057 }
1058 
biosig_set_lowpassfilter(int handle,int biosig_signal,double frequency)1059 int biosig_set_lowpassfilter(int handle, int biosig_signal, double frequency) {
1060 
1061 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1062 	HDRTYPE *hdr = hdrlist[handle].hdr;
1063 	typeof(hdr->NS) ns = hdr->NS;
1064 	if (biosig_signal >= ns) return(-1);
1065 
1066 	hdr->CHANNEL[biosig_signal].LowPass = frequency;
1067 
1068 	return 0;
1069 }
1070 
biosig_set_notchfilter(int handle,int biosig_signal,double frequency)1071 int biosig_set_notchfilter(int handle, int biosig_signal, double frequency) {
1072 
1073 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1074 	HDRTYPE *hdr = hdrlist[handle].hdr;
1075 	typeof(hdr->NS) ns = hdr->NS;
1076 	if (biosig_signal >= ns) return(-1);
1077 
1078 	hdr->CHANNEL[biosig_signal].Notch = frequency;
1079 
1080 	return (0);
1081 }
1082 
1083 
biosig_get_transducer(int handle,int biosig_signal)1084 const char *biosig_get_transducer(int handle, int biosig_signal) {
1085 
1086 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NULL);
1087 	HDRTYPE *hdr = hdrlist[handle].hdr;
1088 	typeof(hdr->NS) ns = hdr->NS;
1089 	if (biosig_signal >= ns) return(NULL);
1090 
1091 	return (hdr->CHANNEL[biosig_signal].Transducer);
1092 }
1093 
biosig_set_transducer(int handle,int biosig_signal,const char * transducer)1094 int biosig_set_transducer(int handle, int biosig_signal, const char *transducer) {
1095 
1096 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1097 	HDRTYPE *hdr = hdrlist[handle].hdr;
1098 	typeof(hdr->NS) ns = hdr->NS;
1099 	if (biosig_signal >= ns) return(-1);
1100 
1101 	strncpy(hdr->CHANNEL[biosig_signal].Transducer, transducer, MAX_LENGTH_TRANSDUCER+1);
1102 
1103 	return (0);
1104 }
1105 
1106 
biosig_physical_dimension(int handle,int biosig_signal)1107 const char *biosig_physical_dimension(int handle, int biosig_signal) {
1108 
1109 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NULL);
1110 	HDRTYPE *hdr = hdrlist[handle].hdr;
1111 	typeof(hdr->NS) ns = hdr->NS;
1112 	if (biosig_signal >= ns) return(NULL);
1113 
1114 	return (PhysDim3(hdr->CHANNEL[biosig_signal].PhysDimCode));
1115 }
1116 
biosig_set_physical_dimension(int handle,int biosig_signal,const char * phys_dim)1117 int biosig_set_physical_dimension(int handle, int biosig_signal, const char *phys_dim) {
1118 
1119 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1120 	HDRTYPE *hdr = hdrlist[handle].hdr;
1121 	typeof(hdr->NS) ns = hdr->NS;
1122 	if (biosig_signal >= ns) return(-1);
1123 
1124 	hdr->CHANNEL[biosig_signal].PhysDimCode = PhysDimCode(phys_dim);
1125 
1126 	return (0);
1127 }
1128 
edf_set_startdatetime(int handle,int startdate_year,int startdate_month,int startdate_day,int starttime_hour,int starttime_minute,int starttime_second)1129 int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day, int starttime_hour, int starttime_minute, int starttime_second) {
1130 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1131 	HDRTYPE *hdr = hdrlist[handle].hdr;
1132 	struct tm T;
1133 	T.tm_year = startdate_year;
1134 	T.tm_mon  = startdate_month;
1135 	T.tm_mday = startdate_day;
1136 	T.tm_hour = starttime_hour;
1137 	T.tm_min  = starttime_minute;
1138 	T.tm_sec  = starttime_second;
1139 	hdr->T0   = tm_time2gdf_time(&T);
1140 	return (0);
1141 }
1142 
biosig_get_patientname(int handle)1143 const char *biosig_get_patientname(int handle)  {
1144 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NULL);
1145 	return(hdrlist[handle].hdr->Patient.Name);
1146 }
biosig_set_patientname(int handle,const char * patientname)1147 int biosig_set_patientname(int handle, const char *patientname) {
1148 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1149 	strncpy(hdrlist[handle].hdr->Patient.Name, patientname, MAX_LENGTH_NAME+1);
1150 	return (0);
1151 }
1152 
biosig_get_patientcode(int handle)1153 const char *biosig_get_patientcode(int handle)  {
1154 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NULL);
1155 	return(hdrlist[handle].hdr->Patient.Id);
1156 }
biosig_set_patientcode(int handle,const char * patientcode)1157 int biosig_set_patientcode(int handle, const char *patientcode) {
1158 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1159 	strncpy(hdrlist[handle].hdr->Patient.Id, patientcode, MAX_LENGTH_PID+1);
1160 	return(0);
1161 }
1162 
biosig_get_gender(int handle)1163 int biosig_get_gender(int handle) {
1164 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(0);
1165 	return(hdrlist[handle].hdr->Patient.Sex);
1166 }
1167 
biosig_set_gender(int handle,int gender)1168 int biosig_set_gender(int handle, int gender) {
1169 	if (gender<0 || gender>9) return (-1);
1170 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1171 	switch (gender) {
1172 	case  1 :
1173 	case 'm':
1174 	case 'M':
1175 		hdrlist[handle].hdr->Patient.Sex = 1;
1176 		return(0);
1177 	case  2 :
1178 	case 'f':
1179 	case 'F':
1180 		hdrlist[handle].hdr->Patient.Sex = 2;
1181 		return(0);
1182 	default:
1183 		return(0);
1184 	}
1185 }
1186 
edf_set_birthdate(int handle,int birthdate_year,int birthdate_month,int birthdate_day)1187 int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day) {
1188 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1189 	HDRTYPE *hdr = hdrlist[handle].hdr;
1190 	struct tm T;
1191 	T.tm_year = birthdate_year;
1192 	T.tm_mon  = birthdate_month;
1193 	T.tm_mday = birthdate_day;
1194 	T.tm_hour = 12;
1195 	T.tm_min  = 0;
1196 	T.tm_sec  = 0;
1197 	hdr->Patient.Birthday = tm_time2gdf_time(&T);
1198 	return (0);
1199 }
1200 
biosig_set_patient_additional(int handle,const char * patient_additional)1201 int biosig_set_patient_additional(int handle, const char *patient_additional) {
1202 	fprintf(stderr,"Warning: biosig_set_patient_additional() not supported.\n");
1203 	return (-1);
1204 }
1205 
biosig_set_admincode(int handle,const char * admincode)1206 int biosig_set_admincode(int handle, const char *admincode) {
1207 	fprintf(stderr,"Warning: biosig_set_admincode() not supported.\n");
1208 	return (-1);
1209 }
1210 
1211 /*
1212 const char *biosig_get_technician(int handle)  {
1213 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(NULL);
1214 	HDRTYPE *hdr = hdrlist[handle].hdr;
1215 	return(hdr->ID.Technician);
1216 }
1217 int biosig_set_technician(int handle, const char *technician) {
1218 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1219 	HDRTYPE *hdr = hdrlist[handle].hdr;
1220 	hdr->ID.Technician = realloc(hdr->ID.Technician, strlen(technician)+1);
1221 	strcpy(hdr->ID.Technician, technician);
1222 	return(0);
1223 }
1224 */
1225 
1226 // TODO: implement the following functions
biosig_set_equipment(int handle,const char * equipment)1227 int biosig_set_equipment(int handle, const char *equipment) {
1228 	return (-1);
1229 }
biosig_set_recording_additional(int handle,const char * recording_additional)1230 int biosig_set_recording_additional(int handle, const char *recording_additional) {
1231 	return (-1);
1232 }
biosig_write_physical_samples(int handle,double * buf)1233 int biosig_write_physical_samples(int handle, double *buf) {
1234 	return (-1);
1235 }
biosig_blockwrite_physical_samples(int handle,double * buf)1236 int biosig_blockwrite_physical_samples(int handle, double *buf) {
1237 	return (-1);
1238 }
biosig_write_digital_samples(int handle,int * buf)1239 int biosig_write_digital_samples(int handle, int *buf) {
1240 	return (-1);
1241 }
biosig_blockwrite_digital_samples(int handle,int * buf)1242 int biosig_blockwrite_digital_samples(int handle, int *buf) {
1243 	return (-1);
1244 }
1245 
biosig_write_annotation(int handle,size_t onset,size_t duration,const char * description)1246 int biosig_write_annotation(int handle, size_t onset, size_t duration, const char *description) {
1247 	/* onset and duration are in samples */
1248 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1249 	HDRTYPE *hdr = hdrlist[handle].hdr;
1250 
1251 	size_t N = hdr->EVENT.N++;
1252 	hdr->EVENT.POS = (uint32_t*) realloc(hdr->EVENT.POS, hdr->EVENT.N*sizeof(*(hdr->EVENT.POS)) );
1253 	hdr->EVENT.TYP = (uint16_t*) realloc(hdr->EVENT.TYP, hdr->EVENT.N*sizeof(*(hdr->EVENT.TYP)) );
1254 	hdr->EVENT.DUR = (uint32_t*) realloc(hdr->EVENT.DUR, hdr->EVENT.N*sizeof(*(hdr->EVENT.DUR)) );
1255 	hdr->EVENT.CHN = (uint16_t*) realloc(hdr->EVENT.CHN, hdr->EVENT.N*sizeof(*(hdr->EVENT.CHN)) );
1256 
1257 	hdr->EVENT.POS[N] = onset;
1258 	hdr->EVENT.DUR[N] = duration;
1259 	hdr->EVENT.CHN[N] = 0;
1260 	FreeTextEvent(hdr, N, description);
1261 	return (hdr->AS.B4C_ERRNUM);
1262 }
1263 
biosig_write_annotation_utf8(int handle,size_t onset,size_t duration,const char * description)1264 int biosig_write_annotation_utf8(int handle, size_t onset, size_t duration, const char *description) {
1265 	fprintf(stdout,"biosig_write_annotation_latin1(): It's recommended to use biosig_write_annotation() instead.\n");
1266 	return ( biosig_write_annotation(handle, onset, duration, description) );
1267 }
biosig_write_annotation_latin1(int handle,size_t onset,size_t duration,const char * description)1268 int biosig_write_annotation_latin1(int handle, size_t onset, size_t duration, const char *description) {
1269 	fprintf(stdout,"biosig_write_annotation_latin1(): It's recommended to use biosig_write_annotation() instead.\n");
1270 	return ( biosig_write_annotation(handle, onset, duration, description) );
1271 }
1272 
biosig_set_datarecord_duration(int handle,double duration)1273 int biosig_set_datarecord_duration(int handle, double duration) {
1274 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1275 	HDRTYPE *hdr = hdrlist[handle].hdr;
1276 	double spr   = hdr->SampleRate * duration;
1277 	size_t rspr  = round(spr);
1278 	if (fabs(spr - rspr) > 1e-8*spr) {
1279 		fprintf(stderr,"Warning biosig_set_datarecord_duration(): number of samples is not integer (%g) - rounded to integers (%i)\n",spr,(int)rspr);
1280 	}
1281 	hdr->SPR = (size_t)rspr;
1282 	return 0;
1283 }
1284 
1285 /******************************************************************************************
1286 	biosig_unserialize_header: converts memory buffer into header structure HDR
1287 
1288 	biosig_unserialize: converts memory buffer into header structure HDR, and
1289 	if data != NULL, data samples will be read into a matrix,
1290 		the starting address of this data matrix will be stored in *data
1291 		point to *data
1292 	input:
1293 		mem : buffer
1294 		len : length of buffer mem
1295 		start: starting position to extract data
1296 		length: number of samples for extracting data,
1297 		flags: BIOSIG_FLAG_UCAL | BIOSIG_FLAG_OVERFLOWDETECTION | BIOSIG_FLAG_ROW_BASED_CHANNELS
1298 	output:
1299 		*data will contain start address to matrix data samples, of size
1300 		hdr->NS * (hdr->SPR * hdr->NRec) or its transpose form depending on flags
1301 	return value:
1302 		header structure HDRTYPE* hdr.
1303  ******************************************************************************************/
biosig_unserialize(void * mem,size_t len,size_t start,size_t length,biosig_data_type ** data,int flags)1304 HDRTYPE* biosig_unserialize(void *mem, size_t len, size_t start, size_t length, biosig_data_type **data, int flags) {
1305 
1306 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1307 
1308 	HDRTYPE *hdr = constructHDR(0,0);
1309 
1310 	// decode header
1311 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1312 
1313 	hdr->AS.Header = mem;
1314 	// in case of error, memory is deallocated through destructHDR(hdr);
1315 	if (gdfbin2struct(hdr)) return(hdr);
1316 	// in case of success, memory is managed by its own pointer *mem
1317 	hdr->AS.Header = NULL;
1318 
1319 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1320 
1321 	// get data block
1322 	biosig_set_flag(hdr, flags);
1323 	if (data != NULL) {
1324 		hdr->AS.rawdata = mem+hdr->HeadLen;
1325 		size_t L = sread(*data, start, length, hdr);
1326 		*data    = hdr->data.block;
1327 		hdr->data.block = NULL;
1328 	}
1329 	hdr->AS.rawdata = NULL;
1330 
1331 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1332 
1333 	// read eventtable
1334 	hdr->AS.rawEventData = (hdr->NRec != -1) ? mem + hdr->HeadLen + hdr->NRec*hdr->AS.bpb : NULL;
1335 	rawEVT2hdrEVT(hdr, len - hdr->HeadLen - hdr->NRec*hdr->AS.bpb);
1336 
1337 	// in case of success, memory is managed by its own pointer *mem
1338 	hdr->AS.rawEventData = NULL;
1339 
1340 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1341 
1342 	return(hdr);
1343 }
1344 
1345 /******************************************************************************************
1346 	biosig_serialize: converts header structure into memory buffer
1347 	input:
1348 		hdr: header structure, including event table.
1349 
1350 	output:
1351 		*mem will contain start address of buffer
1352 		*len will contain length of buffer mem.
1353  ******************************************************************************************/
1354 
biosig_serialize(HDRTYPE * hdr,void ** mem,size_t * len)1355 void* biosig_serialize(HDRTYPE *hdr, void **mem, size_t *len) {
1356 	// encode header
1357 
1358 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1359 
1360 	hdr->TYPE=GDF;
1361 	hdr->VERSION=3.0;
1362 
1363 	struct2gdfbin(hdr);
1364 
1365 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1366 
1367 	// write event table
1368 	size_t len3 = hdrEVT2rawEVT(hdr);
1369 
1370 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1371 
1372 	size_t len0 = hdr->HeadLen + hdr->NRec*hdr->AS.bpb + len3;
1373 	char* M = (char*)realloc(*mem,len0);
1374 	if (M == NULL) return(NULL);
1375 
1376 	*mem = M;
1377 	*len = len0;
1378 	// write header into buffer
1379 	memcpy(M, hdr->AS.Header, hdr->HeadLen);
1380 
1381 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1382 
1383 	// write data into buffer, and collapse unused channels
1384 	size_t count = sread_raw(0, hdr->NRec, hdr, 1, M + hdr->HeadLen, hdr->NRec*hdr->AS.bpb);
1385 
1386 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1387 
1388 	// write event table into buffer
1389 	memcpy(M + hdr->HeadLen + hdr->NRec*hdr->AS.bpb, hdr->AS.rawEventData, len3);
1390 
1391 	fprintf(stdout,"%s (line %i) %s:\n",__FILE__,__LINE__,__func__);
1392 
1393 	return(M);
1394 }
1395 
1396 
1397 
1398 
1399 #if defined(MAKE_EDFLIB)
1400 
edfopen_file_writeonly(const char * path,int filetype,int number_of_signals)1401 int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals) {
1402 	enum FileFormat fmt=unknown;
1403  	switch (filetype) {
1404 	case EDFLIB_FILETYPE_EDF:
1405 	case EDFLIB_FILETYPE_EDFPLUS:
1406 		fmt = EDF;
1407 		break;
1408 	case EDFLIB_FILETYPE_BDF:
1409 	case EDFLIB_FILETYPE_BDFPLUS:
1410 		fmt = EDF;
1411 		break;
1412 	default:
1413 		return(-1);
1414 	}
1415 	return(biosig_open_file_writeonly(path, fmt, number_of_signals));
1416 }
1417 
edf_set_gender(int handle,int gender)1418 int edf_set_gender(int handle, int gender) {
1419 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1420 	HDRTYPE *hdr = hdrlist[handle].hdr;
1421 	hdr->Patient.Sex = (gender==1) + (gender==0)*2 ;
1422 }
1423 
edfread_physical_samples(int handle,int edfsignal,int n,double * buf)1424 int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) {
1425 	fprintf(stderr,"error: edfread_physical_samples - use biosig_read_physical_samples instead.\n");
1426 	return(-1);
1427 }
1428 
edfread_digital_samples(int handle,int edfsignal,int n,int * buf)1429 int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) {
1430 	fprintf(stderr,"error: edfread_digital_samples - use biosig_read_digital_samples instead.\n");
1431 	return(-1);
1432 }
1433 
edfseek(int handle,int channel,long long offset,int whence)1434 long long edfseek(int handle, int channel, long long offset, int whence) {
1435 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL || hdrlist[handle].NS<=channel ) return(-1);
1436 	HDRTYPE *hdr = hdrlist[handle].hdr;
1437 
1438 	switch (whence) {
1439 	case SEEK_SET:
1440 		hdrlist[handle].chanpos[channel] = offset; // update position pointer of channel chan
1441 		break;
1442 	case SEEK_CUR:
1443 		hdrlist[handle].chanpos[channel] += offset; // update position pointer of channel chan
1444 		break;
1445 	case SEEK_END: {
1446 		CHANNEL_TYPE *hc = getChannelHeader(hdr,channel);
1447 		hdrlist[handle].chanpos[channel] = hdr->NRec*hc->SPR + offset; // update position pointer of channel chan
1448 		break;
1449 		}
1450 	}
1451 	return (hdrlist[handle].chanpos[channel]);
1452 }
1453 
edftell(int handle,int channel)1454 long long edftell(int handle, int channel) {
1455 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL || hdrlist[handle].NS<=channel ) return(-1);
1456 	return ( hdrlist[handle].chanpos[channel] );
1457 }
1458 
edfrewind(int handle,int channel)1459 int edfrewind(int handle, int channel) {
1460 /* It is equivalent to: (void) edf_seek(int handle, int biosig_signal, 0LL, SEEK_SET) */
1461 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL || hdrlist[handle].NS<=channel ) return(-1);
1462 	hdrlist[handle].chanpos[channel] = 0;
1463 	return(0);
1464 }
1465 
edf_get_annotation(int handle,int n,struct edf_annotation_struct * annot)1466 int edf_get_annotation(int handle, int n, struct edf_annotation_struct *annot) {
1467 	if (handle<0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1468 	HDRTYPE *hdr = hdrlist[handle].hdr;
1469 
1470 	annot->onset = hdr->EVENT.POS[n]*1e4/hdr->EVENT.SampleRate;
1471 	annot->duration = hdr->EVENT.DUR[n]*1e4/hdr->EVENT.SampleRate;
1472 	strncpy(annot->annotation,GetEventDescription(hdr, n),sizeof(annot->annotation));
1473 
1474 	return(0);
1475 }
1476 
edfwrite_annotation(int handle,size_t onset,size_t duration,const char * description)1477 int edfwrite_annotation(int handle, size_t onset, size_t duration, const char *description) {
1478 	/* onset and duration are multiples of 100 microseconds */
1479 	if (handle < 0 || handle >= hdrlistlen || hdrlist[handle].hdr==NULL) return(-1);
1480 	HDRTYPE *hdr = hdrlist[handle].hdr;
1481 	return (biosig_write_annotation(handle, onset*1e-4*hdr->EVENT.SampleRate, duration*1e-4*hdr->EVENT.SampleRate, description));
1482 }
1483 
1484 /*
1485    TODO: the following functions neeed to be implemented
1486 */
edf_set_recording_additional(int handle,const char * recording_additional)1487 int edf_set_recording_additional(int handle, const char *recording_additional) {
1488 	return fprintf(stderr,"this function is not implemented, yet.\n");
1489 }
1490 
edfwrite_physical_samples(int handle,double * buf)1491 int edfwrite_physical_samples(int handle, double *buf) {
1492 	return fprintf(stderr,"this function is not implemented, yet.\n");
1493 }
1494 
edf_blockwrite_physical_samples(int handle,double * buf)1495 int edf_blockwrite_physical_samples(int handle, double *buf) {
1496 	return fprintf(stderr,"this function is not implemented, yet.\n");
1497 }
1498 
1499 /*
1500 int edfwrite_digital_samples(int handle, int *buf) {
1501 	return fprintf(stderr,"this function is not implemented, yet.\n");
1502 }
1503 */
1504 
edf_blockwrite_digital_samples(int handle,int * buf)1505 int edf_blockwrite_digital_samples(int handle, int *buf) {
1506 	return fprintf(stderr,"this function is not implemented, yet.\n");
1507 }
1508 
1509 
1510 #endif
1511 
1512 
1513