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