1 /*
2 *****************************************************************************
3 *
4 * Copyright (c) 2009 - 2021 Teunis van Beelen
5 * All rights reserved.
6 *
7 * Email: teuniz@protonmail.com
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 *****************************************************************************
32 */
33
34 /* compile with options "-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE" */
35
36 #include "edflib.h"
37
38 #define EDFLIB_VERSION (120)
39 #define EDFLIB_MAXFILES (64)
40
41 #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__HAIKU__) || defined(__FreeBSD__)
42
43 #define fopeno fopen
44
45 #else
46
47 #define fseeko fseeko64
48 #define ftello ftello64
49 #define fopeno fopen64
50
51 #endif
52
53 #ifdef _WIN32
54
55 #ifndef __MINGW32__
56 /* needed for visual c */
57 #undef fseeko
58 #define fseeko _fseeki64
59
60 #undef ftello
61 #define ftello _ftelli64
62
63 #undef fopeno
64 #define fopeno fopen
65
66 #endif
67
68 #endif
69
70 /* max size of annotationtext */
71 #define EDFLIB_WRITE_MAX_ANNOTATION_LEN (40)
72
73 /* bytes in datarecord for EDF annotations, must be an integer multiple of three and two */
74 #define EDFLIB_ANNOTATION_BYTES (114)
75
76 /* for writing only */
77 #define EDFLIB_MAX_ANNOTATION_CHANNELS (64)
78
79 #define EDFLIB_ANNOT_MEMBLOCKSZ (1000)
80
81 struct edfparamblock{
82 char label[17];
83 char transducer[81];
84 char physdimension[9];
85 double phys_min;
86 double phys_max;
87 int dig_min;
88 int dig_max;
89 char prefilter[81];
90 int smp_per_record;
91 char reserved[33];
92 double offset;
93 int buf_offset;
94 double bitvalue;
95 int annotation;
96 long long sample_pntr;
97 };
98
99 struct edfhdrblock{
100 FILE *file_hdl;
101 char path[1024];
102 int writemode;
103 char version[32];
104 char patient[81];
105 char recording[81];
106 char plus_patientcode[81];
107 char plus_gender[16];
108 char plus_birthdate[16];
109 char plus_patient_name[81];
110 char plus_patient_additional[81];
111 char plus_startdate[16];
112 char plus_admincode[81];
113 char plus_technician[81];
114 char plus_equipment[81];
115 char plus_recording_additional[81];
116 long long l_starttime;
117 int startdate_day;
118 int startdate_month;
119 int startdate_year;
120 int starttime_second;
121 int starttime_minute;
122 int starttime_hour;
123 char reserved[45];
124 int hdrsize;
125 int edfsignals;
126 long long datarecords;
127 int recordsize;
128 int annot_ch[EDFLIB_MAXSIGNALS];
129 int nr_annot_chns;
130 int mapped_signals[EDFLIB_MAXSIGNALS];
131 int edf;
132 int edfplus;
133 int bdf;
134 int bdfplus;
135 int discontinuous;
136 int signal_write_sequence_pos;
137 long long starttime_offset;
138 double data_record_duration;
139 long long long_data_record_duration;
140 int annots_in_file;
141 int annotlist_sz;
142 int total_annot_bytes;
143 int eq_sf;
144 char *wrbuf;
145 int wrbufsize;
146 struct edfparamblock *edfparam;
147 };
148
149 static struct edf_annotationblock{
150 long long onset;
151 char duration[16];
152 char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1];
153 } *annotationslist[EDFLIB_MAXFILES];
154
155 static struct edf_write_annotationblock{
156 long long onset;
157 long long duration;
158 char annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1];
159 } *write_annotationslist[EDFLIB_MAXFILES];
160
161 static int edf_files_open=0;
162
163 static struct edfhdrblock *hdrlist[EDFLIB_MAXFILES];
164
165 static struct edfhdrblock * edflib_check_edf_file(FILE *, int *);
166 static int edflib_is_integer_number(char *);
167 static int edflib_is_number(char *);
168 static long long edflib_get_long_duration(char *);
169 static int edflib_get_annotations(struct edfhdrblock *, int, int);
170 static int edflib_is_duration_number(char *);
171 static int edflib_is_onset_number(char *);
172 static long long edflib_get_long_time(char *);
173 static int edflib_write_edf_header(struct edfhdrblock *);
174 static void edflib_latin1_to_ascii(char *, int);
175 static void edflib_latin12utf8(char *, int);
176 static void edflib_remove_padding_trailing_spaces(char *);
177 static int edflib_atoi_nonlocalized(const char *);
178 static double edflib_atof_nonlocalized(const char *);
179 static int edflib_snprint_number_nonlocalized(char *, double, int);
180 /*
181 static int edflib_sprint_int_number_nonlocalized(char *, int, int, int);
182 */
183 static int edflib_snprint_ll_number_nonlocalized(char *, long long, int, int, int);
184 static int edflib_fprint_int_number_nonlocalized(FILE *, int, int, int);
185 static int edflib_fprint_ll_number_nonlocalized(FILE *, long long, int, int);
186 static int edflib_write_tal(struct edfhdrblock *, FILE *);
187 static int edflib_strlcpy(char *, const char *, int);
188 static int edflib_strlcat(char *, const char *, int);
189
190
edflib_is_file_used(const char * path)191 int edflib_is_file_used(const char *path)
192 {
193 int i;
194
195 for(i=0; i<EDFLIB_MAXFILES; i++)
196 {
197 if(hdrlist[i]!=NULL)
198 {
199 if(!(strcmp(path, hdrlist[i]->path)))
200 {
201 return 1;
202 }
203 }
204 }
205
206 return 0;
207 }
208
209
edflib_get_number_of_open_files()210 int edflib_get_number_of_open_files()
211 {
212 return edf_files_open;
213 }
214
215
edflib_get_handle(int file_number)216 int edflib_get_handle(int file_number)
217 {
218 int i, file_count=0;
219
220 for(i=0; i<EDFLIB_MAXFILES; i++)
221 {
222 if(hdrlist[i]!=NULL)
223 {
224 if(file_count++ == file_number)
225 {
226 return i;
227 }
228 }
229 }
230
231 return -1;
232 }
233
234
edfopen_file_readonly(const char * path,struct edf_hdr_struct * edfhdr,int read_annotations_mode)235 int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int read_annotations_mode)
236 {
237 int i, j,
238 channel,
239 edf_error;
240
241 FILE *file;
242
243 struct edfhdrblock *hdr;
244
245
246 if(read_annotations_mode<0)
247 {
248 edfhdr->filetype = EDFLIB_INVALID_READ_ANNOTS_VALUE;
249
250 return -1;
251 }
252
253 if(read_annotations_mode>2)
254 {
255 edfhdr->filetype = EDFLIB_INVALID_READ_ANNOTS_VALUE;
256
257 return -1;
258 }
259
260 memset(edfhdr, 0, sizeof(struct edf_hdr_struct));
261
262 if(edf_files_open>=EDFLIB_MAXFILES)
263 {
264 edfhdr->filetype = EDFLIB_MAXFILES_REACHED;
265
266 return -1;
267 }
268
269 for(i=0; i<EDFLIB_MAXFILES; i++)
270 {
271 if(hdrlist[i]!=NULL)
272 {
273 if(!(strcmp(path, hdrlist[i]->path)))
274 {
275 edfhdr->filetype = EDFLIB_FILE_ALREADY_OPENED;
276
277 return -1;
278 }
279 }
280 }
281
282 file = fopeno(path, "rb");
283 if(file==NULL)
284 {
285 edfhdr->filetype = EDFLIB_NO_SUCH_FILE_OR_DIRECTORY;
286
287 return -1;
288 }
289
290 hdr = edflib_check_edf_file(file, &edf_error);
291 if(hdr==NULL)
292 {
293 edfhdr->filetype = edf_error;
294
295 fclose(file);
296
297 return -1;
298 }
299
300 if(hdr->discontinuous)
301 {
302 edfhdr->filetype = EDFLIB_FILE_IS_DISCONTINUOUS;
303
304 free(hdr->edfparam);
305 free(hdr);
306
307 fclose(file);
308
309 return -1;
310 }
311
312 hdr->writemode = 0;
313
314 for(i=0; i<EDFLIB_MAXFILES; i++)
315 {
316 if(hdrlist[i]==NULL)
317 {
318 hdrlist[i] = hdr;
319
320 edfhdr->handle = i;
321
322 break;
323 }
324 }
325
326 if((hdr->edf)&&(!(hdr->edfplus)))
327 {
328 edfhdr->filetype = EDFLIB_FILETYPE_EDF;
329 }
330
331 if(hdr->edfplus)
332 {
333 edfhdr->filetype = EDFLIB_FILETYPE_EDFPLUS;
334 }
335
336 if((hdr->bdf)&&(!(hdr->bdfplus)))
337 {
338 edfhdr->filetype = EDFLIB_FILETYPE_BDF;
339 }
340
341 if(hdr->bdfplus)
342 {
343 edfhdr->filetype = EDFLIB_FILETYPE_BDFPLUS;
344 }
345
346 edfhdr->edfsignals = hdr->edfsignals - hdr->nr_annot_chns;
347 edfhdr->file_duration = hdr->long_data_record_duration * hdr->datarecords;
348 edfhdr->startdate_day = hdr->startdate_day;
349 edfhdr->startdate_month = hdr->startdate_month;
350 edfhdr->startdate_year = hdr->startdate_year;
351 edfhdr->starttime_hour = hdr->starttime_hour;
352 edfhdr->starttime_second = hdr->starttime_second;
353 edfhdr->starttime_minute = hdr->starttime_minute;
354 edfhdr->starttime_subsecond = hdr->starttime_offset;
355 edfhdr->datarecords_in_file = hdr->datarecords;
356 edfhdr->datarecord_duration = hdr->long_data_record_duration;
357
358 annotationslist[edfhdr->handle] = NULL;
359
360 hdr->annotlist_sz = 0;
361
362 hdr->annots_in_file = 0;
363
364 edfhdr->annotations_in_file = 0LL;
365
366 if((!(hdr->edfplus))&&(!(hdr->bdfplus)))
367 {
368 edflib_strlcpy(edfhdr->patient, hdr->patient, 81);
369 edflib_strlcpy(edfhdr->recording, hdr->recording, 81);
370 edfhdr->patientcode[0] = 0;
371 edfhdr->gender[0] = 0;
372 edfhdr->birthdate[0] = 0;
373 edfhdr->patient_name[0] = 0;
374 edfhdr->patient_additional[0] = 0;
375 edfhdr->admincode[0] = 0;
376 edfhdr->technician[0] = 0;
377 edfhdr->equipment[0] = 0;
378 edfhdr->recording_additional[0] = 0;
379 }
380 else
381 {
382 edfhdr->patient[0] = 0;
383 edfhdr->recording[0] = 0;
384 edflib_strlcpy(edfhdr->patientcode, hdr->plus_patientcode, 81);
385 edflib_strlcpy(edfhdr->gender, hdr->plus_gender, 16);
386 edflib_strlcpy(edfhdr->birthdate, hdr->plus_birthdate, 16);
387 edflib_strlcpy(edfhdr->patient_name, hdr->plus_patient_name, 81);
388 edflib_strlcpy(edfhdr->patient_additional, hdr->plus_patient_additional, 81);
389 edflib_strlcpy(edfhdr->admincode, hdr->plus_admincode, 81);
390 edflib_strlcpy(edfhdr->technician, hdr->plus_technician, 81);
391 edflib_strlcpy(edfhdr->equipment, hdr->plus_equipment, 81);
392 edflib_strlcpy(edfhdr->recording_additional, hdr->plus_recording_additional, 81);
393
394 if(edflib_get_annotations(hdr, edfhdr->handle, read_annotations_mode))
395 {
396 edfhdr->filetype = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
397
398 fclose(file);
399
400 free(hdr->edfparam);
401 hdr->edfparam = NULL;
402 free(hdr);
403 hdr = NULL;
404 hdrlist[edfhdr->handle] = NULL;
405 free(annotationslist[edfhdr->handle]);
406 annotationslist[edfhdr->handle] = NULL;
407
408 return -1;
409 }
410
411 edfhdr->starttime_subsecond = hdr->starttime_offset;
412
413 edfhdr->annotations_in_file = hdr->annots_in_file;
414 }
415
416 edflib_strlcpy(hdr->path, path, 1024);
417
418 edf_files_open++;
419
420 j = 0;
421
422 for(i=0; i<hdr->edfsignals; i++)
423 {
424 if(!(hdr->edfparam[i].annotation))
425 {
426 hdr->mapped_signals[j++] = i;
427 }
428 }
429
430 for(i=0; i<edfhdr->edfsignals; i++)
431 {
432 channel = hdr->mapped_signals[i];
433
434 edflib_strlcpy(edfhdr->signalparam[i].label, hdr->edfparam[channel].label, 17);
435 edflib_strlcpy(edfhdr->signalparam[i].transducer, hdr->edfparam[channel].transducer, 81);
436 edflib_strlcpy(edfhdr->signalparam[i].physdimension, hdr->edfparam[channel].physdimension, 9);
437 edflib_strlcpy(edfhdr->signalparam[i].prefilter, hdr->edfparam[channel].prefilter, 81);
438 edfhdr->signalparam[i].smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords;
439 edfhdr->signalparam[i].phys_max = hdr->edfparam[channel].phys_max;
440 edfhdr->signalparam[i].phys_min = hdr->edfparam[channel].phys_min;
441 edfhdr->signalparam[i].dig_max = hdr->edfparam[channel].dig_max;
442 edfhdr->signalparam[i].dig_min = hdr->edfparam[channel].dig_min;
443 edfhdr->signalparam[i].smp_in_datarecord = hdr->edfparam[channel].smp_per_record;
444 }
445
446 return 0;
447 }
448
449
edfclose_file(int handle)450 int edfclose_file(int handle)
451 {
452 struct edf_write_annotationblock *annot2;
453
454 int i, j, k, n, p, err,
455 datrecsize,
456 nmemb;
457
458 long long offset,
459 datarecords;
460
461 char str[EDFLIB_ANNOTATION_BYTES * 2];
462
463 struct edfhdrblock *hdr;
464
465
466 if(handle<0)
467 {
468 return -1;
469 }
470
471 if(handle>=EDFLIB_MAXFILES)
472 {
473 return -1;
474 }
475
476 if(hdrlist[handle]==NULL)
477 {
478 return -1;
479 }
480
481 hdr = hdrlist[handle];
482
483 if(hdr->writemode)
484 {
485 if(hdr->datarecords == 0LL)
486 {
487 err = edflib_write_edf_header(hdr);
488 if(err)
489 {
490 fclose(hdr->file_hdl);
491
492 free(hdr->edfparam);
493
494 free(hdr->wrbuf);
495
496 free(hdr);
497
498 hdrlist[handle] = NULL;
499
500 free(write_annotationslist[handle]);
501
502 write_annotationslist[handle] = NULL;
503
504 edf_files_open--;
505
506 return err;
507 }
508
509 for(k=0; k<hdr->annots_in_file; k++)
510 {
511 annot2 = write_annotationslist[handle] + k;
512
513 p = edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1);
514
515 if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset))
516 {
517 fputc('.', hdr->file_hdl);
518 p++;
519 p += edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0);
520 }
521 fputc(20, hdr->file_hdl);
522 fputc(20, hdr->file_hdl);
523 p += 2;
524 for(; p<hdr->total_annot_bytes; p++)
525 {
526 fputc(0, hdr->file_hdl);
527 }
528
529 hdr->datarecords++;
530 }
531 }
532
533 if(hdr->datarecords<100000000LL)
534 {
535 fseeko(hdr->file_hdl, 236LL, SEEK_SET);
536 p = edflib_fprint_int_number_nonlocalized(hdr->file_hdl, (int)(hdr->datarecords), 0, 0);
537 if(p < 2)
538 {
539 fputc(' ', hdr->file_hdl);
540 }
541 }
542
543 datarecords = 0LL;
544
545 offset = (long long)((hdr->edfsignals + hdr->nr_annot_chns + 1) * 256);
546
547 datrecsize = hdr->total_annot_bytes;
548
549 for(i=0; i<hdr->edfsignals; i++)
550 {
551 if(hdr->edf)
552 {
553 offset += (long long)(hdr->edfparam[i].smp_per_record * 2);
554
555 datrecsize += (hdr->edfparam[i].smp_per_record * 2);
556 }
557 else
558 {
559 offset += (long long)(hdr->edfparam[i].smp_per_record * 3);
560
561 datrecsize += (hdr->edfparam[i].smp_per_record * 3);
562 }
563 }
564
565 j = 0;
566
567 for(k=0; k<hdr->annots_in_file; k++)
568 {
569 annot2 = write_annotationslist[handle] + k;
570
571 annot2->onset += hdr->starttime_offset / 1000LL;
572
573 p = 0;
574
575 if(j==0) // first annotation signal
576 {
577 if(fseeko(hdr->file_hdl, offset, SEEK_SET))
578 {
579 break;
580 }
581
582 p += edflib_snprint_ll_number_nonlocalized(str, (datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1, EDFLIB_ANNOTATION_BYTES * 2);
583
584 if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset))
585 {
586 str[p++] = '.';
587 n = edflib_snprint_ll_number_nonlocalized(str + p, (datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p);
588 p += n;
589 }
590 str[p++] = 20;
591 str[p++] = 20;
592 str[p++] = 0;
593 }
594
595 n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->onset / 10000LL, 0, 1, (EDFLIB_ANNOTATION_BYTES * 2) - p);
596 p += n;
597 if(annot2->onset % 10000LL)
598 {
599 str[p++] = '.';
600 n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->onset % 10000LL, 4, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p);
601 p += n;
602 }
603 if(annot2->duration>=0LL)
604 {
605 str[p++] = 21;
606 n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->duration / 10000LL, 0, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p);
607 p += n;
608 if(annot2->duration % 10000LL)
609 {
610 str[p++] = '.';
611 n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->duration % 10000LL, 4, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p);
612 p += n;
613 }
614 }
615 str[p++] = 20;
616 for(i=0; i<EDFLIB_WRITE_MAX_ANNOTATION_LEN; i++)
617 {
618 if(annot2->annotation[i]==0)
619 {
620 break;
621 }
622
623 str[p++] = annot2->annotation[i];
624 }
625 str[p++] = 20;
626
627 for(; p<EDFLIB_ANNOTATION_BYTES; p++)
628 {
629 str[p] = 0;
630 }
631
632 nmemb = fwrite(str, EDFLIB_ANNOTATION_BYTES, 1, hdr->file_hdl);
633
634 if(nmemb != 1)
635 {
636 break;
637 }
638
639 j++;
640
641 if(j >= hdr->nr_annot_chns)
642 {
643 j = 0;
644
645 offset += datrecsize;
646
647 datarecords++;
648
649 if(datarecords>=hdr->datarecords)
650 {
651 break;
652 }
653 }
654 }
655
656 free(write_annotationslist[handle]);
657 }
658 else
659 {
660 free(annotationslist[handle]);
661 }
662
663 fclose(hdr->file_hdl);
664
665 free(hdr->edfparam);
666
667 free(hdr->wrbuf);
668
669 free(hdr);
670
671 hdrlist[handle] = NULL;
672
673 edf_files_open--;
674
675 return 0;
676 }
677
678
edfseek(int handle,int edfsignal,long long offset,int whence)679 long long edfseek(int handle, int edfsignal, long long offset, int whence)
680 {
681 long long smp_in_file;
682
683 int channel;
684
685
686 if(handle<0)
687 {
688 return -1;
689 }
690
691 if(handle>=EDFLIB_MAXFILES)
692 {
693 return -1;
694 }
695
696 if(hdrlist[handle]==NULL)
697 {
698 return -1;
699 }
700
701 if(edfsignal<0)
702 {
703 return -1;
704 }
705
706 if(hdrlist[handle]->writemode)
707 {
708 return -1;
709 }
710
711 if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns))
712 {
713 return -1;
714 }
715
716 channel = hdrlist[handle]->mapped_signals[edfsignal];
717
718 smp_in_file = hdrlist[handle]->edfparam[channel].smp_per_record * hdrlist[handle]->datarecords;
719
720 if(whence==EDFSEEK_SET)
721 {
722 hdrlist[handle]->edfparam[channel].sample_pntr = offset;
723 }
724
725 if(whence==EDFSEEK_CUR)
726 {
727 hdrlist[handle]->edfparam[channel].sample_pntr += offset;
728 }
729
730 if(whence==EDFSEEK_END)
731 {
732 hdrlist[handle]->edfparam[channel].sample_pntr =
733 (hdrlist[handle]->edfparam[channel].smp_per_record * hdrlist[handle]->datarecords) + offset;
734 }
735
736 if(hdrlist[handle]->edfparam[channel].sample_pntr > smp_in_file)
737 {
738 hdrlist[handle]->edfparam[channel].sample_pntr = smp_in_file;
739 }
740
741 if(hdrlist[handle]->edfparam[channel].sample_pntr < 0LL)
742 {
743 hdrlist[handle]->edfparam[channel].sample_pntr = 0LL;
744 }
745
746 return hdrlist[handle]->edfparam[channel].sample_pntr;
747 }
748
749
edftell(int handle,int edfsignal)750 long long edftell(int handle, int edfsignal)
751 {
752 int channel;
753
754
755 if(handle<0)
756 {
757 return -1;
758 }
759
760 if(handle>=EDFLIB_MAXFILES)
761 {
762 return -1;
763 }
764
765 if(hdrlist[handle]==NULL)
766 {
767 return -1;
768 }
769
770 if(edfsignal<0)
771 {
772 return -1;
773 }
774
775 if(hdrlist[handle]->writemode)
776 {
777 return -1;
778 }
779
780 if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns))
781 {
782 return -1;
783 }
784
785 channel = hdrlist[handle]->mapped_signals[edfsignal];
786
787 return hdrlist[handle]->edfparam[channel].sample_pntr;
788 }
789
790
edfrewind(int handle,int edfsignal)791 void edfrewind(int handle, int edfsignal)
792 {
793 int channel;
794
795
796 if(handle<0)
797 {
798 return;
799 }
800
801 if(handle>=EDFLIB_MAXFILES)
802 {
803 return;
804 }
805
806 if(hdrlist[handle]==NULL)
807 {
808 return;
809 }
810
811 if(edfsignal<0)
812 {
813 return;
814 }
815
816 if(hdrlist[handle]->writemode)
817 {
818 return;
819 }
820
821 if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns))
822 {
823 return;
824 }
825
826 channel = hdrlist[handle]->mapped_signals[edfsignal];
827
828 hdrlist[handle]->edfparam[channel].sample_pntr = 0LL;
829 }
830
831
edfread_physical_samples(int handle,int edfsignal,int n,double * buf)832 int edfread_physical_samples(int handle, int edfsignal, int n, double *buf)
833 {
834 int bytes_per_smpl=2,
835 tmp,
836 i,
837 channel;
838
839 double phys_bitvalue,
840 phys_offset;
841
842 long long smp_in_file,
843 offset,
844 sample_pntr,
845 smp_per_record,
846 jump;
847
848 struct edfhdrblock *hdr;
849
850 union {
851 unsigned int one;
852 signed int one_signed;
853 unsigned short two[2];
854 signed short two_signed[2];
855 unsigned char four[4];
856 } var;
857
858 FILE *file;
859
860
861 if(handle<0)
862 {
863 return -1;
864 }
865
866 if(handle>=EDFLIB_MAXFILES)
867 {
868 return -1;
869 }
870
871 if(hdrlist[handle]==NULL)
872 {
873 return -1;
874 }
875
876 if(edfsignal<0)
877 {
878 return -1;
879 }
880
881 if(hdrlist[handle]->writemode)
882 {
883 return -1;
884 }
885
886 if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns))
887 {
888 return -1;
889 }
890
891 channel = hdrlist[handle]->mapped_signals[edfsignal];
892
893 if(n<0LL)
894 {
895 return -1;
896 }
897
898 if(n==0LL)
899 {
900 return 0LL;
901 }
902
903 hdr = hdrlist[handle];
904
905 if(hdr->edf)
906 {
907 bytes_per_smpl = 2;
908 }
909
910 if(hdr->bdf)
911 {
912 bytes_per_smpl = 3;
913 }
914
915 smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords;
916
917 if((hdr->edfparam[channel].sample_pntr + n) > smp_in_file)
918 {
919 n = smp_in_file - hdr->edfparam[channel].sample_pntr;
920
921 if(n==0)
922 {
923 return 0LL;
924 }
925
926 if(n<0)
927 {
928 return -1;
929 }
930 }
931
932 file = hdr->file_hdl;
933
934 offset = hdr->hdrsize;
935 offset += (hdr->edfparam[channel].sample_pntr / hdr->edfparam[channel].smp_per_record) * hdr->recordsize;
936 offset += hdr->edfparam[channel].buf_offset;
937 offset += ((hdr->edfparam[channel].sample_pntr % hdr->edfparam[channel].smp_per_record) * bytes_per_smpl);
938
939 fseeko(file, offset, SEEK_SET);
940
941 sample_pntr = hdr->edfparam[channel].sample_pntr;
942
943 smp_per_record = hdr->edfparam[channel].smp_per_record;
944
945 jump = hdr->recordsize - (smp_per_record * bytes_per_smpl);
946
947 phys_bitvalue = hdr->edfparam[channel].bitvalue;
948
949 phys_offset = hdr->edfparam[channel].offset;
950
951 if(hdr->edf)
952 {
953 for(i=0; i<n; i++)
954 {
955 if(!(sample_pntr%smp_per_record))
956 {
957 if(i)
958 {
959 fseeko(file, jump, SEEK_CUR);
960 }
961 }
962
963 var.four[0] = fgetc(file);
964 tmp = fgetc(file);
965 if(tmp==EOF)
966 {
967 return -1;
968 }
969 var.four[1] = tmp;
970
971 if(var.two_signed[0] > hdr->edfparam[channel].dig_max)
972 {
973 var.two_signed[0] = hdr->edfparam[channel].dig_max;
974 }
975 else if(var.two_signed[0] < hdr->edfparam[channel].dig_min)
976 {
977 var.two_signed[0] = hdr->edfparam[channel].dig_min;
978 }
979
980 buf[i] = phys_bitvalue * (phys_offset + (double)var.two_signed[0]);
981
982 sample_pntr++;
983 }
984 }
985
986 if(hdr->bdf)
987 {
988 for(i=0; i<n; i++)
989 {
990 if(!(sample_pntr%smp_per_record))
991 {
992 if(i)
993 {
994 fseeko(file, jump, SEEK_CUR);
995 }
996 }
997
998 var.four[0] = fgetc(file);
999 var.four[1] = fgetc(file);
1000 tmp = fgetc(file);
1001 if(tmp==EOF)
1002 {
1003 return -1;
1004 }
1005 var.four[2] = tmp;
1006
1007 if(var.four[2]&0x80)
1008 {
1009 var.four[3] = 0xff;
1010 }
1011 else
1012 {
1013 var.four[3] = 0x00;
1014 }
1015
1016 if(var.one_signed > hdr->edfparam[channel].dig_max)
1017 {
1018 var.one_signed = hdr->edfparam[channel].dig_max;
1019 }
1020 else if(var.one_signed < hdr->edfparam[channel].dig_min)
1021 {
1022 var.one_signed = hdr->edfparam[channel].dig_min;
1023 }
1024
1025 buf[i] = phys_bitvalue * (phys_offset + (double)var.one_signed);
1026
1027 sample_pntr++;
1028 }
1029 }
1030
1031 hdr->edfparam[channel].sample_pntr = sample_pntr;
1032
1033 return n;
1034 }
1035
1036
edfread_digital_samples(int handle,int edfsignal,int n,int * buf)1037 int edfread_digital_samples(int handle, int edfsignal, int n, int *buf)
1038 {
1039 int bytes_per_smpl=2,
1040 tmp,
1041 i,
1042 channel;
1043
1044 long long smp_in_file,
1045 offset,
1046 sample_pntr,
1047 smp_per_record,
1048 jump;
1049
1050 struct edfhdrblock *hdr;
1051
1052 union {
1053 unsigned int one;
1054 signed int one_signed;
1055 unsigned short two[2];
1056 signed short two_signed[2];
1057 unsigned char four[4];
1058 } var;
1059
1060 FILE *file;
1061
1062
1063 if(handle<0)
1064 {
1065 return -1;
1066 }
1067
1068 if(handle>=EDFLIB_MAXFILES)
1069 {
1070 return -1;
1071 }
1072
1073 if(hdrlist[handle]==NULL)
1074 {
1075 return -1;
1076 }
1077
1078 if(edfsignal<0)
1079 {
1080 return -1;
1081 }
1082
1083 if(hdrlist[handle]->writemode)
1084 {
1085 return -1;
1086 }
1087
1088 if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns))
1089 {
1090 return -1;
1091 }
1092
1093 channel = hdrlist[handle]->mapped_signals[edfsignal];
1094
1095 if(n<0LL)
1096 {
1097 return -1;
1098 }
1099
1100 if(n==0LL)
1101 {
1102 return 0LL;
1103 }
1104
1105 hdr = hdrlist[handle];
1106
1107 if(hdr->edf)
1108 {
1109 bytes_per_smpl = 2;
1110 }
1111
1112 if(hdr->bdf)
1113 {
1114 bytes_per_smpl = 3;
1115 }
1116
1117 smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords;
1118
1119 if((hdr->edfparam[channel].sample_pntr + n) > smp_in_file)
1120 {
1121 n = smp_in_file - hdr->edfparam[channel].sample_pntr;
1122
1123 if(n==0)
1124 {
1125 return 0LL;
1126 }
1127
1128 if(n<0)
1129 {
1130 return -1;
1131 }
1132 }
1133
1134 file = hdr->file_hdl;
1135
1136 offset = hdr->hdrsize;
1137 offset += (hdr->edfparam[channel].sample_pntr / hdr->edfparam[channel].smp_per_record) * hdr->recordsize;
1138 offset += hdr->edfparam[channel].buf_offset;
1139 offset += ((hdr->edfparam[channel].sample_pntr % hdr->edfparam[channel].smp_per_record) * bytes_per_smpl);
1140
1141 fseeko(file, offset, SEEK_SET);
1142
1143 sample_pntr = hdr->edfparam[channel].sample_pntr;
1144
1145 smp_per_record = hdr->edfparam[channel].smp_per_record;
1146
1147 jump = hdr->recordsize - (smp_per_record * bytes_per_smpl);
1148
1149 if(hdr->edf)
1150 {
1151 for(i=0; i<n; i++)
1152 {
1153 if(!(sample_pntr%smp_per_record))
1154 {
1155 if(i)
1156 {
1157 fseeko(file, jump, SEEK_CUR);
1158 }
1159 }
1160
1161 var.four[0] = fgetc(file);
1162 tmp = fgetc(file);
1163 if(tmp==EOF)
1164 {
1165 return -1;
1166 }
1167 var.four[1] = tmp;
1168
1169 if(var.two_signed[0] > hdr->edfparam[channel].dig_max)
1170 {
1171 var.two_signed[0] = hdr->edfparam[channel].dig_max;
1172 }
1173 else if(var.two_signed[0] < hdr->edfparam[channel].dig_min)
1174 {
1175 var.two_signed[0] = hdr->edfparam[channel].dig_min;
1176 }
1177
1178 buf[i] = var.two_signed[0];
1179
1180 sample_pntr++;
1181 }
1182 }
1183
1184 if(hdr->bdf)
1185 {
1186 for(i=0; i<n; i++)
1187 {
1188 if(!(sample_pntr%smp_per_record))
1189 {
1190 if(i)
1191 {
1192 fseeko(file, jump, SEEK_CUR);
1193 }
1194 }
1195
1196 var.four[0] = fgetc(file);
1197 var.four[1] = fgetc(file);
1198 tmp = fgetc(file);
1199 if(tmp==EOF)
1200 {
1201 return -1;
1202 }
1203 var.four[2] = tmp;
1204
1205 if(var.four[2]&0x80)
1206 {
1207 var.four[3] = 0xff;
1208 }
1209 else
1210 {
1211 var.four[3] = 0x00;
1212 }
1213
1214 if(var.one_signed > hdr->edfparam[channel].dig_max)
1215 {
1216 var.one_signed = hdr->edfparam[channel].dig_max;
1217 }
1218 else if(var.one_signed < hdr->edfparam[channel].dig_min)
1219 {
1220 var.one_signed = hdr->edfparam[channel].dig_min;
1221 }
1222
1223 buf[i] = var.one_signed;
1224
1225 sample_pntr++;
1226 }
1227 }
1228
1229 hdr->edfparam[channel].sample_pntr = sample_pntr;
1230
1231 return n;
1232 }
1233
1234
edf_get_annotation(int handle,int n,struct edf_annotation_struct * annot)1235 int edf_get_annotation(int handle, int n, struct edf_annotation_struct *annot)
1236 {
1237 memset(annot, 0, sizeof(struct edf_annotation_struct));
1238
1239 if(handle<0)
1240 {
1241 return -1;
1242 }
1243
1244 if(handle>=EDFLIB_MAXFILES)
1245 {
1246 return -1;
1247 }
1248
1249 if(hdrlist[handle]==NULL)
1250 {
1251 return -1;
1252 }
1253
1254 if(hdrlist[handle]->writemode)
1255 {
1256 return -1;
1257 }
1258
1259 if(n<0)
1260 {
1261 return -1;
1262 }
1263
1264 if(n>=hdrlist[handle]->annots_in_file)
1265 {
1266 return -1;
1267 }
1268
1269 annot->onset = (annotationslist[handle] + n)->onset;
1270 edflib_strlcpy(annot->duration, (annotationslist[handle] + n)->duration, 16);
1271 edflib_strlcpy(annot->annotation, (annotationslist[handle] + n)->annotation, EDFLIB_MAX_ANNOTATION_LEN + 1);
1272
1273 return 0;
1274 }
1275
1276
edflib_check_edf_file(FILE * inputfile,int * edf_error)1277 static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_error)
1278 {
1279 int i, j, p, r=0, n,
1280 dotposition,
1281 error;
1282
1283 char *edf_hdr,
1284 scratchpad[128],
1285 scratchpad2[64];
1286
1287 struct edfhdrblock *edfhdr;
1288
1289 /***************** check header ******************************/
1290
1291 edf_hdr = (char *)calloc(1, 256);
1292 if(edf_hdr==NULL)
1293 {
1294 *edf_error = EDFLIB_MALLOC_ERROR;
1295 return NULL;
1296 }
1297
1298 edfhdr = (struct edfhdrblock *)calloc(1, sizeof(struct edfhdrblock));
1299 if(edfhdr==NULL)
1300 {
1301 free(edf_hdr);
1302 *edf_error = EDFLIB_MALLOC_ERROR;
1303 return NULL;
1304 }
1305
1306 rewind(inputfile);
1307 if(fread(edf_hdr, 256, 1, inputfile)!=1)
1308 {
1309 *edf_error = EDFLIB_FILE_READ_ERROR;
1310 free(edf_hdr);
1311 free(edfhdr);
1312 return NULL;
1313 }
1314
1315 /**************************** VERSION ***************************************/
1316
1317 strncpy(scratchpad, edf_hdr, 8);
1318 scratchpad[8] = 0;
1319
1320 if(((signed char *)scratchpad)[0]==-1) /* BDF-file */
1321 {
1322 for(i=1; i<8; i++)
1323 {
1324 if((scratchpad[i]<32)||(scratchpad[i]>126))
1325 {
1326 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1327 free(edf_hdr);
1328 free(edfhdr);
1329 return NULL;
1330 }
1331 }
1332
1333 if(strcmp(scratchpad + 1, "BIOSEMI"))
1334 {
1335 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1336 free(edf_hdr);
1337 free(edfhdr);
1338 return NULL;
1339 }
1340
1341 edfhdr->bdf = 1;
1342 }
1343 else /* EDF-file */
1344 {
1345 for(i=0; i<8; i++)
1346 {
1347 if((scratchpad[i]<32)||(scratchpad[i]>126))
1348 {
1349 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1350 free(edf_hdr);
1351 free(edfhdr);
1352 return NULL;
1353 }
1354 }
1355
1356 if(strcmp(scratchpad, "0 "))
1357 {
1358 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1359 free(edf_hdr);
1360 free(edfhdr);
1361 return NULL;
1362 }
1363
1364 edfhdr->edf = 1;
1365 }
1366
1367 strncpy(edfhdr->version, edf_hdr, 8);
1368 edfhdr->version[8] = 0;
1369 if(edfhdr->bdf) edfhdr->version[0] = '.';
1370
1371 /********************* PATIENTNAME *********************************************/
1372
1373 strncpy(scratchpad, edf_hdr + 8, 80);
1374 scratchpad[80] = 0;
1375 for(i=0; i<80; i++)
1376 {
1377 if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126))
1378 {
1379 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1380 free(edf_hdr);
1381 free(edfhdr);
1382 return NULL;
1383 }
1384 }
1385
1386 strncpy(edfhdr->patient, edf_hdr + 8, 80);
1387 edfhdr->patient[80] = 0;
1388
1389 /********************* RECORDING *********************************************/
1390
1391 strncpy(scratchpad, edf_hdr + 88, 80);
1392 scratchpad[80] = 0;
1393 for(i=0; i<80; i++)
1394 {
1395 if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126))
1396 {
1397 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1398 free(edf_hdr);
1399 free(edfhdr);
1400 return NULL;
1401 }
1402 }
1403
1404 strncpy(edfhdr->recording, edf_hdr + 88, 80);
1405 edfhdr->recording[80] = 0;
1406
1407 /********************* STARTDATE *********************************************/
1408
1409 strncpy(scratchpad, edf_hdr + 168, 8);
1410 scratchpad[8] = 0;
1411 for(i=0; i<8; i++)
1412 {
1413 if((scratchpad[i]<32)||(scratchpad[i]>126))
1414 {
1415 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1416 free(edf_hdr);
1417 free(edfhdr);
1418 return NULL;
1419 }
1420 }
1421
1422 error = 0;
1423
1424 if((edf_hdr[170]!='.')||(edf_hdr[173]!='.')) error = 1;
1425 if((edf_hdr[168]<48)||(edf_hdr[168]>57)) error = 1;
1426 if((edf_hdr[169]<48)||(edf_hdr[169]>57)) error = 1;
1427 if((edf_hdr[171]<48)||(edf_hdr[171]>57)) error = 1;
1428 if((edf_hdr[172]<48)||(edf_hdr[172]>57)) error = 1;
1429 if((edf_hdr[174]<48)||(edf_hdr[174]>57)) error = 1;
1430 if((edf_hdr[175]<48)||(edf_hdr[175]>57)) error = 1;
1431 strncpy(scratchpad, edf_hdr + 168, 8);
1432
1433 if(error)
1434 {
1435 scratchpad[8] = 0;
1436 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1437 free(edf_hdr);
1438 free(edfhdr);
1439 return NULL;
1440 }
1441
1442 scratchpad[2] = 0;
1443 scratchpad[5] = 0;
1444 scratchpad[8] = 0;
1445
1446 if((edflib_atof_nonlocalized(scratchpad)<1)||(edflib_atof_nonlocalized(scratchpad)>31))
1447 {
1448 strncpy(scratchpad, edf_hdr + 168, 8);
1449 scratchpad[8] = 0;
1450 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1451 free(edf_hdr);
1452 free(edfhdr);
1453 return NULL;
1454 }
1455
1456 if((edflib_atof_nonlocalized(scratchpad+3)<1)||(edflib_atof_nonlocalized(scratchpad+3)>12))
1457 {
1458 strncpy(scratchpad, edf_hdr + 168, 8);
1459 scratchpad[8] = 0;
1460 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1461 free(edf_hdr);
1462 free(edfhdr);
1463 return NULL;
1464 }
1465
1466 edfhdr->startdate_day = edflib_atof_nonlocalized(scratchpad);
1467 edfhdr->startdate_month = edflib_atof_nonlocalized(scratchpad + 3);
1468 edfhdr->startdate_year = edflib_atof_nonlocalized(scratchpad + 6);
1469 if(edfhdr->startdate_year>84)
1470 {
1471 edfhdr->startdate_year += 1900;
1472 }
1473 else
1474 {
1475 edfhdr->startdate_year += 2000;
1476 }
1477
1478 /********************* STARTTIME *********************************************/
1479
1480 strncpy(scratchpad, edf_hdr + 176, 8);
1481 scratchpad[8] = 0;
1482 for(i=0; i<8; i++)
1483 {
1484 if((scratchpad[i]<32)||(scratchpad[i]>126))
1485 {
1486 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1487 free(edf_hdr);
1488 free(edfhdr);
1489 return NULL;
1490 }
1491 }
1492
1493 error = 0;
1494
1495 if((edf_hdr[178]!='.')||(edf_hdr[181]!='.')) error = 1;
1496 if((edf_hdr[176]<48)||(edf_hdr[176]>57)) error = 1;
1497 if((edf_hdr[177]<48)||(edf_hdr[177]>57)) error = 1;
1498 if((edf_hdr[179]<48)||(edf_hdr[179]>57)) error = 1;
1499 if((edf_hdr[180]<48)||(edf_hdr[180]>57)) error = 1;
1500 if((edf_hdr[182]<48)||(edf_hdr[182]>57)) error = 1;
1501 if((edf_hdr[183]<48)||(edf_hdr[183]>57)) error = 1;
1502
1503 strncpy(scratchpad, edf_hdr + 176, 8);
1504
1505 if(error)
1506 {
1507 strncpy(scratchpad, edf_hdr + 176, 8);
1508 scratchpad[8] = 0;
1509 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1510 free(edf_hdr);
1511 free(edfhdr);
1512 return NULL;
1513 }
1514
1515 scratchpad[2] = 0;
1516 scratchpad[5] = 0;
1517 scratchpad[8] = 0;
1518
1519 if(edflib_atof_nonlocalized(scratchpad)>23)
1520 {
1521 strncpy(scratchpad, edf_hdr + 176, 8);
1522 scratchpad[8] = 0;
1523 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1524 free(edf_hdr);
1525 free(edfhdr);
1526 return NULL;
1527 }
1528
1529 if(edflib_atof_nonlocalized(scratchpad+3)>59)
1530 {
1531 strncpy(scratchpad, edf_hdr + 176, 8);
1532 scratchpad[8] = 0;
1533 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1534 free(edf_hdr);
1535 free(edfhdr);
1536 return NULL;
1537 }
1538
1539 if(edflib_atof_nonlocalized(scratchpad+6)>59)
1540 {
1541 strncpy(scratchpad, edf_hdr + 176, 8);
1542 scratchpad[8] = 0;
1543 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1544 free(edf_hdr);
1545 free(edfhdr);
1546 return NULL;
1547 }
1548
1549 edfhdr->starttime_hour = edflib_atof_nonlocalized(scratchpad);
1550 edfhdr->starttime_minute = edflib_atof_nonlocalized(scratchpad + 3);
1551 edfhdr->starttime_second = edflib_atof_nonlocalized(scratchpad + 6);
1552
1553 edfhdr->l_starttime = 3600 * edflib_atof_nonlocalized(scratchpad);
1554 edfhdr->l_starttime += 60 * edflib_atof_nonlocalized(scratchpad + 3);
1555 edfhdr->l_starttime += edflib_atof_nonlocalized(scratchpad + 6);
1556
1557 edfhdr->l_starttime *= EDFLIB_TIME_DIMENSION;
1558
1559 /***************** NUMBER OF SIGNALS IN HEADER *******************************/
1560
1561 strncpy(scratchpad, edf_hdr + 252, 4);
1562 scratchpad[4] = 0;
1563 for(i=0; i<4; i++)
1564 {
1565 if((scratchpad[i]<32)||(scratchpad[i]>126))
1566 {
1567 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1568 free(edf_hdr);
1569 free(edfhdr);
1570 return NULL;
1571 }
1572 }
1573
1574 if(edflib_is_integer_number(scratchpad))
1575 {
1576 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1577 free(edf_hdr);
1578 free(edfhdr);
1579 return NULL;
1580 }
1581 edfhdr->edfsignals = edflib_atof_nonlocalized(scratchpad);
1582 if(edfhdr->edfsignals<1)
1583 {
1584 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1585 free(edf_hdr);
1586 free(edfhdr);
1587 return NULL;
1588 }
1589
1590 if(edfhdr->edfsignals>EDFLIB_MAXSIGNALS)
1591 {
1592 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1593 free(edf_hdr);
1594 free(edfhdr);
1595 return NULL;
1596 }
1597
1598 /***************** NUMBER OF BYTES IN HEADER *******************************/
1599
1600 strncpy(scratchpad, edf_hdr + 184, 8);
1601 scratchpad[8] = 0;
1602
1603 for(i=0; i<8; i++)
1604 {
1605 if((scratchpad[i]<32)||(scratchpad[i]>126))
1606 {
1607 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1608 free(edf_hdr);
1609 free(edfhdr);
1610 return NULL;
1611 }
1612 }
1613
1614 if(edflib_is_integer_number(scratchpad))
1615 {
1616 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1617 free(edf_hdr);
1618 free(edfhdr);
1619 return NULL;
1620 }
1621
1622 n = edflib_atof_nonlocalized(scratchpad);
1623 if((edfhdr->edfsignals * 256 + 256)!=n)
1624 {
1625 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1626 free(edf_hdr);
1627 free(edfhdr);
1628 return NULL;
1629 }
1630
1631 /********************* RESERVED FIELD *************************************/
1632
1633 edfhdr->edfplus = 0;
1634 edfhdr->discontinuous = 0;
1635 strncpy(scratchpad, edf_hdr + 192, 44);
1636 scratchpad[44] = 0;
1637
1638 for(i=0; i<44; i++)
1639 {
1640 if((scratchpad[i]<32)||(scratchpad[i]>126))
1641 {
1642 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1643 free(edf_hdr);
1644 free(edfhdr);
1645 return NULL;
1646 }
1647 }
1648
1649 if(edfhdr->edf)
1650 {
1651 if(!strncmp(scratchpad, "EDF+C", 5))
1652 {
1653 edfhdr->edfplus = 1;
1654 }
1655
1656 if(!strncmp(scratchpad, "EDF+D", 5))
1657 {
1658 edfhdr->edfplus = 1;
1659 edfhdr->discontinuous = 1;
1660 }
1661 }
1662
1663 if(edfhdr->bdf)
1664 {
1665 if(!strncmp(scratchpad, "BDF+C", 5))
1666 {
1667 edfhdr->bdfplus = 1;
1668 }
1669
1670 if(!strncmp(scratchpad, "BDF+D", 5))
1671 {
1672 edfhdr->bdfplus = 1;
1673 edfhdr->discontinuous = 1;
1674 }
1675 }
1676
1677 strncpy(edfhdr->reserved, edf_hdr + 192, 44);
1678 edfhdr->reserved[44] = 0;
1679
1680 /********************* NUMBER OF DATARECORDS *************************************/
1681
1682 strncpy(scratchpad, edf_hdr + 236, 8);
1683 scratchpad[8] = 0;
1684
1685 for(i=0; i<8; i++)
1686 {
1687 if((scratchpad[i]<32)||(scratchpad[i]>126))
1688 {
1689 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1690 free(edf_hdr);
1691 free(edfhdr);
1692 return NULL;
1693 }
1694 }
1695
1696 if(edflib_is_integer_number(scratchpad))
1697 {
1698 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1699 free(edf_hdr);
1700 free(edfhdr);
1701 return NULL;
1702 }
1703
1704 edfhdr->datarecords = edflib_atof_nonlocalized(scratchpad);
1705 if(edfhdr->datarecords<1)
1706 {
1707 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1708 free(edf_hdr);
1709 free(edfhdr);
1710 return NULL;
1711 }
1712
1713 /********************* DATARECORD DURATION *************************************/
1714
1715 strncpy(scratchpad, edf_hdr + 244, 8);
1716 scratchpad[8] = 0;
1717
1718 for(i=0; i<8; i++)
1719 {
1720 if((scratchpad[i]<32)||(scratchpad[i]>126))
1721 {
1722 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1723 free(edf_hdr);
1724 free(edfhdr);
1725 return NULL;
1726 }
1727 }
1728
1729 if(edflib_is_number(scratchpad))
1730 {
1731 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1732 free(edf_hdr);
1733 free(edfhdr);
1734 return NULL;
1735 }
1736
1737 edfhdr->data_record_duration = edflib_atof_nonlocalized(scratchpad);
1738 if(edfhdr->data_record_duration < -0.000001)
1739 {
1740 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1741 free(edf_hdr);
1742 free(edfhdr);
1743 return NULL;
1744 }
1745
1746 edfhdr->long_data_record_duration = edflib_get_long_duration(scratchpad);
1747
1748 free(edf_hdr);
1749
1750 /********************* START WITH THE SIGNALS IN THE HEADER *********************/
1751
1752 edf_hdr = (char *)calloc(1, (edfhdr->edfsignals + 1) * 256);
1753 if(edf_hdr==NULL)
1754 {
1755 *edf_error = EDFLIB_MALLOC_ERROR;
1756 free(edfhdr);
1757 return NULL;
1758 }
1759
1760 rewind(inputfile);
1761 if(fread(edf_hdr, (edfhdr->edfsignals + 1) * 256, 1, inputfile)!=1)
1762 {
1763 *edf_error = EDFLIB_FILE_READ_ERROR;
1764 free(edf_hdr);
1765 free(edfhdr);
1766 return NULL;
1767 }
1768
1769 edfhdr->edfparam = (struct edfparamblock *)calloc(1, sizeof(struct edfparamblock) * edfhdr->edfsignals);
1770 if(edfhdr->edfparam==NULL)
1771 {
1772 *edf_error = EDFLIB_MALLOC_ERROR;
1773 free(edf_hdr);
1774 free(edfhdr);
1775 return NULL;
1776 }
1777
1778 /**************************** LABELS *************************************/
1779
1780 edfhdr->nr_annot_chns = 0;
1781 for(i=0; i<edfhdr->edfsignals; i++)
1782 {
1783 strncpy(scratchpad, edf_hdr + 256 + (i * 16), 16);
1784 for(j=0; j<16; j++)
1785 {
1786 if((scratchpad[j]<32)||(scratchpad[j]>126))
1787 {
1788 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1789 free(edf_hdr);
1790 free(edfhdr->edfparam);
1791 free(edfhdr);
1792 return NULL;
1793 }
1794 }
1795 if(edfhdr->edfplus)
1796 {
1797 if(!strncmp(scratchpad, "EDF Annotations ", 16))
1798 {
1799 edfhdr->annot_ch[edfhdr->nr_annot_chns] = i;
1800 edfhdr->nr_annot_chns++;
1801 edfhdr->edfparam[i].annotation = 1;
1802 }
1803 }
1804 if(edfhdr->bdfplus)
1805 {
1806 if(!strncmp(scratchpad, "BDF Annotations ", 16))
1807 {
1808 edfhdr->annot_ch[edfhdr->nr_annot_chns] = i;
1809 edfhdr->nr_annot_chns++;
1810 edfhdr->edfparam[i].annotation = 1;
1811 }
1812 }
1813 strncpy(edfhdr->edfparam[i].label, edf_hdr + 256 + (i * 16), 16);
1814 edfhdr->edfparam[i].label[16] = 0;
1815 }
1816 if(edfhdr->edfplus&&(!edfhdr->nr_annot_chns))
1817 {
1818 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1819 free(edf_hdr);
1820 free(edfhdr->edfparam);
1821 free(edfhdr);
1822 return NULL;
1823 }
1824 if(edfhdr->bdfplus&&(!edfhdr->nr_annot_chns))
1825 {
1826 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1827 free(edf_hdr);
1828 free(edfhdr->edfparam);
1829 free(edfhdr);
1830 return NULL;
1831 }
1832 if((edfhdr->edfsignals!=edfhdr->nr_annot_chns)||((!edfhdr->edfplus)&&(!edfhdr->bdfplus)))
1833 {
1834 if(edfhdr->data_record_duration<0.0000001)
1835 {
1836 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1837 free(edf_hdr);
1838 free(edfhdr->edfparam);
1839 free(edfhdr);
1840 return NULL;
1841 }
1842 }
1843
1844 /**************************** TRANSDUCER TYPES *************************************/
1845
1846 for(i=0; i<edfhdr->edfsignals; i++)
1847 {
1848 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80);
1849 for(j=0; j<80; j++)
1850 {
1851 if((scratchpad[j]<32)||(scratchpad[j]>126))
1852 {
1853 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1854 free(edf_hdr);
1855 free(edfhdr->edfparam);
1856 free(edfhdr);
1857 return NULL;
1858 }
1859 }
1860 strncpy(edfhdr->edfparam[i].transducer, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80);
1861 edfhdr->edfparam[i].transducer[80] = 0;
1862
1863 if((edfhdr->edfplus) || (edfhdr->bdfplus))
1864 {
1865 if(edfhdr->edfparam[i].annotation)
1866 {
1867 for(j=0; j<80; j++)
1868 {
1869 if(edfhdr->edfparam[i].transducer[j]!=' ')
1870 {
1871 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1872 free(edf_hdr);
1873 free(edfhdr->edfparam);
1874 free(edfhdr);
1875 return NULL;
1876 }
1877 }
1878 }
1879 }
1880 }
1881
1882 /**************************** PHYSICAL DIMENSIONS *************************************/
1883
1884 for(i=0; i<edfhdr->edfsignals; i++)
1885 {
1886 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 96) + (i * 8), 8);
1887 for(j=0; j<8; j++)
1888 {
1889 if((scratchpad[j]<32)||(scratchpad[j]>126))
1890 {
1891 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1892 free(edf_hdr);
1893 free(edfhdr->edfparam);
1894 free(edfhdr);
1895 return NULL;
1896 }
1897 }
1898 strncpy(edfhdr->edfparam[i].physdimension, edf_hdr + 256 + (edfhdr->edfsignals * 96) + (i * 8), 8);
1899 edfhdr->edfparam[i].physdimension[8] = 0;
1900 }
1901
1902 /**************************** PHYSICAL MINIMUMS *************************************/
1903
1904 for(i=0; i<edfhdr->edfsignals; i++)
1905 {
1906 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 104) + (i * 8), 8);
1907 scratchpad[8] = 0;
1908
1909 for(j=0; j<8; j++)
1910 {
1911 if((scratchpad[j]<32)||(scratchpad[j]>126))
1912 {
1913 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1914 free(edf_hdr);
1915 free(edfhdr->edfparam);
1916 free(edfhdr);
1917 return NULL;
1918 }
1919 }
1920
1921 if(edflib_is_number(scratchpad))
1922 {
1923 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1924 free(edf_hdr);
1925 free(edfhdr->edfparam);
1926 free(edfhdr);
1927 return NULL;
1928 }
1929
1930 edfhdr->edfparam[i].phys_min = edflib_atof_nonlocalized(scratchpad);
1931 }
1932
1933 /**************************** PHYSICAL MAXIMUMS *************************************/
1934
1935 for(i=0; i<edfhdr->edfsignals; i++)
1936 {
1937 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 112) + (i * 8), 8);
1938 scratchpad[8] = 0;
1939
1940 for(j=0; j<8; j++)
1941 {
1942 if((scratchpad[j]<32)||(scratchpad[j]>126))
1943 {
1944 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1945 free(edf_hdr);
1946 free(edfhdr->edfparam);
1947 free(edfhdr);
1948 return NULL;
1949 }
1950 }
1951
1952 if(edflib_is_number(scratchpad))
1953 {
1954 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1955 free(edf_hdr);
1956 free(edfhdr->edfparam);
1957 free(edfhdr);
1958 return NULL;
1959 }
1960
1961 edfhdr->edfparam[i].phys_max = edflib_atof_nonlocalized(scratchpad);
1962 if(edfhdr->edfparam[i].phys_max==edfhdr->edfparam[i].phys_min)
1963 {
1964 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1965 free(edf_hdr);
1966 free(edfhdr->edfparam);
1967 free(edfhdr);
1968 return NULL;
1969 }
1970 }
1971
1972 /**************************** DIGITAL MINIMUMS *************************************/
1973
1974 for(i=0; i<edfhdr->edfsignals; i++)
1975 {
1976 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 120) + (i * 8), 8);
1977 scratchpad[8] = 0;
1978
1979 for(j=0; j<8; j++)
1980 {
1981 if((scratchpad[j]<32)||(scratchpad[j]>126))
1982 {
1983 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1984 free(edf_hdr);
1985 free(edfhdr->edfparam);
1986 free(edfhdr);
1987 return NULL;
1988 }
1989 }
1990
1991 if(edflib_is_integer_number(scratchpad))
1992 {
1993 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
1994 free(edf_hdr);
1995 free(edfhdr->edfparam);
1996 free(edfhdr);
1997 return NULL;
1998 }
1999
2000 n = edflib_atof_nonlocalized(scratchpad);
2001 if(edfhdr->edfplus)
2002 {
2003 if(edfhdr->edfparam[i].annotation)
2004 {
2005 if(n!=-32768)
2006 {
2007 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2008 free(edf_hdr);
2009 free(edfhdr->edfparam);
2010 free(edfhdr);
2011 return NULL;
2012 }
2013 }
2014 }
2015 if(edfhdr->bdfplus)
2016 {
2017 if(edfhdr->edfparam[i].annotation)
2018 {
2019 if(n!=-8388608)
2020 {
2021 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2022 free(edf_hdr);
2023 free(edfhdr->edfparam);
2024 free(edfhdr);
2025 return NULL;
2026 }
2027 }
2028 }
2029 if(edfhdr->edf)
2030 {
2031 if((n>32767)||(n<-32768))
2032 {
2033 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2034 free(edf_hdr);
2035 free(edfhdr->edfparam);
2036 free(edfhdr);
2037 return NULL;
2038 }
2039 }
2040 if(edfhdr->bdf)
2041 {
2042 if((n>8388607)||(n<-8388608))
2043 {
2044 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2045 free(edf_hdr);
2046 free(edfhdr->edfparam);
2047 free(edfhdr);
2048 return NULL;
2049 }
2050 }
2051 edfhdr->edfparam[i].dig_min = n;
2052 }
2053
2054 /**************************** DIGITAL MAXIMUMS *************************************/
2055
2056 for(i=0; i<edfhdr->edfsignals; i++)
2057 {
2058 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 128) + (i * 8), 8);
2059 scratchpad[8] = 0;
2060
2061 for(j=0; j<8; j++)
2062 {
2063 if((scratchpad[j]<32)||(scratchpad[j]>126))
2064 {
2065 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2066 free(edf_hdr);
2067 free(edfhdr->edfparam);
2068 free(edfhdr);
2069 return NULL;
2070 }
2071 }
2072
2073 if(edflib_is_integer_number(scratchpad))
2074 {
2075 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2076 free(edf_hdr);
2077 free(edfhdr->edfparam);
2078 free(edfhdr);
2079 return NULL;
2080 }
2081
2082 n = edflib_atof_nonlocalized(scratchpad);
2083 if(edfhdr->edfplus)
2084 {
2085 if(edfhdr->edfparam[i].annotation)
2086 {
2087 if(n!=32767)
2088 {
2089 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2090 free(edf_hdr);
2091 free(edfhdr->edfparam);
2092 free(edfhdr);
2093 return NULL;
2094 }
2095 }
2096 }
2097 if(edfhdr->bdfplus)
2098 {
2099 if(edfhdr->edfparam[i].annotation)
2100 {
2101 if(n!=8388607)
2102 {
2103 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2104 free(edf_hdr);
2105 free(edfhdr->edfparam);
2106 free(edfhdr);
2107 return NULL;
2108 }
2109 }
2110 }
2111 if(edfhdr->edf)
2112 {
2113 if((n>32767)||(n<-32768))
2114 {
2115 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2116 free(edf_hdr);
2117 free(edfhdr->edfparam);
2118 free(edfhdr);
2119 return NULL;
2120 }
2121 }
2122 else
2123 {
2124 if((n>8388607)||(n<-8388608))
2125 {
2126 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2127 free(edf_hdr);
2128 free(edfhdr->edfparam);
2129 free(edfhdr);
2130 return NULL;
2131 }
2132 }
2133 edfhdr->edfparam[i].dig_max = n;
2134 if(edfhdr->edfparam[i].dig_max<(edfhdr->edfparam[i].dig_min + 1))
2135 {
2136 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2137 free(edf_hdr);
2138 free(edfhdr->edfparam);
2139 free(edfhdr);
2140 return NULL;
2141 }
2142 }
2143
2144 /**************************** PREFILTER FIELDS *************************************/
2145
2146 for(i=0; i<edfhdr->edfsignals; i++)
2147 {
2148 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80);
2149 for(j=0; j<80; j++)
2150 {
2151 if((scratchpad[j]<32)||(scratchpad[j]>126))
2152 {
2153 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2154 free(edf_hdr);
2155 free(edfhdr->edfparam);
2156 free(edfhdr);
2157 return NULL;
2158 }
2159 }
2160 strncpy(edfhdr->edfparam[i].prefilter, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80);
2161 edfhdr->edfparam[i].prefilter[80] = 0;
2162
2163 if((edfhdr->edfplus) || (edfhdr->bdfplus))
2164 {
2165 if(edfhdr->edfparam[i].annotation)
2166 {
2167 for(j=0; j<80; j++)
2168 {
2169 if(edfhdr->edfparam[i].prefilter[j]!=' ')
2170 {
2171 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2172 free(edf_hdr);
2173 free(edfhdr->edfparam);
2174 free(edfhdr);
2175 return NULL;
2176 }
2177 }
2178 }
2179 }
2180 }
2181
2182 /*********************** NR OF SAMPLES IN EACH DATARECORD ********************/
2183
2184 edfhdr->recordsize = 0;
2185
2186 for(i=0; i<edfhdr->edfsignals; i++)
2187 {
2188 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 216) + (i * 8), 8);
2189 scratchpad[8] = 0;
2190
2191 for(j=0; j<8; j++)
2192 {
2193 if((scratchpad[j]<32)||(scratchpad[j]>126))
2194 {
2195 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2196 free(edf_hdr);
2197 free(edfhdr->edfparam);
2198 free(edfhdr);
2199 return NULL;
2200 }
2201 }
2202
2203 if(edflib_is_integer_number(scratchpad))
2204 {
2205 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2206 free(edf_hdr);
2207 free(edfhdr->edfparam);
2208 free(edfhdr);
2209 return NULL;
2210 }
2211
2212 n = edflib_atof_nonlocalized(scratchpad);
2213 if(n<1)
2214 {
2215 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2216 free(edf_hdr);
2217 free(edfhdr->edfparam);
2218 free(edfhdr);
2219 return NULL;
2220 }
2221 edfhdr->edfparam[i].smp_per_record = n;
2222 edfhdr->recordsize += n;
2223 }
2224
2225 if(edfhdr->bdf)
2226 {
2227 edfhdr->recordsize *= 3;
2228
2229 if(edfhdr->recordsize > (15 * 1024 * 1024))
2230 {
2231 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2232 free(edf_hdr);
2233 free(edfhdr->edfparam);
2234 free(edfhdr);
2235 return NULL;
2236 }
2237 }
2238 else
2239 {
2240 edfhdr->recordsize *= 2;
2241
2242 if(edfhdr->recordsize > (10 * 1024 * 1024))
2243 {
2244 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2245 free(edf_hdr);
2246 free(edfhdr->edfparam);
2247 free(edfhdr);
2248 return NULL;
2249 }
2250 }
2251
2252 /**************************** RESERVED FIELDS *************************************/
2253
2254 for(i=0; i<edfhdr->edfsignals; i++)
2255 {
2256 strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 224) + (i * 32), 32);
2257 for(j=0; j<32; j++)
2258 {
2259 if((scratchpad[j]<32)||(scratchpad[j]>126))
2260 {
2261 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2262 free(edf_hdr);
2263 free(edfhdr->edfparam);
2264 free(edfhdr);
2265 return NULL;
2266 }
2267 }
2268 strncpy(edfhdr->edfparam[i].reserved, edf_hdr + 256 + (edfhdr->edfsignals * 224) + (i * 32), 32);
2269 edfhdr->edfparam[i].reserved[32] = 0;
2270 }
2271
2272 /********************* EDF+ PATIENTNAME *********************************************/
2273
2274 if(edfhdr->edfplus || edfhdr->bdfplus)
2275 {
2276 error = 0;
2277 dotposition = 0;
2278 strncpy(scratchpad, edf_hdr + 8, 80);
2279 scratchpad[80] = 0;
2280 for(i=0; i<80; i++)
2281 {
2282 if(scratchpad[i]==' ')
2283 {
2284 dotposition = i;
2285 break;
2286 }
2287 }
2288 dotposition++;
2289 if((dotposition>73)||(dotposition<2)) error = 1;
2290 if(scratchpad[dotposition + 2]!='X')
2291 {
2292 if(dotposition>65) error = 1;
2293 }
2294 if((scratchpad[dotposition]!='M')&&(scratchpad[dotposition]!='F')&&(scratchpad[dotposition]!='X')) error = 1;
2295 dotposition++;
2296 if(scratchpad[dotposition]!=' ') error = 1;
2297 if(scratchpad[dotposition + 1]=='X')
2298 {
2299 if(scratchpad[dotposition + 2]!=' ') error = 1;
2300 if(scratchpad[dotposition + 3]==' ') error = 1;
2301 }
2302 else
2303 {
2304 if(scratchpad[dotposition + 12]!=' ') error = 1;
2305 if(scratchpad[dotposition + 13]==' ') error = 1;
2306 dotposition++;
2307 strncpy(scratchpad2, scratchpad + dotposition, 11);
2308 scratchpad2[11] = 0;
2309 if((scratchpad2[2]!='-')||(scratchpad2[6]!='-')) error = 1;
2310 scratchpad2[2] = 0;
2311 scratchpad2[6] = 0;
2312 if((scratchpad2[0]<48)||(scratchpad2[0]>57)) error = 1;
2313 if((scratchpad2[1]<48)||(scratchpad2[1]>57)) error = 1;
2314 if((scratchpad2[7]<48)||(scratchpad2[7]>57)) error = 1;
2315 if((scratchpad2[8]<48)||(scratchpad2[8]>57)) error = 1;
2316 if((scratchpad2[9]<48)||(scratchpad2[9]>57)) error = 1;
2317 if((scratchpad2[10]<48)||(scratchpad2[10]>57)) error = 1;
2318 if((edflib_atof_nonlocalized(scratchpad2)<1)||(edflib_atof_nonlocalized(scratchpad2)>31)) error = 1;
2319 if(strcmp(scratchpad2 + 3, "JAN"))
2320 if(strcmp(scratchpad2 + 3, "FEB"))
2321 if(strcmp(scratchpad2 + 3, "MAR"))
2322 if(strcmp(scratchpad2 + 3, "APR"))
2323 if(strcmp(scratchpad2 + 3, "MAY"))
2324 if(strcmp(scratchpad2 + 3, "JUN"))
2325 if(strcmp(scratchpad2 + 3, "JUL"))
2326 if(strcmp(scratchpad2 + 3, "AUG"))
2327 if(strcmp(scratchpad2 + 3, "SEP"))
2328 if(strcmp(scratchpad2 + 3, "OCT"))
2329 if(strcmp(scratchpad2 + 3, "NOV"))
2330 if(strcmp(scratchpad2 + 3, "DEC"))
2331 error = 1;
2332 }
2333
2334 if(error)
2335 {
2336 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2337 free(edf_hdr);
2338 free(edfhdr->edfparam);
2339 free(edfhdr);
2340 return NULL;
2341 }
2342
2343 p = 0;
2344 if(edfhdr->patient[p]=='X')
2345 {
2346 edfhdr->plus_patientcode[0] = 0;
2347 p += 2;
2348 }
2349 else
2350 {
2351 for(i=0; i<(80-p); i++)
2352 {
2353 if(edfhdr->patient[i+p]==' ')
2354 {
2355 break;
2356 }
2357 edfhdr->plus_patientcode[i] = edfhdr->patient[i+p];
2358 if(edfhdr->plus_patientcode[i]=='_') edfhdr->plus_patientcode[i] = ' ';
2359 }
2360 edfhdr->plus_patientcode[i] = 0;
2361 p += i + 1;
2362 }
2363
2364 if(edfhdr->patient[p]=='M')
2365 {
2366 edflib_strlcpy(edfhdr->plus_gender, "Male", 16);
2367 }
2368 if(edfhdr->patient[p]=='F')
2369 {
2370 edflib_strlcpy(edfhdr->plus_gender, "Female", 16);
2371 }
2372 if(edfhdr->patient[p]=='X')
2373 {
2374 edfhdr->plus_gender[0] = 0;
2375 }
2376 for(i=0; i<(80-p);i++)
2377 {
2378 if(edfhdr->patient[i+p]==' ')
2379 {
2380 break;
2381 }
2382 }
2383 p += i + 1;
2384
2385 if(edfhdr->patient[p]=='X')
2386 {
2387 edfhdr->plus_birthdate[0] = 0;
2388 p += 2;
2389 }
2390 else
2391 {
2392 for(i=0; i<(80-p); i++)
2393 {
2394 if(edfhdr->patient[i+p]==' ')
2395 {
2396 break;
2397 }
2398 edfhdr->plus_birthdate[i] = edfhdr->patient[i+p];
2399 }
2400 edfhdr->plus_birthdate[2] = ' ';
2401 edfhdr->plus_birthdate[3] += 32;
2402 edfhdr->plus_birthdate[4] += 32;
2403 edfhdr->plus_birthdate[5] += 32;
2404 edfhdr->plus_birthdate[6] = ' ';
2405 edfhdr->plus_birthdate[11] = 0;
2406 p += i + 1;
2407 }
2408
2409 for(i=0; i<(80-p);i++)
2410 {
2411 if(edfhdr->patient[i+p]==' ')
2412 {
2413 break;
2414 }
2415 edfhdr->plus_patient_name[i] = edfhdr->patient[i+p];
2416 if(edfhdr->plus_patient_name[i]=='_') edfhdr->plus_patient_name[i] = ' ';
2417 }
2418 edfhdr->plus_patient_name[i] = 0;
2419 p += i + 1;
2420
2421 for(i=0; i<(80-p);i++)
2422 {
2423 edfhdr->plus_patient_additional[i] = edfhdr->patient[i+p];
2424 }
2425 edfhdr->plus_patient_additional[i] = 0;
2426 p += i + 1;
2427 }
2428
2429 /********************* EDF+ RECORDINGFIELD *********************************************/
2430
2431 if(edfhdr->edfplus || edfhdr->bdfplus)
2432 {
2433 error = 0;
2434 strncpy(scratchpad, edf_hdr + 88, 80);
2435 scratchpad[80] = 0;
2436 if(strncmp(scratchpad, "Startdate ", 10)) error = 1;
2437 if(scratchpad[10]=='X')
2438 {
2439 if(scratchpad[11]!=' ') error = 1;
2440 if(scratchpad[12]==' ') error = 1;
2441 p = 12;
2442 }
2443 else
2444 {
2445 if(scratchpad[21]!=' ') error = 1;
2446 if(scratchpad[22]==' ') error = 1;
2447 p = 22;
2448 strncpy(scratchpad2, scratchpad + 10, 11);
2449 scratchpad2[11] = 0;
2450 if((scratchpad2[2]!='-')||(scratchpad2[6]!='-')) error = 1;
2451 scratchpad2[2] = 0;
2452 scratchpad2[6] = 0;
2453 if((scratchpad2[0]<48)||(scratchpad2[0]>57)) error = 1;
2454 if((scratchpad2[1]<48)||(scratchpad2[1]>57)) error = 1;
2455 if((scratchpad2[7]<48)||(scratchpad2[7]>57)) error = 1;
2456 if((scratchpad2[8]<48)||(scratchpad2[8]>57)) error = 1;
2457 if((scratchpad2[9]<48)||(scratchpad2[9]>57)) error = 1;
2458 if((scratchpad2[10]<48)||(scratchpad2[10]>57)) error = 1;
2459 if((edflib_atof_nonlocalized(scratchpad2)<1)||(edflib_atof_nonlocalized(scratchpad2)>31)) error = 1;
2460 r = 0;
2461 if(!strcmp(scratchpad2 + 3, "JAN")) r = 1;
2462 else if(!strcmp(scratchpad2 + 3, "FEB")) r = 2;
2463 else if(!strcmp(scratchpad2 + 3, "MAR")) r = 3;
2464 else if(!strcmp(scratchpad2 + 3, "APR")) r = 4;
2465 else if(!strcmp(scratchpad2 + 3, "MAY")) r = 5;
2466 else if(!strcmp(scratchpad2 + 3, "JUN")) r = 6;
2467 else if(!strcmp(scratchpad2 + 3, "JUL")) r = 7;
2468 else if(!strcmp(scratchpad2 + 3, "AUG")) r = 8;
2469 else if(!strcmp(scratchpad2 + 3, "SEP")) r = 9;
2470 else if(!strcmp(scratchpad2 + 3, "OCT")) r = 10;
2471 else if(!strcmp(scratchpad2 + 3, "NOV")) r = 11;
2472 else if(!strcmp(scratchpad2 + 3, "DEC")) r = 12;
2473 else error = 1;
2474 }
2475
2476 n = 0;
2477 for(i=p; i<80; i++)
2478 {
2479 if(i>78)
2480 {
2481 error = 1;
2482 break;
2483 }
2484 if(scratchpad[i]==' ')
2485 {
2486 n++;
2487 if(scratchpad[i + 1]==' ')
2488 {
2489 error = 1;
2490 break;
2491 }
2492 }
2493 if(n>1) break;
2494 }
2495
2496 if(error)
2497 {
2498 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2499 free(edf_hdr);
2500 free(edfhdr->edfparam);
2501 free(edfhdr);
2502 return NULL;
2503 }
2504
2505 if(edf_hdr[98]!='X')
2506 {
2507 error = 0;
2508
2509 strncpy(scratchpad, edf_hdr + 168, 8);
2510 scratchpad[2] = 0;
2511 scratchpad[5] = 0;
2512 scratchpad[8] = 0;
2513
2514 if(edflib_atof_nonlocalized(scratchpad)!=edflib_atof_nonlocalized(scratchpad2)) error = 1;
2515 if(edflib_atof_nonlocalized(scratchpad+3)!=r) error = 1;
2516 if(edflib_atof_nonlocalized(scratchpad+6)!=edflib_atof_nonlocalized(scratchpad2+9)) error = 1;
2517 if(error)
2518 {
2519 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2520 free(edf_hdr);
2521 free(edfhdr->edfparam);
2522 free(edfhdr);
2523 return NULL;
2524 }
2525
2526 if(edfhdr->startdate_year != edflib_atof_nonlocalized(scratchpad2 + 7))
2527 {
2528 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2529 free(edf_hdr);
2530 free(edfhdr->edfparam);
2531 free(edfhdr);
2532 return NULL;
2533 }
2534 }
2535
2536 p = 10;
2537 for(i=0; i<(80-p); i++)
2538 {
2539 if(edfhdr->recording[i+p]==' ')
2540 {
2541 break;
2542 }
2543 edfhdr->plus_startdate[i] = edfhdr->recording[i+p];
2544 }
2545 edfhdr->plus_startdate[2] = ' ';
2546 edfhdr->plus_startdate[3] += 32;
2547 edfhdr->plus_startdate[4] += 32;
2548 edfhdr->plus_startdate[5] += 32;
2549 edfhdr->plus_startdate[6] = ' ';
2550 edfhdr->plus_startdate[11] = 0;
2551 p += i + 1;
2552
2553 if(edfhdr->recording[p]=='X')
2554 {
2555 edfhdr->plus_admincode[0] = 0;
2556 p += 2;
2557 }
2558 else
2559 {
2560 for(i=0; i<(80-p); i++)
2561 {
2562 if(edfhdr->recording[i+p]==' ')
2563 {
2564 break;
2565 }
2566 edfhdr->plus_admincode[i] = edfhdr->recording[i+p];
2567 if(edfhdr->plus_admincode[i]=='_') edfhdr->plus_admincode[i] = ' ';
2568 }
2569 edfhdr->plus_admincode[i] = 0;
2570 p += i + 1;
2571 }
2572
2573 if(edfhdr->recording[p]=='X')
2574 {
2575 edfhdr->plus_technician[0] = 0;
2576 p += 2;
2577 }
2578 else
2579 {
2580 for(i=0; i<(80-p); i++)
2581 {
2582 if(edfhdr->recording[i+p]==' ')
2583 {
2584 break;
2585 }
2586 edfhdr->plus_technician[i] = edfhdr->recording[i+p];
2587 if(edfhdr->plus_technician[i]=='_') edfhdr->plus_technician[i] = ' ';
2588 }
2589 edfhdr->plus_technician[i] = 0;
2590 p += i + 1;
2591 }
2592
2593 if(edfhdr->recording[p]=='X')
2594 {
2595 edfhdr->plus_equipment[0] = 0;
2596 p += 2;
2597 }
2598 else
2599 {
2600 for(i=0; i<(80-p); i++)
2601 {
2602 if(edfhdr->recording[i+p]==' ')
2603 {
2604 break;
2605 }
2606 edfhdr->plus_equipment[i] = edfhdr->recording[i+p];
2607 if(edfhdr->plus_equipment[i]=='_') edfhdr->plus_equipment[i] = ' ';
2608 }
2609 edfhdr->plus_equipment[i] = 0;
2610 p += i + 1;
2611 }
2612
2613 for(i=0; i<(80-p);i++)
2614 {
2615 edfhdr->plus_recording_additional[i] = edfhdr->recording[i+p];
2616 }
2617 edfhdr->plus_recording_additional[i] = 0;
2618 p += i + 1;
2619 }
2620
2621 /********************* FILESIZE *********************************************/
2622
2623 edfhdr->hdrsize = edfhdr->edfsignals * 256 + 256;
2624
2625 fseeko(inputfile, 0LL, SEEK_END);
2626 if(ftello(inputfile)!=(edfhdr->recordsize * edfhdr->datarecords + edfhdr->hdrsize))
2627 {
2628 *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS;
2629 free(edf_hdr);
2630 free(edfhdr->edfparam);
2631 free(edfhdr);
2632 return NULL;
2633 }
2634
2635 n = 0;
2636
2637 for(i=0; i<edfhdr->edfsignals; i++)
2638 {
2639 edfhdr->edfparam[i].buf_offset = n;
2640 if(edfhdr->bdf) n += edfhdr->edfparam[i].smp_per_record * 3;
2641 else n += edfhdr->edfparam[i].smp_per_record * 2;
2642
2643 edfhdr->edfparam[i].bitvalue = (edfhdr->edfparam[i].phys_max - edfhdr->edfparam[i].phys_min) / (edfhdr->edfparam[i].dig_max - edfhdr->edfparam[i].dig_min);
2644 edfhdr->edfparam[i].offset = edfhdr->edfparam[i].phys_max / edfhdr->edfparam[i].bitvalue - edfhdr->edfparam[i].dig_max;
2645 }
2646
2647 edfhdr->file_hdl = inputfile;
2648
2649 free(edf_hdr);
2650
2651 return edfhdr;
2652 }
2653
2654
2655
2656
edflib_is_integer_number(char * str)2657 static int edflib_is_integer_number(char *str)
2658 {
2659 int i=0, l, hasspace = 0, hassign=0, digit=0;
2660
2661 l = strlen(str);
2662
2663 if(!l) return 1;
2664
2665 if((str[0]=='+')||(str[0]=='-'))
2666 {
2667 hassign++;
2668 i++;
2669 }
2670
2671 for(; i<l; i++)
2672 {
2673 if(str[i]==' ')
2674 {
2675 if(!digit)
2676 {
2677 return 1;
2678 }
2679 hasspace++;
2680 }
2681 else
2682 {
2683 if((str[i]<48)||(str[i]>57))
2684 {
2685 return 1;
2686 }
2687 else
2688 {
2689 if(hasspace)
2690 {
2691 return 1;
2692 }
2693 digit++;
2694 }
2695 }
2696 }
2697
2698 if(digit) return 0;
2699 else return 1;
2700 }
2701
2702
2703
edflib_is_number(char * str)2704 static int edflib_is_number(char *str)
2705 {
2706 int i=0, l, hasspace = 0, hassign=0, digit=0, hasdot=0, hasexp=0;
2707
2708 l = strlen(str);
2709
2710 if(!l) return 1;
2711
2712 if((str[0]=='+')||(str[0]=='-'))
2713 {
2714 hassign++;
2715 i++;
2716 }
2717
2718 for(; i<l; i++)
2719 {
2720 if((str[i]=='e')||(str[i]=='E'))
2721 {
2722 if((!digit)||hasexp)
2723 {
2724 return 1;
2725 }
2726 hasexp++;
2727 hassign = 0;
2728 digit = 0;
2729
2730 break;
2731 }
2732
2733 if(str[i]==' ')
2734 {
2735 if(!digit)
2736 {
2737 return 1;
2738 }
2739 hasspace++;
2740 }
2741 else
2742 {
2743 if(((str[i]<48)||(str[i]>57))&&str[i]!='.')
2744 {
2745 return 1;
2746 }
2747 else
2748 {
2749 if(hasspace)
2750 {
2751 return 1;
2752 }
2753 if(str[i]=='.')
2754 {
2755 if(hasdot) return 1;
2756 hasdot++;
2757 }
2758 else
2759 {
2760 digit++;
2761 }
2762 }
2763 }
2764 }
2765
2766 if(hasexp)
2767 {
2768 if(++i==l)
2769 {
2770 return 1;
2771 }
2772
2773 if((str[i]=='+')||(str[i]=='-'))
2774 {
2775 hassign++;
2776 i++;
2777 }
2778
2779 for(; i<l; i++)
2780 {
2781 if(str[i]==' ')
2782 {
2783 if(!digit)
2784 {
2785 return 1;
2786 }
2787 hasspace++;
2788 }
2789 else
2790 {
2791 if((str[i]<48)||(str[i]>57))
2792 {
2793 return 1;
2794 }
2795 else
2796 {
2797 if(hasspace)
2798 {
2799 return 1;
2800 }
2801
2802 digit++;
2803 }
2804 }
2805 }
2806 }
2807
2808 if(digit) return 0;
2809 else return 1;
2810 }
2811
2812
edflib_get_long_duration(char * str)2813 static long long edflib_get_long_duration(char *str)
2814 {
2815 int i, len=8, hasdot=0, dotposition=0;
2816
2817 long long value=0, radix;
2818
2819 if((str[0] == '+') || (str[0] == '-'))
2820 {
2821 for(i=0; i<7; i++)
2822 {
2823 str[i] = str[i+1];
2824 }
2825
2826 str[7] = ' ';
2827 }
2828
2829 for(i=0; i<8; i++)
2830 {
2831 if(str[i]==' ')
2832 {
2833 len = i;
2834 break;
2835 }
2836 }
2837
2838 for(i=0; i<len; i++)
2839 {
2840 if(str[i]=='.')
2841 {
2842 hasdot = 1;
2843 dotposition = i;
2844 break;
2845 }
2846 }
2847
2848 if(hasdot)
2849 {
2850 radix = EDFLIB_TIME_DIMENSION;
2851
2852 for(i=dotposition-1; i>=0; i--)
2853 {
2854 value += ((long long)(str[i] - 48)) * radix;
2855 radix *= 10;
2856 }
2857
2858 radix = EDFLIB_TIME_DIMENSION / 10;
2859
2860 for(i=dotposition+1; i<len; i++)
2861 {
2862 value += ((long long)(str[i] - 48)) * radix;
2863 radix /= 10;
2864 }
2865 }
2866 else
2867 {
2868 radix = EDFLIB_TIME_DIMENSION;
2869
2870 for(i=len-1; i>=0; i--)
2871 {
2872 value += ((long long)(str[i] - 48)) * radix;
2873 radix *= 10;
2874 }
2875 }
2876
2877 return value;
2878 }
2879
2880
edflib_version(void)2881 int edflib_version(void)
2882 {
2883 return EDFLIB_VERSION;
2884 }
2885
2886
edflib_get_annotations(struct edfhdrblock * edfhdr,int hdl,int read_annotations_mode)2887 static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_annotations_mode)
2888 {
2889 int i, j, k, p, r=0, n,
2890 edfsignals,
2891 datarecords,
2892 recordsize,
2893 discontinuous,
2894 *annot_ch,
2895 nr_annot_chns,
2896 max,
2897 onset,
2898 duration,
2899 duration_start,
2900 zero,
2901 max_tal_ln,
2902 error,
2903 annots_in_record,
2904 annots_in_tal,
2905 samplesize=2;
2906
2907 char *scratchpad,
2908 *cnv_buf,
2909 *time_in_txt,
2910 *duration_in_txt;
2911
2912
2913 long long data_record_duration,
2914 elapsedtime,
2915 time_tmp=0;
2916
2917 FILE *inputfile;
2918
2919 struct edfparamblock *edfparam;
2920
2921 struct edf_annotationblock *new_annotation=NULL,
2922 *malloc_list;
2923
2924 inputfile = edfhdr->file_hdl;
2925 edfsignals = edfhdr->edfsignals;
2926 recordsize = edfhdr->recordsize;
2927 edfparam = edfhdr->edfparam;
2928 nr_annot_chns = edfhdr->nr_annot_chns;
2929 datarecords = edfhdr->datarecords;
2930 data_record_duration = edfhdr->long_data_record_duration;
2931 discontinuous = edfhdr->discontinuous;
2932 annot_ch = edfhdr->annot_ch;
2933
2934 if(edfhdr->edfplus)
2935 {
2936 samplesize = 2;
2937 }
2938 if(edfhdr->bdfplus)
2939 {
2940 samplesize = 3;
2941 }
2942
2943 cnv_buf = (char *)calloc(1, recordsize);
2944 if(cnv_buf==NULL)
2945 {
2946 return 1;
2947 }
2948
2949 max_tal_ln = 0;
2950
2951 for(i=0; i<nr_annot_chns; i++)
2952 {
2953 if(max_tal_ln<edfparam[annot_ch[i]].smp_per_record * samplesize) max_tal_ln = edfparam[annot_ch[i]].smp_per_record * samplesize;
2954 }
2955
2956 if(max_tal_ln<128) max_tal_ln = 128;
2957
2958 scratchpad = (char *)calloc(1, max_tal_ln + 3);
2959 if(scratchpad==NULL)
2960 {
2961 free(cnv_buf);
2962 return 1;
2963 }
2964
2965 time_in_txt = (char *)calloc(1, max_tal_ln + 3);
2966 if(time_in_txt==NULL)
2967 {
2968 free(cnv_buf);
2969 free(scratchpad);
2970 return 1;
2971 }
2972
2973 duration_in_txt = (char *)calloc(1, max_tal_ln + 3);
2974 if(duration_in_txt==NULL)
2975 {
2976 free(cnv_buf);
2977 free(scratchpad);
2978 free(time_in_txt);
2979 return 1;
2980 }
2981
2982 if(fseeko(inputfile, (long long)((edfsignals + 1) * 256), SEEK_SET))
2983 {
2984 free(cnv_buf);
2985 free(scratchpad);
2986 free(time_in_txt);
2987 free(duration_in_txt);
2988 return 2;
2989 }
2990
2991 elapsedtime = 0;
2992
2993 for(i=0; i<datarecords; i++)
2994 {
2995 if(fread(cnv_buf, recordsize, 1, inputfile)!=1)
2996 {
2997 free(cnv_buf);
2998 free(scratchpad);
2999 free(time_in_txt);
3000 free(duration_in_txt);
3001 return 2;
3002 }
3003
3004
3005 /************** process annotationsignals (if any) **************/
3006
3007 error = 0;
3008
3009 for(r=0; r<nr_annot_chns; r++)
3010 {
3011 n = 0;
3012 zero = 0;
3013 onset = 0;
3014 duration = 0;
3015 duration_start = 0;
3016 scratchpad[0] = 0;
3017 annots_in_tal = 0;
3018 annots_in_record = 0;
3019
3020 p = edfparam[annot_ch[r]].buf_offset;
3021 max = edfparam[annot_ch[r]].smp_per_record * samplesize;
3022
3023 /************** process one annotation signal ****************/
3024
3025 if(cnv_buf[p + max - 1]!=0)
3026 {
3027 error = 5;
3028 goto END;
3029 }
3030
3031 if(!r) /* if it's the first annotation signal, then check */
3032 { /* the timekeeping annotation */
3033 error = 1;
3034
3035 for(k=0; k<(max-2); k++)
3036 {
3037 scratchpad[k] = cnv_buf[p + k];
3038
3039 if(scratchpad[k]==20)
3040 {
3041 if(cnv_buf[p + k + 1]!=20)
3042 {
3043 error = 6;
3044 goto END;
3045 }
3046 scratchpad[k] = 0;
3047 if(edflib_is_onset_number(scratchpad))
3048 {
3049 error = 36;
3050 goto END;
3051 }
3052 else
3053 {
3054 time_tmp = edflib_get_long_time(scratchpad);
3055 if(i)
3056 {
3057 if(discontinuous)
3058 {
3059 if((time_tmp-elapsedtime)<data_record_duration)
3060 {
3061 error = 4;
3062 goto END;
3063 }
3064 }
3065 else
3066 {
3067 if((time_tmp-elapsedtime)!=data_record_duration)
3068 {
3069 error = 3;
3070 goto END;
3071 }
3072 }
3073 }
3074 else
3075 {
3076 if((time_tmp>=EDFLIB_TIME_DIMENSION) || (time_tmp<0LL))
3077 {
3078 error = 2;
3079 goto END;
3080 }
3081 else
3082 {
3083 edfhdr->starttime_offset = time_tmp;
3084 if(read_annotations_mode==EDFLIB_DO_NOT_READ_ANNOTATIONS)
3085 {
3086 error = 0;
3087 goto END_OUT;
3088 }
3089 }
3090 }
3091 elapsedtime = time_tmp;
3092 error = 0;
3093 break;
3094 }
3095 }
3096 }
3097 }
3098
3099 for(k=0; k<max; k++)
3100 {
3101 scratchpad[n] = cnv_buf[p + k];
3102
3103 if(!scratchpad[n])
3104 {
3105 if(!zero)
3106 {
3107 if(k)
3108 {
3109 if(cnv_buf[p + k - 1]!=20)
3110 {
3111 error = 33;
3112 goto END;
3113 }
3114 }
3115 n = 0;
3116 onset = 0;
3117 duration = 0;
3118 duration_start = 0;
3119 scratchpad[0] = 0;
3120 annots_in_tal = 0;
3121 }
3122 zero++;
3123 continue;
3124 }
3125 if(zero>1)
3126 {
3127 error = 34;
3128 goto END;
3129 }
3130 zero = 0;
3131
3132 if((scratchpad[n]==20)||(scratchpad[n]==21))
3133 {
3134 if(scratchpad[n]==21)
3135 {
3136 if(duration||duration_start||onset||annots_in_tal)
3137 { /* it's not allowed to have multiple duration fields */
3138 error = 35; /* in one TAL or to have a duration field which is */
3139 goto END; /* not immediately behind the onsetfield */
3140 }
3141 duration_start = 1;
3142 }
3143
3144 if((scratchpad[n]==20)&&onset&&(!duration_start))
3145 {
3146 if(r||annots_in_record)
3147 {
3148 if(n >= 0)
3149 {
3150 if(edfhdr->annots_in_file >= edfhdr->annotlist_sz)
3151 {
3152 malloc_list = (struct edf_annotationblock *)realloc(annotationslist[hdl],
3153 sizeof(struct edf_annotationblock) * (edfhdr->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ));
3154 if(malloc_list==NULL)
3155 {
3156 free(cnv_buf);
3157 free(scratchpad);
3158 free(time_in_txt);
3159 free(duration_in_txt);
3160 return -1;
3161 }
3162
3163 annotationslist[hdl] = malloc_list;
3164
3165 edfhdr->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ;
3166 }
3167
3168 new_annotation = annotationslist[hdl] + edfhdr->annots_in_file;
3169
3170 new_annotation->annotation[0] = 0;
3171
3172 if(duration) edflib_strlcpy(new_annotation->duration, duration_in_txt, 16);
3173 else new_annotation->duration[0] = 0;
3174
3175 for(j=0; j<n; j++)
3176 {
3177 if(j==EDFLIB_MAX_ANNOTATION_LEN) break;
3178 new_annotation->annotation[j] = scratchpad[j];
3179 }
3180 new_annotation->annotation[j] = 0;
3181
3182 new_annotation->onset = edflib_get_long_time(time_in_txt);
3183
3184 new_annotation->onset -= edfhdr->starttime_offset;
3185
3186 edfhdr->annots_in_file++;
3187
3188 if(read_annotations_mode==EDFLIB_READ_ANNOTATIONS)
3189 {
3190 if(!(strncmp(new_annotation->annotation, "Recording ends", 14)))
3191 {
3192 if(nr_annot_chns==1)
3193 {
3194 goto END;
3195 }
3196 }
3197 }
3198 }
3199 }
3200
3201 annots_in_tal++;
3202 annots_in_record++;
3203 n = 0;
3204 continue;
3205 }
3206
3207 if(!onset)
3208 {
3209 scratchpad[n] = 0;
3210 if(edflib_is_onset_number(scratchpad))
3211 {
3212 error = 36;
3213 goto END;
3214 }
3215 onset = 1;
3216 n = 0;
3217 edflib_strlcpy(time_in_txt, scratchpad, max_tal_ln + 3);
3218 continue;
3219 }
3220
3221 if(duration_start)
3222 {
3223 scratchpad[n] = 0;
3224 if(edflib_is_duration_number(scratchpad))
3225 {
3226 error = 37;
3227 goto END;
3228 }
3229
3230 for(j=0; j<n; j++)
3231 {
3232 if(j==15) break;
3233 duration_in_txt[j] = scratchpad[j];
3234 if((duration_in_txt[j]<32)||(duration_in_txt[j]>126))
3235 {
3236 duration_in_txt[j] = '.';
3237 }
3238 }
3239 duration_in_txt[j] = 0;
3240
3241 duration = 1;
3242 duration_start = 0;
3243 n = 0;
3244 continue;
3245 }
3246 }
3247
3248 n++;
3249 }
3250
3251 END:
3252
3253 /****************** end ************************/
3254
3255 if(error)
3256 {
3257 free(cnv_buf);
3258 free(scratchpad);
3259 free(time_in_txt);
3260 free(duration_in_txt);
3261 return 9;
3262 }
3263 }
3264 }
3265
3266 END_OUT:
3267
3268 free(cnv_buf);
3269 free(scratchpad);
3270 free(time_in_txt);
3271 free(duration_in_txt);
3272
3273 return 0;
3274 }
3275
3276
edflib_is_duration_number(char * str)3277 static int edflib_is_duration_number(char *str)
3278 {
3279 int i, l, hasdot = 0;
3280
3281 l = strlen(str);
3282
3283 if(!l) return 1;
3284
3285 if((str[0] == '.')||(str[l-1] == '.')) return 1;
3286
3287 for(i=0; i<l; i++)
3288 {
3289 if(str[i]=='.')
3290 {
3291 if(hasdot) return 1;
3292 hasdot++;
3293 }
3294 else
3295 {
3296 if((str[i]<48)||(str[i]>57)) return 1;
3297 }
3298 }
3299
3300 return 0;
3301 }
3302
3303
3304
edflib_is_onset_number(char * str)3305 static int edflib_is_onset_number(char *str)
3306 {
3307 int i, l, hasdot = 0;
3308
3309 l = strlen(str);
3310
3311 if(l<2) return 1;
3312
3313 if((str[0]!='+')&&(str[0]!='-')) return 1;
3314
3315 if((str[1] == '.')||(str[l-1] == '.')) return 1;
3316
3317 for(i=1; i<l; i++)
3318 {
3319 if(str[i]=='.')
3320 {
3321 if(hasdot) return 1;
3322 hasdot++;
3323 }
3324 else
3325 {
3326 if((str[i]<48)||(str[i]>57)) return 1;
3327 }
3328 }
3329
3330 return 0;
3331 }
3332
3333
3334
edflib_get_long_time(char * str)3335 static long long edflib_get_long_time(char *str)
3336 {
3337 int i, len, hasdot=0, dotposition=0, neg=0;
3338
3339 long long value=0, radix;
3340
3341 if(str[0] == '+')
3342 {
3343 str++;
3344 }
3345 else if(str[0] == '-')
3346 {
3347 neg = 1;
3348 str++;
3349 }
3350
3351 len = strlen(str);
3352
3353 for(i=0; i<len; i++)
3354 {
3355 if(str[i]=='.')
3356 {
3357 hasdot = 1;
3358 dotposition = i;
3359 break;
3360 }
3361 }
3362
3363 if(hasdot)
3364 {
3365 radix = EDFLIB_TIME_DIMENSION;
3366
3367 for(i=dotposition-1; i>=0; i--)
3368 {
3369 value += ((long long)(str[i] - 48)) * radix;
3370 radix *= 10;
3371 }
3372
3373 radix = EDFLIB_TIME_DIMENSION / 10;
3374
3375 for(i=dotposition+1; i<len; i++)
3376 {
3377 value += ((long long)(str[i] - 48)) * radix;
3378 radix /= 10;
3379 }
3380 }
3381 else
3382 {
3383 radix = EDFLIB_TIME_DIMENSION;
3384
3385 for(i=len-1; i>=0; i--)
3386 {
3387 value += ((long long)(str[i] - 48)) * radix;
3388 radix *= 10;
3389 }
3390 }
3391
3392 if(neg) value = -value;
3393
3394 return value;
3395 }
3396
3397
edflib_latin1_to_ascii(char * str,int len)3398 static void edflib_latin1_to_ascii(char *str, int len)
3399 {
3400 /* ISO 8859-1 except for characters 0x80 to 0x9f which are taken from the extension CP-1252 */
3401
3402 int i, value;
3403
3404 const char conv_table[]=".E.,F\".++^.S<E.Z..`\'\"\".--~.s>e.zY.i....|....<...-....\'u.....>...?AAAAAAECEEEEIIIIDNOOOOOxOUUUUYtsaaaaaaeceeeeiiiidnooooo:0uuuuyty";
3405
3406 for(i=0; i<len; i++)
3407 {
3408 value = *((unsigned char *)(str + i));
3409
3410 if((value>31)&&(value<127))
3411 {
3412 continue;
3413 }
3414
3415 if(value < 32)
3416 {
3417 str[i] = '.';
3418
3419 continue;
3420 }
3421
3422 str[i] = conv_table[value - 127];
3423 }
3424 }
3425
3426
edflib_latin12utf8(char * latin1_str,int len)3427 static void edflib_latin12utf8(char *latin1_str, int len)
3428 {
3429 int i, j;
3430
3431 unsigned char *str, tmp_str[512];
3432
3433
3434 str = (unsigned char *)latin1_str;
3435
3436 j = 0;
3437
3438 for(i=0; i<len; i++)
3439 {
3440 if(str[i]==0)
3441 {
3442 tmp_str[j] = 0;
3443
3444 break;
3445 }
3446
3447 tmp_str[j] = str[i];
3448
3449 if(str[i]<32) tmp_str[j] = '.';
3450
3451 if((str[i]>126)&&(str[i]<160)) tmp_str[j] = '.';
3452
3453 if(str[i]>159)
3454 {
3455 if((len-j)<2)
3456 {
3457 tmp_str[j] = ' ';
3458 }
3459 else
3460 {
3461 tmp_str[j] = 192 + (str[i]>>6);
3462 j++;
3463 tmp_str[j] = 128 + (str[i]&63);
3464 }
3465 }
3466
3467 j++;
3468
3469 if(j>=len) break;
3470 }
3471
3472 for(i=0; i<len; i++)
3473 {
3474 str[i] = tmp_str[i];
3475 }
3476 }
3477
3478
edfopen_file_writeonly_with_params(const char * path,int filetype,int number_of_signals,int samplefrequency,double phys_max_min,const char * phys_dim)3479 int edfopen_file_writeonly_with_params(const char *path, int filetype, int number_of_signals, int samplefrequency, double phys_max_min, const char *phys_dim)
3480 {
3481 int i, handle;
3482
3483 char str[32]="";
3484
3485 handle = edfopen_file_writeonly(path, filetype, number_of_signals);
3486 if(handle < 0)
3487 {
3488 return handle;
3489 }
3490
3491 for(i=0; i<number_of_signals; i++)
3492 {
3493 if(edf_set_samplefrequency(handle, i, samplefrequency))
3494 {
3495 edfclose_file(handle);
3496 return -1;
3497 }
3498
3499 if(edf_set_physical_maximum(handle, i, phys_max_min))
3500 {
3501 edfclose_file(handle);
3502 return -1;
3503 }
3504
3505 if(edf_set_physical_minimum(handle, i, -phys_max_min))
3506 {
3507 edfclose_file(handle);
3508 return -1;
3509 }
3510
3511 if(edf_set_physical_dimension(handle, i, phys_dim))
3512 {
3513 edfclose_file(handle);
3514 return -1;
3515 }
3516
3517 snprintf(str, 32, "chan. %i", i + 1);
3518
3519 if(edf_set_label(handle, i, str))
3520 {
3521 edfclose_file(handle);
3522 return -1;
3523 }
3524
3525 if(filetype == EDFLIB_FILETYPE_BDFPLUS)
3526 {
3527 if(edf_set_digital_maximum(handle, i, 8388607))
3528 {
3529 edfclose_file(handle);
3530 return -1;
3531 }
3532
3533 if(edf_set_digital_minimum(handle, i, -8388608))
3534 {
3535 edfclose_file(handle);
3536 return -1;
3537 }
3538 }
3539 else
3540 {
3541 if(edf_set_digital_maximum(handle, i, 32767))
3542 {
3543 edfclose_file(handle);
3544 return -1;
3545 }
3546
3547 if(edf_set_digital_minimum(handle, i, -32768))
3548 {
3549 edfclose_file(handle);
3550 return -1;
3551 }
3552 }
3553 }
3554
3555 return handle;
3556 }
3557
3558
edfopen_file_writeonly(const char * path,int filetype,int number_of_signals)3559 int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals)
3560 {
3561 int i, handle;
3562
3563 FILE *file;
3564
3565 struct edfhdrblock *hdr;
3566
3567
3568 if((filetype!=EDFLIB_FILETYPE_EDFPLUS)&&(filetype!=EDFLIB_FILETYPE_BDFPLUS))
3569 {
3570 return EDFLIB_FILETYPE_ERROR;
3571 }
3572
3573 if(edf_files_open>=EDFLIB_MAXFILES)
3574 {
3575 return EDFLIB_MAXFILES_REACHED;
3576 }
3577
3578 for(i=0; i<EDFLIB_MAXFILES; i++)
3579 {
3580 if(hdrlist[i]!=NULL)
3581 {
3582 if(!(strcmp(path, hdrlist[i]->path)))
3583 {
3584 return EDFLIB_FILE_ALREADY_OPENED;
3585 }
3586 }
3587 }
3588
3589 if(number_of_signals<0)
3590 {
3591 return EDFLIB_NUMBER_OF_SIGNALS_INVALID;
3592 }
3593
3594 if(number_of_signals>EDFLIB_MAXSIGNALS)
3595 {
3596 return EDFLIB_NUMBER_OF_SIGNALS_INVALID;
3597 }
3598
3599 hdr = (struct edfhdrblock *)calloc(1, sizeof(struct edfhdrblock));
3600 if(hdr==NULL)
3601 {
3602 return EDFLIB_MALLOC_ERROR;
3603 }
3604
3605 hdr->edfparam = (struct edfparamblock *)calloc(1, sizeof(struct edfparamblock) * number_of_signals);
3606 if(hdr->edfparam==NULL)
3607 {
3608 free(hdr);
3609
3610 return EDFLIB_MALLOC_ERROR;
3611 }
3612
3613 hdr->writemode = 1;
3614
3615 hdr->edfsignals = number_of_signals;
3616
3617 handle = -1;
3618
3619 for(i=0; i<EDFLIB_MAXFILES; i++)
3620 {
3621 if(hdrlist[i]==NULL)
3622 {
3623 hdrlist[i] = hdr;
3624
3625 handle = i;
3626
3627 break;
3628 }
3629 }
3630
3631 if(handle<0)
3632 {
3633 free(hdr->edfparam);
3634
3635 free(hdr);
3636
3637 return EDFLIB_MAXFILES_REACHED;
3638 }
3639
3640 write_annotationslist[handle] = NULL;
3641
3642 hdr->annotlist_sz = 0;
3643
3644 hdr->annots_in_file = 0;
3645
3646 file = fopeno(path, "wb");
3647 if(file==NULL)
3648 {
3649 free(hdr->edfparam);
3650 hdr->edfparam = NULL;
3651 free(hdr);
3652 hdr = NULL;
3653 hdrlist[handle] = NULL;
3654
3655 return EDFLIB_NO_SUCH_FILE_OR_DIRECTORY;
3656 }
3657
3658 hdr->file_hdl = file;
3659
3660 edflib_strlcpy(hdr->path, path, 1024);
3661
3662 edf_files_open++;
3663
3664 if(filetype==EDFLIB_FILETYPE_EDFPLUS)
3665 {
3666 hdr->edf = 1;
3667 hdr->edfplus = 1;
3668 }
3669
3670 if(filetype==EDFLIB_FILETYPE_BDFPLUS)
3671 {
3672 hdr->bdf = 1;
3673 hdr->bdfplus = 1;
3674 }
3675
3676 hdr->long_data_record_duration = EDFLIB_TIME_DIMENSION;
3677
3678 hdr->data_record_duration = 1.0;
3679
3680 hdr->nr_annot_chns = 1;
3681
3682 return handle;
3683 }
3684
3685
edf_set_samplefrequency(int handle,int edfsignal,int samplefrequency)3686 int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency)
3687 {
3688 if(handle<0)
3689 {
3690 return -1;
3691 }
3692
3693 if(handle>=EDFLIB_MAXFILES)
3694 {
3695 return -1;
3696 }
3697
3698 if(hdrlist[handle]==NULL)
3699 {
3700 return -1;
3701 }
3702
3703 if(!(hdrlist[handle]->writemode))
3704 {
3705 return -1;
3706 }
3707
3708 if(edfsignal<0)
3709 {
3710 return -1;
3711 }
3712
3713 if(edfsignal>=hdrlist[handle]->edfsignals)
3714 {
3715 return -1;
3716 }
3717
3718 if(samplefrequency<1)
3719 {
3720 return -1;
3721 }
3722
3723 if(hdrlist[handle]->datarecords)
3724 {
3725 return -1;
3726 }
3727
3728 hdrlist[handle]->edfparam[edfsignal].smp_per_record = samplefrequency;
3729
3730 return 0;
3731 }
3732
3733
edf_set_number_of_annotation_signals(int handle,int annot_signals)3734 int edf_set_number_of_annotation_signals(int handle, int annot_signals)
3735 {
3736 if(handle<0)
3737 {
3738 return -1;
3739 }
3740
3741 if(handle>=EDFLIB_MAXFILES)
3742 {
3743 return -1;
3744 }
3745
3746 if(hdrlist[handle]==NULL)
3747 {
3748 return -1;
3749 }
3750
3751 if(!(hdrlist[handle]->writemode))
3752 {
3753 return -1;
3754 }
3755
3756 if(hdrlist[handle]->datarecords)
3757 {
3758 return -1;
3759 }
3760
3761 if((annot_signals < 1) || (annot_signals > EDFLIB_MAX_ANNOTATION_CHANNELS))
3762 {
3763 return -1;
3764 }
3765
3766 hdrlist[handle]->nr_annot_chns = annot_signals;
3767
3768 return 0;
3769 }
3770
3771
edf_set_datarecord_duration(int handle,int duration)3772 int edf_set_datarecord_duration(int handle, int duration)
3773 {
3774 if(handle<0)
3775 {
3776 return -1;
3777 }
3778
3779 if(handle>=EDFLIB_MAXFILES)
3780 {
3781 return -1;
3782 }
3783
3784 if(hdrlist[handle]==NULL)
3785 {
3786 return -1;
3787 }
3788
3789 if(!(hdrlist[handle]->writemode))
3790 {
3791 return -1;
3792 }
3793
3794 if(hdrlist[handle]->datarecords)
3795 {
3796 return -1;
3797 }
3798
3799 if((duration < 100) || (duration > 6000000))
3800 {
3801 return -1;
3802 }
3803
3804 hdrlist[handle]->long_data_record_duration = (long long)duration * 100LL;
3805
3806 if(hdrlist[handle]->long_data_record_duration < (EDFLIB_TIME_DIMENSION * 10LL))
3807 {
3808 hdrlist[handle]->long_data_record_duration /= 10LL;
3809
3810 hdrlist[handle]->long_data_record_duration *= 10LL;
3811 }
3812 else
3813 {
3814 hdrlist[handle]->long_data_record_duration /= 100LL;
3815
3816 hdrlist[handle]->long_data_record_duration *= 100LL;
3817 }
3818
3819 hdrlist[handle]->data_record_duration = ((double)(hdrlist[handle]->long_data_record_duration)) / EDFLIB_TIME_DIMENSION;
3820
3821 return 0;
3822 }
3823
3824
edf_set_micro_datarecord_duration(int handle,int duration)3825 int edf_set_micro_datarecord_duration(int handle, int duration)
3826 {
3827 if(handle<0)
3828 {
3829 return -1;
3830 }
3831
3832 if(handle>=EDFLIB_MAXFILES)
3833 {
3834 return -1;
3835 }
3836
3837 if(hdrlist[handle]==NULL)
3838 {
3839 return -1;
3840 }
3841
3842 if(!(hdrlist[handle]->writemode))
3843 {
3844 return -1;
3845 }
3846
3847 if(hdrlist[handle]->datarecords)
3848 {
3849 return -1;
3850 }
3851
3852 if((duration < 1) || (duration > 9999))
3853 {
3854 return -1;
3855 }
3856
3857 hdrlist[handle]->long_data_record_duration = (long long)duration * 10LL;
3858
3859 hdrlist[handle]->data_record_duration = ((double)(hdrlist[handle]->long_data_record_duration)) / EDFLIB_TIME_DIMENSION;
3860
3861 return 0;
3862 }
3863
3864
edf_set_subsecond_starttime(int handle,int subsecond)3865 int edf_set_subsecond_starttime(int handle, int subsecond)
3866 {
3867 if(handle<0)
3868 {
3869 return -1;
3870 }
3871
3872 if(handle>=EDFLIB_MAXFILES)
3873 {
3874 return -1;
3875 }
3876
3877 if(hdrlist[handle]==NULL)
3878 {
3879 return -1;
3880 }
3881
3882 if(!(hdrlist[handle]->writemode))
3883 {
3884 return -1;
3885 }
3886
3887 if(hdrlist[handle]->datarecords)
3888 {
3889 return -1;
3890 }
3891
3892 if((subsecond < 0) || (subsecond > 9999999))
3893 {
3894 return -1;
3895 }
3896
3897 hdrlist[handle]->starttime_offset = (long long)subsecond;
3898
3899 return 0;
3900 }
3901
3902
edfwrite_digital_short_samples(int handle,short * buf)3903 int edfwrite_digital_short_samples(int handle, short *buf)
3904 {
3905 int i,
3906 error,
3907 sf,
3908 digmax,
3909 digmin,
3910 edfsignal,
3911 value;
3912
3913 FILE *file;
3914
3915 struct edfhdrblock *hdr;
3916
3917
3918 if(handle<0)
3919 {
3920 return -1;
3921 }
3922
3923 if(handle>=EDFLIB_MAXFILES)
3924 {
3925 return -1;
3926 }
3927
3928 if(hdrlist[handle]==NULL)
3929 {
3930 return -1;
3931 }
3932
3933 if(!(hdrlist[handle]->writemode))
3934 {
3935 return -1;
3936 }
3937
3938 if(hdrlist[handle]->edfsignals == 0)
3939 {
3940 return -1;
3941 }
3942
3943 if(hdrlist[handle]->bdf == 1)
3944 {
3945 return -1;
3946 }
3947
3948 hdr = hdrlist[handle];
3949
3950 file = hdr->file_hdl;
3951
3952 edfsignal = hdr->signal_write_sequence_pos;
3953
3954 if(!hdr->datarecords)
3955 {
3956 if(!edfsignal)
3957 {
3958 error = edflib_write_edf_header(hdr);
3959
3960 if(error)
3961 {
3962 return error;
3963 }
3964 }
3965 }
3966
3967 sf = hdr->edfparam[edfsignal].smp_per_record;
3968
3969 digmax = hdr->edfparam[edfsignal].dig_max;
3970
3971 digmin = hdr->edfparam[edfsignal].dig_min;
3972
3973 if(hdr->edf)
3974 {
3975 if((digmax != 32767) || (digmin != -32768))
3976 {
3977 for(i=0; i<sf; i++)
3978 {
3979 if(buf[i]>digmax)
3980 {
3981 buf[i] = digmax;
3982 }
3983
3984 if(buf[i]<digmin)
3985 {
3986 buf[i] = digmin;
3987 }
3988 }
3989 }
3990
3991 if(fwrite(buf, sf * 2, 1, file) != 1)
3992 {
3993 return -1;
3994 }
3995 }
3996 else // BDF
3997 {
3998 if(hdr->wrbufsize < (sf * 3))
3999 {
4000 free(hdr->wrbuf);
4001
4002 hdr->wrbufsize = 0;
4003
4004 hdr->wrbuf = (char *)malloc(sf * 3);
4005
4006 if(hdr->wrbuf == NULL)
4007 {
4008 return -1;
4009 }
4010
4011 hdr->wrbufsize = sf * 3;
4012 }
4013
4014 for(i=0; i<sf; i++)
4015 {
4016 value = buf[i];
4017
4018 if(value>digmax)
4019 {
4020 value = digmax;
4021 }
4022
4023 if(value<digmin)
4024 {
4025 value = digmin;
4026 }
4027
4028 hdr->wrbuf[i * 3] = value & 0xff;
4029
4030 hdr->wrbuf[i * 3 + 1] = (value >> 8) & 0xff;
4031
4032 hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff;
4033 }
4034
4035 if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1)
4036 {
4037 return -1;
4038 }
4039 }
4040
4041 hdr->signal_write_sequence_pos++;
4042
4043 if(hdr->signal_write_sequence_pos == hdr->edfsignals)
4044 {
4045 hdr->signal_write_sequence_pos = 0;
4046
4047 if(edflib_write_tal(hdr, file))
4048 {
4049 return -1;
4050 }
4051
4052 hdr->datarecords++;
4053
4054 fflush(file);
4055 }
4056
4057 return 0;
4058 }
4059
4060
edfwrite_digital_samples(int handle,int * buf)4061 int edfwrite_digital_samples(int handle, int *buf)
4062 {
4063 int i,
4064 error,
4065 sf,
4066 digmax,
4067 digmin,
4068 edfsignal,
4069 value;
4070
4071 FILE *file;
4072
4073 struct edfhdrblock *hdr;
4074
4075
4076 if(handle<0)
4077 {
4078 return -1;
4079 }
4080
4081 if(handle>=EDFLIB_MAXFILES)
4082 {
4083 return -1;
4084 }
4085
4086 if(hdrlist[handle]==NULL)
4087 {
4088 return -1;
4089 }
4090
4091 if(!(hdrlist[handle]->writemode))
4092 {
4093 return -1;
4094 }
4095
4096 if(hdrlist[handle]->edfsignals == 0)
4097 {
4098 return -1;
4099 }
4100
4101 hdr = hdrlist[handle];
4102
4103 file = hdr->file_hdl;
4104
4105 edfsignal = hdr->signal_write_sequence_pos;
4106
4107 if(!hdr->datarecords)
4108 {
4109 if(!edfsignal)
4110 {
4111 error = edflib_write_edf_header(hdr);
4112
4113 if(error)
4114 {
4115 return error;
4116 }
4117 }
4118 }
4119
4120 sf = hdr->edfparam[edfsignal].smp_per_record;
4121
4122 digmax = hdr->edfparam[edfsignal].dig_max;
4123
4124 digmin = hdr->edfparam[edfsignal].dig_min;
4125
4126 if(hdr->edf)
4127 {
4128 if(hdr->wrbufsize < (sf * 2))
4129 {
4130 free(hdr->wrbuf);
4131
4132 hdr->wrbufsize = 0;
4133
4134 hdr->wrbuf = (char *)malloc(sf * 2);
4135
4136 if(hdr->wrbuf == NULL)
4137 {
4138 return -1;
4139 }
4140
4141 hdr->wrbufsize = sf * 2;
4142 }
4143
4144 for(i=0; i<sf; i++)
4145 {
4146 value = buf[i];
4147
4148 if(value>digmax)
4149 {
4150 value = digmax;
4151 }
4152
4153 if(value<digmin)
4154 {
4155 value = digmin;
4156 }
4157
4158 hdr->wrbuf[i * 2] = value & 0xff;
4159
4160 hdr->wrbuf[i * 2 + 1] = (value >> 8) & 0xff;
4161 }
4162
4163 if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1)
4164 {
4165 return -1;
4166 }
4167 }
4168 else // BDF
4169 {
4170 if(hdr->wrbufsize < (sf * 3))
4171 {
4172 free(hdr->wrbuf);
4173
4174 hdr->wrbufsize = 0;
4175
4176 hdr->wrbuf = (char *)malloc(sf * 3);
4177
4178 if(hdr->wrbuf == NULL)
4179 {
4180 return -1;
4181 }
4182
4183 hdr->wrbufsize = sf * 3;
4184 }
4185
4186 for(i=0; i<sf; i++)
4187 {
4188 value = buf[i];
4189
4190 if(value>digmax)
4191 {
4192 value = digmax;
4193 }
4194
4195 if(value<digmin)
4196 {
4197 value = digmin;
4198 }
4199
4200 hdr->wrbuf[i * 3] = value & 0xff;
4201
4202 hdr->wrbuf[i * 3 + 1] = (value >> 8) & 0xff;
4203
4204 hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff;
4205 }
4206
4207 if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1)
4208 {
4209 return -1;
4210 }
4211 }
4212
4213 hdr->signal_write_sequence_pos++;
4214
4215 if(hdr->signal_write_sequence_pos == hdr->edfsignals)
4216 {
4217 hdr->signal_write_sequence_pos = 0;
4218
4219 if(edflib_write_tal(hdr, file))
4220 {
4221 return -1;
4222 }
4223
4224 hdr->datarecords++;
4225
4226 fflush(file);
4227 }
4228
4229 return 0;
4230 }
4231
4232
edf_blockwrite_digital_samples(int handle,int * buf)4233 int edf_blockwrite_digital_samples(int handle, int *buf)
4234 {
4235 int i, j,
4236 error,
4237 sf,
4238 digmax,
4239 digmin,
4240 edfsignals,
4241 buf_offset,
4242 value;
4243
4244 FILE *file;
4245
4246 struct edfhdrblock *hdr;
4247
4248
4249 if(handle<0)
4250 {
4251 return -1;
4252 }
4253
4254 if(handle>=EDFLIB_MAXFILES)
4255 {
4256 return -1;
4257 }
4258
4259 if(hdrlist[handle]==NULL)
4260 {
4261 return -1;
4262 }
4263
4264 if(!(hdrlist[handle]->writemode))
4265 {
4266 return -1;
4267 }
4268
4269 if(hdrlist[handle]->signal_write_sequence_pos)
4270 {
4271 return -1;
4272 }
4273
4274 if(hdrlist[handle]->edfsignals == 0)
4275 {
4276 return -1;
4277 }
4278
4279 hdr = hdrlist[handle];
4280
4281 file = hdr->file_hdl;
4282
4283 edfsignals = hdr->edfsignals;
4284
4285 if(!hdr->datarecords)
4286 {
4287 error = edflib_write_edf_header(hdr);
4288
4289 if(error)
4290 {
4291 return error;
4292 }
4293 }
4294
4295 buf_offset = 0;
4296
4297 for(j=0; j<edfsignals; j++)
4298 {
4299 sf = hdr->edfparam[j].smp_per_record;
4300
4301 digmax = hdr->edfparam[j].dig_max;
4302
4303 digmin = hdr->edfparam[j].dig_min;
4304
4305 if(hdr->edf)
4306 {
4307 if(hdr->wrbufsize < (sf * 2))
4308 {
4309 free(hdr->wrbuf);
4310
4311 hdr->wrbufsize = 0;
4312
4313 hdr->wrbuf = (char *)malloc(sf * 2);
4314
4315 if(hdr->wrbuf == NULL)
4316 {
4317 return -1;
4318 }
4319
4320 hdr->wrbufsize = sf * 2;
4321 }
4322
4323 for(i=0; i<sf; i++)
4324 {
4325 value = buf[i + buf_offset];
4326
4327 if(value>digmax)
4328 {
4329 value = digmax;
4330 }
4331
4332 if(value<digmin)
4333 {
4334 value = digmin;
4335 }
4336
4337 hdr->wrbuf[i * 2] = value & 0xff;
4338
4339 hdr->wrbuf[i * 2 + 1] = (value >> 8) & 0xff;
4340 }
4341
4342 if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1)
4343 {
4344 return -1;
4345 }
4346 }
4347 else // BDF
4348 {
4349 if(hdr->wrbufsize < (sf * 3))
4350 {
4351 free(hdr->wrbuf);
4352
4353 hdr->wrbufsize = 0;
4354
4355 hdr->wrbuf = (char *)malloc(sf * 3);
4356
4357 if(hdr->wrbuf == NULL)
4358 {
4359 return -1;
4360 }
4361
4362 hdr->wrbufsize = sf * 3;
4363 }
4364
4365 for(i=0; i<sf; i++)
4366 {
4367 value = buf[i + buf_offset];
4368
4369 if(value>digmax)
4370 {
4371 value = digmax;
4372 }
4373
4374 if(value<digmin)
4375 {
4376 value = digmin;
4377 }
4378
4379 hdr->wrbuf[i * 3] = value & 0xff;
4380
4381 hdr->wrbuf[i * 3 + 1] = (value >> 8) & 0xff;
4382
4383 hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff;
4384 }
4385
4386 if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1)
4387 {
4388 return -1;
4389 }
4390 }
4391
4392 buf_offset += sf;
4393 }
4394
4395 if(edflib_write_tal(hdr, file))
4396 {
4397 return -1;
4398 }
4399
4400 hdr->datarecords++;
4401
4402 fflush(file);
4403
4404 return 0;
4405 }
4406
4407
edf_blockwrite_digital_short_samples(int handle,short * buf)4408 int edf_blockwrite_digital_short_samples(int handle, short *buf)
4409 {
4410 int i, j,
4411 error,
4412 sf,
4413 digmax,
4414 digmin,
4415 edfsignals,
4416 buf_offset,
4417 value;
4418
4419 FILE *file;
4420
4421 struct edfhdrblock *hdr;
4422
4423
4424 if(handle<0)
4425 {
4426 return -1;
4427 }
4428
4429 if(handle>=EDFLIB_MAXFILES)
4430 {
4431 return -1;
4432 }
4433
4434 if(hdrlist[handle]==NULL)
4435 {
4436 return -1;
4437 }
4438
4439 if(!(hdrlist[handle]->writemode))
4440 {
4441 return -1;
4442 }
4443
4444 if(hdrlist[handle]->signal_write_sequence_pos)
4445 {
4446 return -1;
4447 }
4448
4449 if(hdrlist[handle]->edfsignals == 0)
4450 {
4451 return -1;
4452 }
4453
4454 if(hdrlist[handle]->bdf == 1)
4455 {
4456 return -1;
4457 }
4458
4459 hdr = hdrlist[handle];
4460
4461 file = hdr->file_hdl;
4462
4463 edfsignals = hdr->edfsignals;
4464
4465 if(!hdr->datarecords)
4466 {
4467 error = edflib_write_edf_header(hdr);
4468
4469 if(error)
4470 {
4471 return error;
4472 }
4473 }
4474
4475 buf_offset = 0;
4476
4477 for(j=0; j<edfsignals; j++)
4478 {
4479 sf = hdr->edfparam[j].smp_per_record;
4480
4481 digmax = hdr->edfparam[j].dig_max;
4482
4483 digmin = hdr->edfparam[j].dig_min;
4484
4485 if(hdr->edf)
4486 {
4487 if((digmax != 32767) || (digmin != -32768))
4488 {
4489 for(i=0; i<sf; i++)
4490 {
4491 if(buf[i + buf_offset] > digmax)
4492 {
4493 buf[i + buf_offset] = digmax;
4494 }
4495
4496 if(buf[i + buf_offset] < digmin)
4497 {
4498 buf[i + buf_offset] = digmin;
4499 }
4500 }
4501 }
4502
4503 if(fwrite(buf + buf_offset, sf * 2, 1, file) != 1)
4504 {
4505 return -1;
4506 }
4507 }
4508 else // BDF
4509 {
4510 if(hdr->wrbufsize < (sf * 3))
4511 {
4512 free(hdr->wrbuf);
4513
4514 hdr->wrbufsize = 0;
4515
4516 hdr->wrbuf = (char *)malloc(sf * 3);
4517
4518 if(hdr->wrbuf == NULL)
4519 {
4520 return -1;
4521 }
4522
4523 hdr->wrbufsize = sf * 3;
4524 }
4525
4526 for(i=0; i<sf; i++)
4527 {
4528 value = buf[i + buf_offset];
4529
4530 if(value>digmax)
4531 {
4532 value = digmax;
4533 }
4534
4535 if(value<digmin)
4536 {
4537 value = digmin;
4538 }
4539
4540 hdr->wrbuf[i * 3] = value & 0xff;
4541
4542 hdr->wrbuf[i * 3 + 1] = (value >> 8) & 0xff;
4543
4544 hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff;
4545 }
4546
4547 if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1)
4548 {
4549 return -1;
4550 }
4551 }
4552
4553 buf_offset += sf;
4554 }
4555
4556 if(edflib_write_tal(hdr, file))
4557 {
4558 return -1;
4559 }
4560
4561 hdr->datarecords++;
4562
4563 fflush(file);
4564
4565 return 0;
4566 }
4567
4568
edf_blockwrite_digital_3byte_samples(int handle,void * buf)4569 int edf_blockwrite_digital_3byte_samples(int handle, void *buf)
4570 {
4571 int j,
4572 error,
4573 edfsignals,
4574 total_samples=0;
4575
4576 FILE *file;
4577
4578 struct edfhdrblock *hdr;
4579
4580
4581 if(handle<0)
4582 {
4583 return -1;
4584 }
4585
4586 if(handle>=EDFLIB_MAXFILES)
4587 {
4588 return -1;
4589 }
4590
4591 if(hdrlist[handle]==NULL)
4592 {
4593 return -1;
4594 }
4595
4596 if(!(hdrlist[handle]->writemode))
4597 {
4598 return -1;
4599 }
4600
4601 if(hdrlist[handle]->signal_write_sequence_pos)
4602 {
4603 return -1;
4604 }
4605
4606 if(hdrlist[handle]->edfsignals == 0)
4607 {
4608 return -1;
4609 }
4610
4611 if(hdrlist[handle]->bdf != 1)
4612 {
4613 return -1;
4614 }
4615
4616 hdr = hdrlist[handle];
4617
4618 file = hdr->file_hdl;
4619
4620 edfsignals = hdr->edfsignals;
4621
4622 if(!hdr->datarecords)
4623 {
4624 error = edflib_write_edf_header(hdr);
4625
4626 if(error)
4627 {
4628 return error;
4629 }
4630 }
4631
4632 for(j=0; j<edfsignals; j++)
4633 {
4634 total_samples += hdr->edfparam[j].smp_per_record;
4635 }
4636
4637 if(fwrite(buf, total_samples * 3, 1, file) != 1)
4638 {
4639 return -1;
4640 }
4641
4642 if(edflib_write_tal(hdr, file))
4643 {
4644 return -1;
4645 }
4646
4647 hdr->datarecords++;
4648
4649 fflush(file);
4650
4651 return 0;
4652 }
4653
4654
edfwrite_physical_samples(int handle,double * buf)4655 int edfwrite_physical_samples(int handle, double *buf)
4656 {
4657 int i,
4658 error,
4659 sf,
4660 digmax,
4661 digmin,
4662 value,
4663 edfsignal;
4664
4665 double bitvalue,
4666 phys_offset;
4667
4668 FILE *file;
4669
4670 struct edfhdrblock *hdr;
4671
4672
4673 if(handle<0)
4674 {
4675 return -1;
4676 }
4677
4678 if(handle>=EDFLIB_MAXFILES)
4679 {
4680 return -1;
4681 }
4682
4683 if(hdrlist[handle]==NULL)
4684 {
4685 return -1;
4686 }
4687
4688 if(!(hdrlist[handle]->writemode))
4689 {
4690 return -1;
4691 }
4692
4693 if(hdrlist[handle]->edfsignals == 0)
4694 {
4695 return -1;
4696 }
4697
4698 hdr = hdrlist[handle];
4699
4700 file = hdr->file_hdl;
4701
4702 edfsignal = hdr->signal_write_sequence_pos;
4703
4704 if(!hdr->datarecords)
4705 {
4706 if(!edfsignal)
4707 {
4708 error = edflib_write_edf_header(hdr);
4709
4710 if(error)
4711 {
4712 return error;
4713 }
4714 }
4715 }
4716
4717 sf = hdr->edfparam[edfsignal].smp_per_record;
4718
4719 digmax = hdr->edfparam[edfsignal].dig_max;
4720
4721 digmin = hdr->edfparam[edfsignal].dig_min;
4722
4723 bitvalue = hdr->edfparam[edfsignal].bitvalue;
4724
4725 phys_offset = hdr->edfparam[edfsignal].offset;
4726
4727 if(hdr->edf)
4728 {
4729 if(hdr->wrbufsize < (sf * 2))
4730 {
4731 free(hdr->wrbuf);
4732
4733 hdr->wrbufsize = 0;
4734
4735 hdr->wrbuf = (char *)malloc(sf * 2);
4736
4737 if(hdr->wrbuf == NULL)
4738 {
4739 return -1;
4740 }
4741
4742 hdr->wrbufsize = sf * 2;
4743 }
4744
4745 for(i=0; i<sf; i++)
4746 {
4747 value = (buf[i] / bitvalue) - phys_offset;
4748
4749 if(value>digmax)
4750 {
4751 value = digmax;
4752 }
4753
4754 if(value<digmin)
4755 {
4756 value = digmin;
4757 }
4758
4759 hdr->wrbuf[i * 2] = value & 0xff;
4760
4761 hdr->wrbuf[i * 2 + 1] = (value >> 8) & 0xff;
4762 }
4763
4764 if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1)
4765 {
4766 return -1;
4767 }
4768 }
4769 else // BDF
4770 {
4771 if(hdr->wrbufsize < (sf * 3))
4772 {
4773 free(hdr->wrbuf);
4774
4775 hdr->wrbufsize = 0;
4776
4777 hdr->wrbuf = (char *)malloc(sf * 3);
4778
4779 if(hdr->wrbuf == NULL)
4780 {
4781 return -1;
4782 }
4783
4784 hdr->wrbufsize = sf * 3;
4785 }
4786
4787 for(i=0; i<sf; i++)
4788 {
4789 value = (buf[i] / bitvalue) - phys_offset;
4790
4791 if(value>digmax)
4792 {
4793 value = digmax;
4794 }
4795
4796 if(value<digmin)
4797 {
4798 value = digmin;
4799 }
4800
4801 hdr->wrbuf[i * 3] = value & 0xff;
4802
4803 hdr->wrbuf[i * 3 + 1] = (value >> 8) & 0xff;
4804
4805 hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff;
4806 }
4807
4808 if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1)
4809 {
4810 return -1;
4811 }
4812 }
4813
4814 hdr->signal_write_sequence_pos++;
4815
4816 if(hdr->signal_write_sequence_pos == hdr->edfsignals)
4817 {
4818 hdr->signal_write_sequence_pos = 0;
4819
4820 if(edflib_write_tal(hdr, file))
4821 {
4822 return -1;
4823 }
4824
4825 hdr->datarecords++;
4826
4827 fflush(file);
4828 }
4829
4830 return 0;
4831 }
4832
4833
edf_blockwrite_physical_samples(int handle,double * buf)4834 int edf_blockwrite_physical_samples(int handle, double *buf)
4835 {
4836 int i, j,
4837 error,
4838 sf,
4839 digmax,
4840 digmin,
4841 edfsignals,
4842 buf_offset,
4843 value;
4844
4845 double bitvalue,
4846 phys_offset;
4847
4848 FILE *file;
4849
4850 struct edfhdrblock *hdr;
4851
4852
4853 if(handle<0)
4854 {
4855 return -1;
4856 }
4857
4858 if(handle>=EDFLIB_MAXFILES)
4859 {
4860 return -1;
4861 }
4862
4863 if(hdrlist[handle]==NULL)
4864 {
4865 return -1;
4866 }
4867
4868 if(!(hdrlist[handle]->writemode))
4869 {
4870 return -1;
4871 }
4872
4873 if(hdrlist[handle]->signal_write_sequence_pos)
4874 {
4875 return -1;
4876 }
4877
4878 if(hdrlist[handle]->edfsignals == 0)
4879 {
4880 return -1;
4881 }
4882
4883 hdr = hdrlist[handle];
4884
4885 file = hdr->file_hdl;
4886
4887 edfsignals = hdr->edfsignals;
4888
4889 if(!hdr->datarecords)
4890 {
4891 error = edflib_write_edf_header(hdr);
4892
4893 if(error)
4894 {
4895 return error;
4896 }
4897 }
4898
4899 buf_offset = 0;
4900
4901 for(j=0; j<edfsignals; j++)
4902 {
4903 sf = hdr->edfparam[j].smp_per_record;
4904
4905 digmax = hdr->edfparam[j].dig_max;
4906
4907 digmin = hdr->edfparam[j].dig_min;
4908
4909 bitvalue = hdr->edfparam[j].bitvalue;
4910
4911 phys_offset = hdr->edfparam[j].offset;
4912
4913 if(hdr->edf)
4914 {
4915 if(hdr->wrbufsize < (sf * 2))
4916 {
4917 free(hdr->wrbuf);
4918
4919 hdr->wrbufsize = 0;
4920
4921 hdr->wrbuf = (char *)malloc(sf * 2);
4922
4923 if(hdr->wrbuf == NULL)
4924 {
4925 return -1;
4926 }
4927
4928 hdr->wrbufsize = sf * 2;
4929 }
4930
4931 for(i=0; i<sf; i++)
4932 {
4933 value = (buf[i + buf_offset] / bitvalue) - phys_offset;
4934
4935 if(value>digmax)
4936 {
4937 value = digmax;
4938 }
4939
4940 if(value<digmin)
4941 {
4942 value = digmin;
4943 }
4944
4945 hdr->wrbuf[i * 2] = value & 0xff;
4946
4947 hdr->wrbuf[i * 2 + 1] = (value >> 8) & 0xff;
4948 }
4949
4950 if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1)
4951 {
4952 return -1;
4953 }
4954 }
4955 else // BDF
4956 {
4957 if(hdr->wrbufsize < (sf * 3))
4958 {
4959 free(hdr->wrbuf);
4960
4961 hdr->wrbufsize = 0;
4962
4963 hdr->wrbuf = (char *)malloc(sf * 3);
4964
4965 if(hdr->wrbuf == NULL)
4966 {
4967 return -1;
4968 }
4969
4970 hdr->wrbufsize = sf * 3;
4971 }
4972
4973 for(i=0; i<sf; i++)
4974 {
4975 value = (buf[i + buf_offset] / bitvalue) - phys_offset;
4976
4977 if(value>digmax)
4978 {
4979 value = digmax;
4980 }
4981
4982 if(value<digmin)
4983 {
4984 value = digmin;
4985 }
4986
4987 hdr->wrbuf[i * 3] = value & 0xff;
4988
4989 hdr->wrbuf[i * 3 + 1] = (value >> 8) & 0xff;
4990
4991 hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff;
4992 }
4993
4994 if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1)
4995 {
4996 return -1;
4997 }
4998 }
4999
5000 buf_offset += sf;
5001 }
5002
5003 if(edflib_write_tal(hdr, file))
5004 {
5005 return -1;
5006 }
5007
5008 hdr->datarecords++;
5009
5010 fflush(file);
5011
5012 return 0;
5013 }
5014
5015
edflib_write_edf_header(struct edfhdrblock * hdr)5016 static int edflib_write_edf_header(struct edfhdrblock *hdr)
5017 {
5018 int i, j, p, q,
5019 len,
5020 rest,
5021 edfsignals;
5022
5023 char str[128];
5024
5025 struct tm *date_time;
5026
5027 time_t elapsed_time;
5028
5029 FILE *file;
5030
5031
5032 file = hdr->file_hdl;
5033
5034 edfsignals = hdr->edfsignals;
5035
5036 if(edfsignals<0)
5037 {
5038 return EDFLIB_NO_SIGNALS;
5039 }
5040
5041 if(edfsignals>EDFLIB_MAXSIGNALS)
5042 {
5043 return EDFLIB_TOO_MANY_SIGNALS;
5044 }
5045
5046 hdr->eq_sf = 1;
5047
5048 hdr->recordsize = 0;
5049
5050 hdr->total_annot_bytes = EDFLIB_ANNOTATION_BYTES * hdr->nr_annot_chns;
5051
5052 for(i=0; i<edfsignals; i++)
5053 {
5054 if(hdr->edfparam[i].smp_per_record<1)
5055 {
5056 return EDFLIB_NO_SAMPLES_IN_RECORD;
5057 }
5058
5059 if(hdr->edfparam[i].dig_max==hdr->edfparam[i].dig_min)
5060 {
5061 return EDFLIB_DIGMIN_IS_DIGMAX;
5062 }
5063
5064 if(hdr->edfparam[i].dig_max<hdr->edfparam[i].dig_min)
5065 {
5066 return EDFLIB_DIGMAX_LOWER_THAN_DIGMIN;
5067 }
5068
5069 if(hdr->edfparam[i].phys_max==hdr->edfparam[i].phys_min)
5070 {
5071 return EDFLIB_PHYSMIN_IS_PHYSMAX;
5072 }
5073
5074 hdr->recordsize += hdr->edfparam[i].smp_per_record;
5075
5076 if(i > 0)
5077 {
5078 if(hdr->edfparam[i].smp_per_record != hdr->edfparam[i-1].smp_per_record)
5079 {
5080 hdr->eq_sf = 0;
5081 }
5082 }
5083 }
5084
5085 if(hdr->edf)
5086 {
5087 hdr->recordsize *= 2;
5088
5089 hdr->recordsize += hdr->total_annot_bytes;
5090
5091 if(hdr->recordsize > (10 * 1024 * 1024)) /* datarecord size should not exceed 10MB for EDF */
5092 {
5093 return EDFLIB_DATARECORD_SIZE_TOO_BIG;
5094 } /* if your application gets hit by this limitation, lower the value for the datarecord duration */
5095 /* using the function edf_set_datarecord_duration() */
5096 }
5097 else
5098 {
5099 hdr->recordsize *= 3;
5100
5101 hdr->recordsize += hdr->total_annot_bytes;
5102
5103 if(hdr->recordsize > (15 * 1024 * 1024)) /* datarecord size should not exceed 15MB for BDF */
5104 {
5105 return EDFLIB_DATARECORD_SIZE_TOO_BIG;
5106 } /* if your application gets hit by this limitation, lower the value for the datarecord duration */
5107 /* using the function edf_set_datarecord_duration() */
5108 }
5109
5110 for(i=0; i<edfsignals; i++)
5111 {
5112 hdr->edfparam[i].bitvalue = (hdr->edfparam[i].phys_max - hdr->edfparam[i].phys_min) / (hdr->edfparam[i].dig_max - hdr->edfparam[i].dig_min);
5113 hdr->edfparam[i].offset = hdr->edfparam[i].phys_max / hdr->edfparam[i].bitvalue - hdr->edfparam[i].dig_max;
5114 }
5115
5116 rewind(file);
5117
5118 if(hdr->edf)
5119 {
5120 fprintf(file, "0 ");
5121 }
5122 else
5123 {
5124 fputc(255, file);
5125 fprintf(file, "BIOSEMI");
5126 }
5127
5128 p = 0;
5129
5130 if(hdr->plus_birthdate[0]==0)
5131 {
5132 rest = 72;
5133 }
5134 else
5135 {
5136 rest = 62;
5137 }
5138
5139 len = strlen(hdr->plus_patientcode);
5140 if(len && rest)
5141 {
5142 if(len>rest)
5143 {
5144 len = rest;
5145 rest = 0;
5146 }
5147 else
5148 {
5149 rest -= len;
5150 }
5151 edflib_strlcpy(str, hdr->plus_patientcode, 128);
5152 edflib_latin1_to_ascii(str, len);
5153 str[len] = 0;
5154 for(i=0; i<len; i++)
5155 {
5156 if(str[i]==' ')
5157 {
5158 str[i] = '_';
5159 }
5160 }
5161 p += fprintf(file, "%s ", str);
5162 }
5163 else
5164 {
5165 p += fprintf(file, "X ");
5166 }
5167
5168 if(hdr->plus_gender[0]=='M')
5169 {
5170 fputc('M', file);
5171 }
5172 else
5173 {
5174 if(hdr->plus_gender[0]=='F')
5175 {
5176 fputc('F', file);
5177 }
5178 else
5179 {
5180 fputc('X', file);
5181 }
5182 }
5183 fputc(' ', file);
5184 p +=2;
5185
5186 if(hdr->plus_birthdate[0]==0)
5187 {
5188 fputc('X', file);
5189 fputc(' ', file);
5190
5191 p +=2;
5192 }
5193 else
5194 {
5195 fputc(hdr->plus_birthdate[0], file);
5196 fputc(hdr->plus_birthdate[1], file);
5197 fputc('-', file);
5198 q = edflib_atof_nonlocalized(&(hdr->plus_birthdate[3]));
5199 switch(q)
5200 {
5201 case 1: fprintf(file, "JAN"); break;
5202 case 2: fprintf(file, "FEB"); break;
5203 case 3: fprintf(file, "MAR"); break;
5204 case 4: fprintf(file, "APR"); break;
5205 case 5: fprintf(file, "MAY"); break;
5206 case 6: fprintf(file, "JUN"); break;
5207 case 7: fprintf(file, "JUL"); break;
5208 case 8: fprintf(file, "AUG"); break;
5209 case 9: fprintf(file, "SEP"); break;
5210 case 10: fprintf(file, "OCT"); break;
5211 case 11: fprintf(file, "NOV"); break;
5212 case 12: fprintf(file, "DEC"); break;
5213 }
5214 fputc('-', file);
5215 fputc(hdr->plus_birthdate[6], file);
5216 fputc(hdr->plus_birthdate[7], file);
5217 fputc(hdr->plus_birthdate[8], file);
5218 fputc(hdr->plus_birthdate[9], file);
5219 fputc(' ', file);
5220
5221 p += 12;
5222 }
5223
5224 len = strlen(hdr->plus_patient_name);
5225 if(len && rest)
5226 {
5227 if(len>rest)
5228 {
5229 len = rest;
5230 rest = 0;
5231 }
5232 else
5233 {
5234 rest -= len;
5235 }
5236 edflib_strlcpy(str, hdr->plus_patient_name, 128);
5237 edflib_latin1_to_ascii(str, len);
5238 str[len] = 0;
5239 for(i=0; i<len; i++)
5240 {
5241 if(str[i]==' ')
5242 {
5243 str[i] = '_';
5244 }
5245 }
5246 p += fprintf(file, "%s", str);
5247 }
5248 else
5249 {
5250 fputc('X', file);
5251
5252 p++;
5253 }
5254
5255 if(rest)
5256 {
5257 fputc(' ', file);
5258
5259 p++;
5260
5261 rest--;
5262 }
5263
5264 len = strlen(hdr->plus_patient_additional);
5265 if(len && rest)
5266 {
5267 if(len>rest)
5268 {
5269 len = rest;
5270 }
5271 edflib_strlcpy(str, hdr->plus_patient_additional, 128);
5272 edflib_latin1_to_ascii(str, len);
5273 str[len] = 0;
5274 p += fprintf(file, "%s", str);
5275 }
5276
5277 for(; p<80; p++)
5278 {
5279 fputc(' ', file);
5280 }
5281
5282 if(!hdr->startdate_year)
5283 {
5284 elapsed_time = time(NULL);
5285 date_time = localtime(&elapsed_time);
5286
5287 hdr->startdate_year = date_time->tm_year + 1900;
5288 hdr->startdate_month = date_time->tm_mon + 1;
5289 hdr->startdate_day = date_time->tm_mday;
5290 hdr->starttime_hour = date_time->tm_hour;
5291 hdr->starttime_minute = date_time->tm_min;
5292 hdr->starttime_second = date_time->tm_sec % 60;
5293 }
5294
5295 p = 0;
5296
5297 p += fprintf(file, "Startdate %02u-", hdr->startdate_day);
5298 switch(hdr->startdate_month)
5299 {
5300 case 1 : fprintf(file, "JAN"); break;
5301 case 2 : fprintf(file, "FEB"); break;
5302 case 3 : fprintf(file, "MAR"); break;
5303 case 4 : fprintf(file, "APR"); break;
5304 case 5 : fprintf(file, "MAY"); break;
5305 case 6 : fprintf(file, "JUN"); break;
5306 case 7 : fprintf(file, "JUL"); break;
5307 case 8 : fprintf(file, "AUG"); break;
5308 case 9 : fprintf(file, "SEP"); break;
5309 case 10 : fprintf(file, "OCT"); break;
5310 case 11 : fprintf(file, "NOV"); break;
5311 case 12 : fprintf(file, "DEC"); break;
5312 }
5313 p += 3;
5314 fputc('-', file);
5315 p++;
5316 p += edflib_fprint_int_number_nonlocalized(file, hdr->startdate_year, 4, 0);
5317 fputc(' ', file);
5318 p++;
5319
5320 rest = 42;
5321
5322 len = strlen(hdr->plus_admincode);
5323 if(len && rest)
5324 {
5325 if(len>rest)
5326 {
5327 len = rest;
5328 rest = 0;
5329 }
5330 else
5331 {
5332 rest -= len;
5333 }
5334 edflib_strlcpy(str, hdr->plus_admincode, 128);
5335 edflib_latin1_to_ascii(str, len);
5336 str[len] = 0;
5337 for(i=0; i<len; i++)
5338 {
5339 if(str[i]==' ')
5340 {
5341 str[i] = '_';
5342 }
5343 }
5344 p += fprintf(file, "%s", str);
5345 }
5346 else
5347 {
5348 p += fprintf(file, "X");
5349 }
5350
5351 if(rest)
5352 {
5353 fputc(' ', file);
5354
5355 p++;
5356
5357 rest--;
5358 }
5359
5360 len = strlen(hdr->plus_technician);
5361 if(len && rest)
5362 {
5363 if(len>rest)
5364 {
5365 len = rest;
5366 rest = 0;
5367 }
5368 else
5369 {
5370 rest -= len;
5371 }
5372 edflib_strlcpy(str, hdr->plus_technician, 128);
5373 edflib_latin1_to_ascii(str, len);
5374 str[len] = 0;
5375 for(i=0; i<len; i++)
5376 {
5377 if(str[i]==' ')
5378 {
5379 str[i] = '_';
5380 }
5381 }
5382 p += fprintf(file, "%s", str);
5383 }
5384 else
5385 {
5386 p += fprintf(file, "X");
5387 }
5388
5389 if(rest)
5390 {
5391 fputc(' ', file);
5392
5393 p++;
5394
5395 rest--;
5396 }
5397
5398 len = strlen(hdr->plus_equipment);
5399 if(len && rest)
5400 {
5401 if(len>rest)
5402 {
5403 len = rest;
5404 rest = 0;
5405 }
5406 else
5407 {
5408 rest -= len;
5409 }
5410 edflib_strlcpy(str, hdr->plus_equipment, 128);
5411 edflib_latin1_to_ascii(str, len);
5412 str[len] = 0;
5413 for(i=0; i<len; i++)
5414 {
5415 if(str[i]==' ')
5416 {
5417 str[i] = '_';
5418 }
5419 }
5420 p += fprintf(file, "%s", str);
5421 }
5422 else
5423 {
5424 p += fprintf(file, "X");
5425 }
5426
5427 if(rest)
5428 {
5429 fputc(' ', file);
5430
5431 p++;
5432
5433 rest--;
5434 }
5435
5436 len = strlen(hdr->plus_recording_additional);
5437 if(len && rest)
5438 {
5439 if(len>rest)
5440 {
5441 len = rest;
5442 }
5443 edflib_strlcpy(str, hdr->plus_recording_additional, 128);
5444 edflib_latin1_to_ascii(str, len);
5445 str[len] = 0;
5446 p += fprintf(file, "%s", str);
5447 }
5448
5449 for(; p<80; p++)
5450 {
5451 fputc(' ', file);
5452 }
5453
5454 fprintf(file, "%02u.%02u.%02u", hdr->startdate_day, hdr->startdate_month, (hdr->startdate_year % 100));
5455 fprintf(file, "%02u.%02u.%02u", hdr->starttime_hour, hdr->starttime_minute, hdr->starttime_second);
5456 p = edflib_fprint_int_number_nonlocalized(file, (edfsignals + hdr->nr_annot_chns + 1) * 256, 0, 0);
5457 for(; p<8; p++)
5458 {
5459 fputc(' ', file);
5460 }
5461 if(hdr->edf)
5462 {
5463 fprintf(file, "EDF+C");
5464 }
5465 else
5466 {
5467 fprintf(file, "BDF+C");
5468 }
5469 for(i=0; i<39; i++)
5470 {
5471 fputc(' ', file);
5472 }
5473 fprintf(file, "-1 ");
5474 if(hdr->long_data_record_duration == EDFLIB_TIME_DIMENSION)
5475 {
5476 fprintf(file, "1 ");
5477 }
5478 else
5479 {
5480 edflib_snprint_number_nonlocalized(str, hdr->data_record_duration, 128);
5481 edflib_strlcat(str, " ", 128);
5482 str[8] = 0;
5483 fprintf(file, "%s", str);
5484 }
5485 p = edflib_fprint_int_number_nonlocalized(file, edfsignals + hdr->nr_annot_chns, 0, 0);
5486 for(; p<4; p++)
5487 {
5488 fputc(' ', file);
5489 }
5490
5491 for(i=0; i<edfsignals; i++)
5492 {
5493 len = strlen(hdr->edfparam[i].label);
5494 edflib_latin1_to_ascii(hdr->edfparam[i].label, len);
5495 for(j=0; j<len; j++)
5496 {
5497 fputc(hdr->edfparam[i].label[j], file);
5498 }
5499 for(; j<16; j++)
5500 {
5501 fputc(' ', file);
5502 }
5503 }
5504 for(j=0; j<hdr->nr_annot_chns; j++)
5505 {
5506 if(hdr->edf)
5507 {
5508 fprintf(file, "EDF Annotations ");
5509 }
5510 else
5511 {
5512 fprintf(file, "BDF Annotations ");
5513 }
5514 }
5515 for(i=0; i<edfsignals; i++)
5516 {
5517 len = strlen(hdr->edfparam[i].transducer);
5518 edflib_latin1_to_ascii(hdr->edfparam[i].transducer, len);
5519 for(j=0; j<len; j++)
5520 {
5521 fputc(hdr->edfparam[i].transducer[j], file);
5522 }
5523 for(; j<80; j++)
5524 {
5525 fputc(' ', file);
5526 }
5527 }
5528 for(j=0; j<hdr->nr_annot_chns; j++)
5529 {
5530 for(i=0; i<80; i++)
5531 {
5532 fputc(' ', file);
5533 }
5534 }
5535 for(i=0; i<edfsignals; i++)
5536 {
5537 len = strlen(hdr->edfparam[i].physdimension);
5538 edflib_latin1_to_ascii(hdr->edfparam[i].physdimension, len);
5539 for(j=0; j<len; j++)
5540 {
5541 fputc(hdr->edfparam[i].physdimension[j], file);
5542 }
5543 for(; j<8; j++)
5544 {
5545 fputc(' ', file);
5546 }
5547 }
5548 for(j=0; j<hdr->nr_annot_chns; j++)
5549 {
5550 fprintf(file, " ");
5551 }
5552 for(i=0; i<edfsignals; i++)
5553 {
5554 p = edflib_snprint_number_nonlocalized(str, hdr->edfparam[i].phys_min, 128);
5555 for(; p<8; p++)
5556 {
5557 str[p] = ' ';
5558 }
5559 str[8] = 0;
5560 fprintf(file, "%s", str);
5561 }
5562 for(j=0; j<hdr->nr_annot_chns; j++)
5563 {
5564 fprintf(file, "-1 ");
5565 }
5566 for(i=0; i<edfsignals; i++)
5567 {
5568 p = edflib_snprint_number_nonlocalized(str, hdr->edfparam[i].phys_max, 128);
5569 for(; p<8; p++)
5570 {
5571 str[p] = ' ';
5572 }
5573 str[8] = 0;
5574 fprintf(file, "%s", str);
5575 }
5576 for(j=0; j<hdr->nr_annot_chns; j++)
5577 {
5578 fprintf(file, "1 ");
5579 }
5580 for(i=0; i<edfsignals; i++)
5581 {
5582 p = edflib_fprint_int_number_nonlocalized(file, hdr->edfparam[i].dig_min, 0, 0);
5583 for(; p<8; p++)
5584 {
5585 fputc(' ', file);
5586 }
5587 }
5588 for(j=0; j<hdr->nr_annot_chns; j++)
5589 {
5590 if(hdr->edf)
5591 {
5592 fprintf(file, "-32768 ");
5593 }
5594 else
5595 {
5596 fprintf(file, "-8388608");
5597 }
5598 }
5599 for(i=0; i<edfsignals; i++)
5600 {
5601 p = edflib_fprint_int_number_nonlocalized(file, hdr->edfparam[i].dig_max, 0, 0);
5602 for(; p<8; p++)
5603 {
5604 fputc(' ', file);
5605 }
5606 }
5607 for(j=0; j<hdr->nr_annot_chns; j++)
5608 {
5609 if(hdr->edf)
5610 {
5611 fprintf(file, "32767 ");
5612 }
5613 else
5614 {
5615 fprintf(file, "8388607 ");
5616 }
5617 }
5618 for(i=0; i<edfsignals; i++)
5619 {
5620 len = strlen(hdr->edfparam[i].prefilter);
5621 edflib_latin1_to_ascii(hdr->edfparam[i].prefilter, len);
5622 for(j=0; j<len; j++)
5623 {
5624 fputc(hdr->edfparam[i].prefilter[j], file);
5625 }
5626 for(; j<80; j++)
5627 {
5628 fputc(' ', file);
5629 }
5630 }
5631 for(i=0; i<hdr->nr_annot_chns; i++)
5632 {
5633 for(j=0; j<80; j++)
5634 {
5635 fputc(' ', file);
5636 }
5637 }
5638 for(i=0; i<edfsignals; i++)
5639 {
5640 p = edflib_fprint_int_number_nonlocalized(file, hdr->edfparam[i].smp_per_record, 0, 0);
5641 for(; p<8; p++)
5642 {
5643 fputc(' ', file);
5644 }
5645 }
5646 for(j=0; j<hdr->nr_annot_chns; j++)
5647 {
5648 if(hdr->edf)
5649 {
5650 p = edflib_fprint_int_number_nonlocalized(file, EDFLIB_ANNOTATION_BYTES / 2, 0, 0);
5651 for(; p<8; p++)
5652 {
5653 fputc(' ', file);
5654 }
5655 }
5656 else
5657 {
5658 p = edflib_fprint_int_number_nonlocalized(file, EDFLIB_ANNOTATION_BYTES / 3, 0, 0);
5659 for(; p<8; p++)
5660 {
5661 fputc(' ', file);
5662 }
5663 }
5664 }
5665 for(i=0; i<(edfsignals * 32); i++)
5666 {
5667 fputc(' ', file);
5668 }
5669 for(i=0; i<(hdr->nr_annot_chns * 32); i++)
5670 {
5671 fputc(' ', file);
5672 }
5673
5674 return 0;
5675 }
5676
5677
edf_set_label(int handle,int edfsignal,const char * label)5678 int edf_set_label(int handle, int edfsignal, const char *label)
5679 {
5680 if(handle<0)
5681 {
5682 return -1;
5683 }
5684
5685 if(handle>=EDFLIB_MAXFILES)
5686 {
5687 return -1;
5688 }
5689
5690 if(hdrlist[handle]==NULL)
5691 {
5692 return -1;
5693 }
5694
5695 if(!(hdrlist[handle]->writemode))
5696 {
5697 return -1;
5698 }
5699
5700 if(edfsignal<0)
5701 {
5702 return -1;
5703 }
5704
5705 if(edfsignal>=hdrlist[handle]->edfsignals)
5706 {
5707 return -1;
5708 }
5709
5710 if(hdrlist[handle]->datarecords)
5711 {
5712 return -1;
5713 }
5714
5715 strncpy(hdrlist[handle]->edfparam[edfsignal].label, label, 16);
5716
5717 hdrlist[handle]->edfparam[edfsignal].label[16] = 0;
5718
5719 edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].label);
5720
5721 return 0;
5722 }
5723
5724
edf_set_physical_dimension(int handle,int edfsignal,const char * phys_dim)5725 int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim)
5726 {
5727 if(handle<0)
5728 {
5729 return -1;
5730 }
5731
5732 if(handle>=EDFLIB_MAXFILES)
5733 {
5734 return -1;
5735 }
5736
5737 if(hdrlist[handle]==NULL)
5738 {
5739 return -1;
5740 }
5741
5742 if(!(hdrlist[handle]->writemode))
5743 {
5744 return -1;
5745 }
5746
5747 if(edfsignal<0)
5748 {
5749 return -1;
5750 }
5751
5752 if(edfsignal>=hdrlist[handle]->edfsignals)
5753 {
5754 return -1;
5755 }
5756
5757 if(hdrlist[handle]->datarecords)
5758 {
5759 return -1;
5760 }
5761
5762 strncpy(hdrlist[handle]->edfparam[edfsignal].physdimension, phys_dim, 8);
5763
5764 hdrlist[handle]->edfparam[edfsignal].physdimension[8] = 0;
5765
5766 edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].physdimension);
5767
5768 return 0;
5769 }
5770
5771
edf_set_physical_maximum(int handle,int edfsignal,double phys_max)5772 int edf_set_physical_maximum(int handle, int edfsignal, double phys_max)
5773 {
5774 if(handle<0)
5775 {
5776 return -1;
5777 }
5778
5779 if(handle>=EDFLIB_MAXFILES)
5780 {
5781 return -1;
5782 }
5783
5784 if(hdrlist[handle]==NULL)
5785 {
5786 return -1;
5787 }
5788
5789 if(!(hdrlist[handle]->writemode))
5790 {
5791 return -1;
5792 }
5793
5794 if(edfsignal<0)
5795 {
5796 return -1;
5797 }
5798
5799 if(edfsignal>=hdrlist[handle]->edfsignals)
5800 {
5801 return -1;
5802 }
5803
5804 if(hdrlist[handle]->datarecords)
5805 {
5806 return -1;
5807 }
5808
5809 hdrlist[handle]->edfparam[edfsignal].phys_max = phys_max;
5810
5811 return 0;
5812 }
5813
5814
edf_set_physical_minimum(int handle,int edfsignal,double phys_min)5815 int edf_set_physical_minimum(int handle, int edfsignal, double phys_min)
5816 {
5817 if(handle<0)
5818 {
5819 return -1;
5820 }
5821
5822 if(handle>=EDFLIB_MAXFILES)
5823 {
5824 return -1;
5825 }
5826
5827 if(hdrlist[handle]==NULL)
5828 {
5829 return -1;
5830 }
5831
5832 if(!(hdrlist[handle]->writemode))
5833 {
5834 return -1;
5835 }
5836
5837 if(edfsignal<0)
5838 {
5839 return -1;
5840 }
5841
5842 if(edfsignal>=hdrlist[handle]->edfsignals)
5843 {
5844 return -1;
5845 }
5846
5847 if(hdrlist[handle]->datarecords)
5848 {
5849 return -1;
5850 }
5851
5852 hdrlist[handle]->edfparam[edfsignal].phys_min = phys_min;
5853
5854 return 0;
5855 }
5856
5857
edf_set_digital_maximum(int handle,int edfsignal,int dig_max)5858 int edf_set_digital_maximum(int handle, int edfsignal, int dig_max)
5859 {
5860 if(handle<0)
5861 {
5862 return -1;
5863 }
5864
5865 if(handle>=EDFLIB_MAXFILES)
5866 {
5867 return -1;
5868 }
5869
5870 if(hdrlist[handle]==NULL)
5871 {
5872 return -1;
5873 }
5874
5875 if(!(hdrlist[handle]->writemode))
5876 {
5877 return -1;
5878 }
5879
5880 if(edfsignal<0)
5881 {
5882 return -1;
5883 }
5884
5885 if(edfsignal>=hdrlist[handle]->edfsignals)
5886 {
5887 return -1;
5888 }
5889
5890 if(hdrlist[handle]->edf)
5891 {
5892 if(dig_max > 32767)
5893 {
5894 return -1;
5895 }
5896 }
5897 else
5898 {
5899 if(dig_max > 8388607)
5900 {
5901 return -1;
5902 }
5903 }
5904
5905 if(hdrlist[handle]->datarecords)
5906 {
5907 return -1;
5908 }
5909
5910 hdrlist[handle]->edfparam[edfsignal].dig_max = dig_max;
5911
5912 return 0;
5913 }
5914
5915
edf_set_digital_minimum(int handle,int edfsignal,int dig_min)5916 int edf_set_digital_minimum(int handle, int edfsignal, int dig_min)
5917 {
5918 if(handle<0)
5919 {
5920 return -1;
5921 }
5922
5923 if(handle>=EDFLIB_MAXFILES)
5924 {
5925 return -1;
5926 }
5927
5928 if(hdrlist[handle]==NULL)
5929 {
5930 return -1;
5931 }
5932
5933 if(!(hdrlist[handle]->writemode))
5934 {
5935 return -1;
5936 }
5937
5938 if(edfsignal<0)
5939 {
5940 return -1;
5941 }
5942
5943 if(edfsignal>=hdrlist[handle]->edfsignals)
5944 {
5945 return -1;
5946 }
5947
5948 if(hdrlist[handle]->edf)
5949 {
5950 if(dig_min < (-32768))
5951 {
5952 return -1;
5953 }
5954 }
5955 else
5956 {
5957 if(dig_min < (-8388608))
5958 {
5959 return -1;
5960 }
5961 }
5962
5963 if(hdrlist[handle]->datarecords)
5964 {
5965 return -1;
5966 }
5967
5968 hdrlist[handle]->edfparam[edfsignal].dig_min = dig_min;
5969
5970 return 0;
5971 }
5972
5973
edf_set_patientname(int handle,const char * patientname)5974 int edf_set_patientname(int handle, const char *patientname)
5975 {
5976 if(handle<0)
5977 {
5978 return -1;
5979 }
5980
5981 if(handle>=EDFLIB_MAXFILES)
5982 {
5983 return -1;
5984 }
5985
5986 if(hdrlist[handle]==NULL)
5987 {
5988 return -1;
5989 }
5990
5991 if(!(hdrlist[handle]->writemode))
5992 {
5993 return -1;
5994 }
5995
5996 if(hdrlist[handle]->datarecords)
5997 {
5998 return -1;
5999 }
6000
6001 strncpy(hdrlist[handle]->plus_patient_name, patientname, 80);
6002
6003 hdrlist[handle]->plus_patient_name[80] = 0;
6004
6005 edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patient_name);
6006
6007 return 0;
6008 }
6009
6010
edf_set_patientcode(int handle,const char * patientcode)6011 int edf_set_patientcode(int handle, const char *patientcode)
6012 {
6013 if(handle<0)
6014 {
6015 return -1;
6016 }
6017
6018 if(handle>=EDFLIB_MAXFILES)
6019 {
6020 return -1;
6021 }
6022
6023 if(hdrlist[handle]==NULL)
6024 {
6025 return -1;
6026 }
6027
6028 if(!(hdrlist[handle]->writemode))
6029 {
6030 return -1;
6031 }
6032
6033 if(hdrlist[handle]->datarecords)
6034 {
6035 return -1;
6036 }
6037
6038 strncpy(hdrlist[handle]->plus_patientcode, patientcode, 80);
6039
6040 hdrlist[handle]->plus_patientcode[80] = 0;
6041
6042 edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patientcode);
6043
6044 return 0;
6045 }
6046
6047
edf_set_gender(int handle,int gender)6048 int edf_set_gender(int handle, int gender)
6049 {
6050 if(handle<0)
6051 {
6052 return -1;
6053 }
6054
6055 if(handle>=EDFLIB_MAXFILES)
6056 {
6057 return -1;
6058 }
6059
6060 if(hdrlist[handle]==NULL)
6061 {
6062 return -1;
6063 }
6064
6065 if(!(hdrlist[handle]->writemode))
6066 {
6067 return -1;
6068 }
6069
6070 if(hdrlist[handle]->datarecords)
6071 {
6072 return -1;
6073 }
6074
6075 if((gender<0)||(gender>1))
6076 {
6077 return -1;
6078 }
6079
6080 if(gender)
6081 {
6082 hdrlist[handle]->plus_gender[0] = 'M';
6083 }
6084 else
6085 {
6086 hdrlist[handle]->plus_gender[0] = 'F';
6087 }
6088
6089 hdrlist[handle]->plus_gender[1] = 0;
6090
6091 return 0;
6092 }
6093
6094
edf_set_birthdate(int handle,int birthdate_year,int birthdate_month,int birthdate_day)6095 int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day)
6096 {
6097 if(handle<0)
6098 {
6099 return -1;
6100 }
6101
6102 if(handle>=EDFLIB_MAXFILES)
6103 {
6104 return -1;
6105 }
6106
6107 if(hdrlist[handle]==NULL)
6108 {
6109 return -1;
6110 }
6111
6112 if(!(hdrlist[handle]->writemode))
6113 {
6114 return -1;
6115 }
6116
6117 if(hdrlist[handle]->datarecords)
6118 {
6119 return -1;
6120 }
6121
6122 if((birthdate_year<1800) || (birthdate_year>3000) ||
6123 (birthdate_month<1) || (birthdate_month>12) ||
6124 (birthdate_day<1) || (birthdate_day>31))
6125 {
6126 return -1;
6127 }
6128
6129 sprintf(hdrlist[handle]->plus_birthdate, "%02i.%02i.%02i%02i", birthdate_day, birthdate_month, birthdate_year / 100, birthdate_year % 100);
6130
6131 hdrlist[handle]->plus_birthdate[10] = 0;
6132
6133 return 0;
6134 }
6135
6136
edf_set_patient_additional(int handle,const char * patient_additional)6137 int edf_set_patient_additional(int handle, const char *patient_additional)
6138 {
6139 if(handle<0)
6140 {
6141 return -1;
6142 }
6143
6144 if(handle>=EDFLIB_MAXFILES)
6145 {
6146 return -1;
6147 }
6148
6149 if(hdrlist[handle]==NULL)
6150 {
6151 return -1;
6152 }
6153
6154 if(!(hdrlist[handle]->writemode))
6155 {
6156 return -1;
6157 }
6158
6159 if(hdrlist[handle]->datarecords)
6160 {
6161 return -1;
6162 }
6163
6164 strncpy(hdrlist[handle]->plus_patient_additional, patient_additional, 80);
6165
6166 hdrlist[handle]->plus_patient_additional[80] = 0;
6167
6168 edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patient_additional);
6169
6170 return 0;
6171 }
6172
6173
edf_set_admincode(int handle,const char * admincode)6174 int edf_set_admincode(int handle, const char *admincode)
6175 {
6176 if(handle<0)
6177 {
6178 return -1;
6179 }
6180
6181 if(handle>=EDFLIB_MAXFILES)
6182 {
6183 return -1;
6184 }
6185
6186 if(hdrlist[handle]==NULL)
6187 {
6188 return -1;
6189 }
6190
6191 if(!(hdrlist[handle]->writemode))
6192 {
6193 return -1;
6194 }
6195
6196 if(hdrlist[handle]->datarecords)
6197 {
6198 return -1;
6199 }
6200
6201 strncpy(hdrlist[handle]->plus_admincode, admincode, 80);
6202
6203 hdrlist[handle]->plus_admincode[80] = 0;
6204
6205 edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_admincode);
6206
6207 return 0;
6208 }
6209
6210
edf_set_technician(int handle,const char * technician)6211 int edf_set_technician(int handle, const char *technician)
6212 {
6213 if(handle<0)
6214 {
6215 return -1;
6216 }
6217
6218 if(handle>=EDFLIB_MAXFILES)
6219 {
6220 return -1;
6221 }
6222
6223 if(hdrlist[handle]==NULL)
6224 {
6225 return -1;
6226 }
6227
6228 if(!(hdrlist[handle]->writemode))
6229 {
6230 return -1;
6231 }
6232
6233 if(hdrlist[handle]->datarecords)
6234 {
6235 return -1;
6236 }
6237
6238 strncpy(hdrlist[handle]->plus_technician, technician, 80);
6239
6240 hdrlist[handle]->plus_technician[80] = 0;
6241
6242 edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_technician);
6243
6244 return 0;
6245 }
6246
6247
edf_set_equipment(int handle,const char * equipment)6248 int edf_set_equipment(int handle, const char *equipment)
6249 {
6250 if(handle<0)
6251 {
6252 return -1;
6253 }
6254
6255 if(handle>=EDFLIB_MAXFILES)
6256 {
6257 return -1;
6258 }
6259
6260 if(hdrlist[handle]==NULL)
6261 {
6262 return -1;
6263 }
6264
6265 if(!(hdrlist[handle]->writemode))
6266 {
6267 return -1;
6268 }
6269
6270 if(hdrlist[handle]->datarecords)
6271 {
6272 return -1;
6273 }
6274
6275 strncpy(hdrlist[handle]->plus_equipment, equipment, 80);
6276
6277 hdrlist[handle]->plus_equipment[80] = 0;
6278
6279 edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_equipment);
6280
6281 return 0;
6282 }
6283
6284
edf_set_recording_additional(int handle,const char * recording_additional)6285 int edf_set_recording_additional(int handle, const char *recording_additional)
6286 {
6287 if(handle<0)
6288 {
6289 return -1;
6290 }
6291
6292 if(handle>=EDFLIB_MAXFILES)
6293 {
6294 return -1;
6295 }
6296
6297 if(hdrlist[handle]==NULL)
6298 {
6299 return -1;
6300 }
6301
6302 if(!(hdrlist[handle]->writemode))
6303 {
6304 return -1;
6305 }
6306
6307 if(hdrlist[handle]->datarecords)
6308 {
6309 return -1;
6310 }
6311
6312 strncpy(hdrlist[handle]->plus_recording_additional, recording_additional, 80);
6313
6314 hdrlist[handle]->plus_recording_additional[80] = 0;
6315
6316 edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_recording_additional);
6317
6318 return 0;
6319 }
6320
6321
edf_set_startdatetime(int handle,int startdate_year,int startdate_month,int startdate_day,int starttime_hour,int starttime_minute,int starttime_second)6322 int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day,
6323 int starttime_hour, int starttime_minute, int starttime_second)
6324 {
6325 if(handle<0)
6326 {
6327 return -1;
6328 }
6329
6330 if(handle>=EDFLIB_MAXFILES)
6331 {
6332 return -1;
6333 }
6334
6335 if(hdrlist[handle]==NULL)
6336 {
6337 return -1;
6338 }
6339
6340 if(!(hdrlist[handle]->writemode))
6341 {
6342 return -1;
6343 }
6344
6345 if(hdrlist[handle]->datarecords)
6346 {
6347 return -1;
6348 }
6349
6350 if((startdate_year<1985) || (startdate_year>2084) ||
6351 (startdate_month<1) || (startdate_month>12) ||
6352 (startdate_day<1) || (startdate_day>31) ||
6353 (starttime_hour<0) || (starttime_hour>23) ||
6354 (starttime_minute<0) || (starttime_minute>59) ||
6355 (starttime_second<0) || (starttime_second>59))
6356 {
6357 return -1;
6358 }
6359
6360 hdrlist[handle]->startdate_year = startdate_year;
6361 hdrlist[handle]->startdate_month = startdate_month;
6362 hdrlist[handle]->startdate_day = startdate_day;
6363 hdrlist[handle]->starttime_hour = starttime_hour;
6364 hdrlist[handle]->starttime_minute = starttime_minute;
6365 hdrlist[handle]->starttime_second = starttime_second;
6366
6367 return 0;
6368 }
6369
6370
edfwrite_annotation_utf8(int handle,long long onset,long long duration,const char * description)6371 int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description)
6372 {
6373 int i;
6374
6375 struct edf_write_annotationblock *list_annot, *malloc_list;
6376
6377
6378 if(handle<0)
6379 {
6380 return -1;
6381 }
6382
6383 if(handle>=EDFLIB_MAXFILES)
6384 {
6385 return -1;
6386 }
6387
6388 if(hdrlist[handle]==NULL)
6389 {
6390 return -1;
6391 }
6392
6393 if(!(hdrlist[handle]->writemode))
6394 {
6395 return -1;
6396 }
6397
6398 if(onset<0LL)
6399 {
6400 return -1;
6401 }
6402
6403 if(hdrlist[handle]->annots_in_file >= hdrlist[handle]->annotlist_sz)
6404 {
6405 malloc_list = (struct edf_write_annotationblock *)realloc(write_annotationslist[handle],
6406 sizeof(struct edf_write_annotationblock) * (hdrlist[handle]->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ));
6407 if(malloc_list==NULL)
6408 {
6409 return -1;
6410 }
6411
6412 write_annotationslist[handle] = malloc_list;
6413
6414 hdrlist[handle]->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ;
6415 }
6416
6417 list_annot = write_annotationslist[handle] + hdrlist[handle]->annots_in_file;
6418
6419 list_annot->onset = onset;
6420 list_annot->duration = duration;
6421 strncpy(list_annot->annotation, description, EDFLIB_WRITE_MAX_ANNOTATION_LEN);
6422 list_annot->annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0;
6423
6424 for(i=0; ; i++)
6425 {
6426 if(list_annot->annotation[i] == 0)
6427 {
6428 break;
6429 }
6430
6431 if(((unsigned char *)(list_annot->annotation))[i] < 32)
6432 {
6433 list_annot->annotation[i] = '.';
6434 }
6435 }
6436
6437 hdrlist[handle]->annots_in_file++;
6438
6439 return 0;
6440 }
6441
6442
edfwrite_annotation_latin1(int handle,long long onset,long long duration,const char * description)6443 int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description)
6444 {
6445 struct edf_write_annotationblock *list_annot, *malloc_list;
6446
6447 char str[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1];
6448
6449
6450 if(handle<0)
6451 {
6452 return -1;
6453 }
6454
6455 if(handle>=EDFLIB_MAXFILES)
6456 {
6457 return -1;
6458 }
6459
6460 if(hdrlist[handle]==NULL)
6461 {
6462 return -1;
6463 }
6464
6465 if(!(hdrlist[handle]->writemode))
6466 {
6467 return -1;
6468 }
6469
6470 if(onset<0LL)
6471 {
6472 return -1;
6473 }
6474
6475 if(hdrlist[handle]->annots_in_file >= hdrlist[handle]->annotlist_sz)
6476 {
6477 malloc_list = (struct edf_write_annotationblock *)realloc(write_annotationslist[handle],
6478 sizeof(struct edf_write_annotationblock) * (hdrlist[handle]->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ));
6479 if(malloc_list==NULL)
6480 {
6481 return -1;
6482 }
6483
6484 write_annotationslist[handle] = malloc_list;
6485
6486 hdrlist[handle]->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ;
6487 }
6488
6489 list_annot = write_annotationslist[handle] + hdrlist[handle]->annots_in_file;
6490
6491 list_annot->onset = onset;
6492 list_annot->duration = duration;
6493 strncpy(str, description, EDFLIB_WRITE_MAX_ANNOTATION_LEN);
6494 str[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0;
6495 edflib_latin12utf8(str, strlen(str));
6496 strncpy(list_annot->annotation, str, EDFLIB_WRITE_MAX_ANNOTATION_LEN);
6497 list_annot->annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0;
6498
6499 hdrlist[handle]->annots_in_file++;
6500
6501 return 0;
6502 }
6503
6504
edflib_remove_padding_trailing_spaces(char * str)6505 static void edflib_remove_padding_trailing_spaces(char *str)
6506 {
6507 int i;
6508
6509 while(str[0]==' ')
6510 {
6511 for(i=0; ; i++)
6512 {
6513 if(str[i]==0)
6514 {
6515 break;
6516 }
6517
6518 str[i] = str[i+1];
6519 }
6520 }
6521
6522 for(i = strlen(str); i>0; i--)
6523 {
6524 if(str[i-1]==' ')
6525 {
6526 str[i-1] = 0;
6527 }
6528 else
6529 {
6530 break;
6531 }
6532 }
6533 }
6534
6535
edf_set_prefilter(int handle,int edfsignal,const char * prefilter)6536 int edf_set_prefilter(int handle, int edfsignal, const char *prefilter)
6537 {
6538 if(handle<0)
6539 {
6540 return -1;
6541 }
6542
6543 if(handle>=EDFLIB_MAXFILES)
6544 {
6545 return -1;
6546 }
6547
6548 if(hdrlist[handle]==NULL)
6549 {
6550 return -1;
6551 }
6552
6553 if(!(hdrlist[handle]->writemode))
6554 {
6555 return -1;
6556 }
6557
6558 if(edfsignal<0)
6559 {
6560 return -1;
6561 }
6562
6563 if(edfsignal>=hdrlist[handle]->edfsignals)
6564 {
6565 return -1;
6566 }
6567
6568 if(hdrlist[handle]->datarecords)
6569 {
6570 return -1;
6571 }
6572
6573 strncpy(hdrlist[handle]->edfparam[edfsignal].prefilter, prefilter, 80);
6574
6575 hdrlist[handle]->edfparam[edfsignal].prefilter[80] = 0;
6576
6577 edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].prefilter);
6578
6579 return 0;
6580 }
6581
6582
edf_set_transducer(int handle,int edfsignal,const char * transducer)6583 int edf_set_transducer(int handle, int edfsignal, const char *transducer)
6584 {
6585 if(handle<0)
6586 {
6587 return -1;
6588 }
6589
6590 if(handle>=EDFLIB_MAXFILES)
6591 {
6592 return -1;
6593 }
6594
6595 if(hdrlist[handle]==NULL)
6596 {
6597 return -1;
6598 }
6599
6600 if(!(hdrlist[handle]->writemode))
6601 {
6602 return -1;
6603 }
6604
6605 if(edfsignal<0)
6606 {
6607 return -1;
6608 }
6609
6610 if(edfsignal>=hdrlist[handle]->edfsignals)
6611 {
6612 return -1;
6613 }
6614
6615 if(hdrlist[handle]->datarecords)
6616 {
6617 return -1;
6618 }
6619
6620 strncpy(hdrlist[handle]->edfparam[edfsignal].transducer, transducer, 80);
6621
6622 hdrlist[handle]->edfparam[edfsignal].transducer[80] = 0;
6623
6624 edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].transducer);
6625
6626 return 0;
6627 }
6628
6629
6630 /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */
6631 /* if sign is zero, only negative numbers will have the sign '-' character */
6632 /* if sign is one, the sign '+' or '-' character will always be printed */
6633 /* returns the amount of characters printed */
edflib_fprint_int_number_nonlocalized(FILE * file,int q,int minimum,int sign)6634 static int edflib_fprint_int_number_nonlocalized(FILE *file, int q, int minimum, int sign)
6635 {
6636 int flag=0, z, i, j=0, base = 1000000000;
6637
6638 if(minimum < 0)
6639 {
6640 minimum = 0;
6641 }
6642
6643 if(minimum > 9)
6644 {
6645 flag = 1;
6646 }
6647
6648 if(q < 0)
6649 {
6650 fputc('-', file);
6651
6652 j++;
6653
6654 base = -base;
6655 }
6656 else
6657 {
6658 if(sign)
6659 {
6660 fputc('+', file);
6661
6662 j++;
6663 }
6664 }
6665
6666 for(i=10; i; i--)
6667 {
6668 if(minimum == i)
6669 {
6670 flag = 1;
6671 }
6672
6673 z = q / base;
6674
6675 q %= base;
6676
6677 if(z || flag)
6678 {
6679 fputc('0' + z, file);
6680
6681 j++;
6682
6683 flag = 1;
6684 }
6685
6686 base /= 10;
6687 }
6688
6689 if(!flag)
6690 {
6691 fputc('0', file);
6692
6693 j++;
6694 }
6695
6696 return j;
6697 }
6698
6699
6700 /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */
6701 /* if sign is zero, only negative numbers will have the sign '-' character */
6702 /* if sign is one, the sign '+' or '-' character will always be printed */
6703 /* returns the amount of characters printed */
edflib_fprint_ll_number_nonlocalized(FILE * file,long long q,int minimum,int sign)6704 static int edflib_fprint_ll_number_nonlocalized(FILE *file, long long q, int minimum, int sign)
6705 {
6706 int flag=0, z, i, j=0;
6707
6708 long long base = 1000000000000000000LL;
6709
6710 if(minimum < 0)
6711 {
6712 minimum = 0;
6713 }
6714
6715 if(minimum > 18)
6716 {
6717 flag = 1;
6718 }
6719
6720 if(q < 0LL)
6721 {
6722 fputc('-', file);
6723
6724 j++;
6725
6726 base = -base;
6727 }
6728 else
6729 {
6730 if(sign)
6731 {
6732 fputc('+', file);
6733
6734 j++;
6735 }
6736 }
6737
6738 for(i=19; i; i--)
6739 {
6740 if(minimum == i)
6741 {
6742 flag = 1;
6743 }
6744
6745 z = q / base;
6746
6747 q %= base;
6748
6749 if(z || flag)
6750 {
6751 fputc('0' + z, file);
6752
6753 j++;
6754
6755 flag = 1;
6756 }
6757
6758 base /= 10LL;
6759 }
6760
6761 if(!flag)
6762 {
6763 fputc('0', file);
6764
6765 j++;
6766 }
6767
6768 return j;
6769 }
6770
6771
6772 /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */
6773 /* if sign is zero, only negative numbers will have the sign '-' character */
6774 /* if sign is one, the sign '+' or '-' character will always be printed */
6775 /* returns the amount of characters printed */
6776 /*
6777 static int edflib_sprint_int_number_nonlocalized(char *str, int q, int minimum, int sign)
6778 {
6779 int flag=0, z, i, j=0, base = 1000000000;
6780
6781 if(minimum < 0)
6782 {
6783 minimum = 0;
6784 }
6785
6786 if(minimum > 9)
6787 {
6788 flag = 1;
6789 }
6790
6791 if(q < 0)
6792 {
6793 str[j++] = '-';
6794
6795 q = -q;
6796 }
6797 else
6798 {
6799 if(sign)
6800 {
6801 str[j++] = '+';
6802 }
6803 }
6804
6805 for(i=10; i; i--)
6806 {
6807 if(minimum == i)
6808 {
6809 flag = 1;
6810 }
6811
6812 z = q / base;
6813
6814 q %= base;
6815
6816 if(z || flag)
6817 {
6818 str[j++] = '0' + z;
6819
6820 flag = 1;
6821 }
6822
6823 base /= 10;
6824 }
6825
6826 if(!flag)
6827 {
6828 str[j++] = '0';
6829 }
6830
6831 str[j] = 0;
6832
6833 return j;
6834 }
6835 */
6836
6837 /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */
6838 /* if sign is zero, only negative numbers will have the sign '-' character */
6839 /* if sign is one, the sign '+' or '-' character will always be printed */
6840 /* returns the amount of characters printed */
edflib_snprint_ll_number_nonlocalized(char * dest,long long q,int minimum,int sign,int sz)6841 static int edflib_snprint_ll_number_nonlocalized(char *dest, long long q, int minimum, int sign, int sz)
6842 {
6843 int flag=0, z, i, j=0;
6844
6845 long long base = 1000000000000000000LL;
6846
6847 if(sz < 1)
6848 {
6849 return 0;
6850 }
6851
6852 if(minimum < 0)
6853 {
6854 minimum = 0;
6855 }
6856
6857 if(minimum > 18)
6858 {
6859 flag = 1;
6860 }
6861
6862 if(q < 0LL)
6863 {
6864 dest[j++] = '-';
6865
6866 base = -base;
6867 }
6868 else
6869 {
6870 if(sign)
6871 {
6872 dest[j++] = '+';
6873 }
6874 }
6875
6876 if(j == sz)
6877 {
6878 dest[--j] = 0;
6879
6880 return j;
6881 }
6882
6883 for(i=19; i; i--)
6884 {
6885 if(minimum == i)
6886 {
6887 flag = 1;
6888 }
6889
6890 z = q / base;
6891
6892 q %= base;
6893
6894 if(z || flag)
6895 {
6896 dest[j++] = '0' + z;
6897
6898 if(j == sz)
6899 {
6900 dest[--j] = 0;
6901
6902 return j;
6903 }
6904
6905 flag = 1;
6906 }
6907
6908 base /= 10LL;
6909 }
6910
6911 if(!flag)
6912 {
6913 dest[j++] = '0';
6914 }
6915
6916 if(j == sz)
6917 {
6918 dest[--j] = 0;
6919
6920 return j;
6921 }
6922
6923 dest[j] = 0;
6924
6925 return j;
6926 }
6927
6928
edflib_snprint_number_nonlocalized(char * dest,double val,int sz)6929 static int edflib_snprint_number_nonlocalized(char *dest, double val, int sz)
6930 {
6931 int flag=0, z, i, j=0, q, base = 1000000000;
6932
6933 double var;
6934
6935 if(sz < 1) return 0;
6936
6937 q = (int)val;
6938
6939 var = val - q;
6940
6941 if(val < 0.0)
6942 {
6943 dest[j++] = '-';
6944
6945 if(q < 0)
6946 {
6947 base = -base;
6948 }
6949 }
6950
6951 if(j == sz)
6952 {
6953 dest[--j] = 0;
6954
6955 return j;
6956 }
6957
6958 for(i=10; i; i--)
6959 {
6960 z = q / base;
6961
6962 q %= base;
6963
6964 if(z || flag)
6965 {
6966 dest[j++] = '0' + z;
6967
6968 if(j == sz)
6969 {
6970 dest[--j] = 0;
6971
6972 return j;
6973 }
6974
6975 flag = 1;
6976 }
6977
6978 base /= 10;
6979 }
6980
6981 if(!flag)
6982 {
6983 dest[j++] = '0';
6984 }
6985
6986 if(j == sz)
6987 {
6988 dest[--j] = 0;
6989
6990 return j;
6991 }
6992
6993 base = 100000000;
6994
6995 var *= (base * 10);
6996
6997 q = (int)var;
6998
6999 if(q < 0)
7000 {
7001 base = -base;
7002 }
7003
7004 if(!q)
7005 {
7006 dest[j] = 0;
7007
7008 return j;
7009 }
7010
7011 dest[j++] = '.';
7012
7013 if(j == sz)
7014 {
7015 dest[--j] = 0;
7016
7017 return j;
7018 }
7019
7020 for(i=9; i; i--)
7021 {
7022 z = q / base;
7023
7024 q %= base;
7025
7026 dest[j++] = '0' + z;
7027
7028 if(j == sz)
7029 {
7030 dest[--j] = 0;
7031
7032 return j;
7033 }
7034
7035 base /= 10;
7036 }
7037
7038 dest[j] = 0;
7039
7040 j--;
7041
7042 for(; j>0; j--)
7043 {
7044 if(dest[j] == '0')
7045 {
7046 dest[j] = 0;
7047 }
7048 else
7049 {
7050 j++;
7051
7052 break;
7053 }
7054 }
7055
7056 return j;
7057 }
7058
7059
edflib_atof_nonlocalized(const char * str)7060 static double edflib_atof_nonlocalized(const char *str)
7061 {
7062 int i=0, j, dot_pos=-1, decimals=0, sign=1, exp_pos=-1, exp_sign=1, exp_val=0;
7063
7064 double value, value2=0.0;
7065
7066
7067 value = edflib_atoi_nonlocalized(str);
7068
7069 while(str[i] == ' ')
7070 {
7071 i++;
7072 }
7073
7074 if((str[i] == '+') || (str[i] == '-'))
7075 {
7076 if(str[i] == '-')
7077 {
7078 sign = -1;
7079 }
7080
7081 i++;
7082 }
7083
7084 for(; ; i++)
7085 {
7086 if(str[i] == 0)
7087 {
7088 break;
7089 }
7090
7091 if((str[i] == 'e') || (str[i] == 'E'))
7092 {
7093 exp_pos = i;
7094
7095 break;
7096 }
7097
7098 if(((str[i] < '0') || (str[i] > '9')) && (str[i] != '.'))
7099 {
7100 break;
7101 }
7102
7103 if(dot_pos >= 0)
7104 {
7105 if((str[i] >= '0') && (str[i] <= '9'))
7106 {
7107 decimals++;
7108 }
7109 else
7110 {
7111 break;
7112 }
7113 }
7114
7115 if(str[i] == '.')
7116 {
7117 if(dot_pos < 0)
7118 {
7119 dot_pos = i;
7120 }
7121 }
7122 }
7123
7124 if(decimals)
7125 {
7126 value2 = edflib_atoi_nonlocalized(str + dot_pos + 1) * sign;
7127
7128 i = 1;
7129
7130 while(decimals--)
7131 {
7132 i *= 10;
7133 }
7134
7135 value2 /= i;
7136
7137 value += value2;
7138 }
7139
7140 if(exp_pos > 0)
7141 {
7142 i = exp_pos + 1;
7143
7144 if(str[i])
7145 {
7146 if(str[i] == '+')
7147 {
7148 i++;
7149 }
7150 else if(str[i] == '-')
7151 {
7152 exp_sign = -1;
7153
7154 i++;
7155 }
7156
7157 if(str[i])
7158 {
7159 exp_val = edflib_atoi_nonlocalized(str + i);
7160
7161 if(exp_val > 0)
7162 {
7163 for(j=0; j<exp_val; j++)
7164 {
7165 if(exp_sign > 0)
7166 {
7167 value *= 10;
7168 }
7169 else
7170 {
7171 value /= 10;
7172 }
7173 }
7174 }
7175 }
7176 }
7177 }
7178
7179 return value;
7180 }
7181
7182
edflib_atoi_nonlocalized(const char * str)7183 static int edflib_atoi_nonlocalized(const char *str)
7184 {
7185 int i=0, value=0, sign=1;
7186
7187 while(str[i] == ' ')
7188 {
7189 i++;
7190 }
7191
7192 if((str[i] == '+') || (str[i] == '-'))
7193 {
7194 if(str[i] == '-')
7195 {
7196 sign = -1;
7197 }
7198
7199 i++;
7200 }
7201
7202 for( ; ; i++)
7203 {
7204 if(str[i] == 0)
7205 {
7206 break;
7207 }
7208
7209 if((str[i] < '0') || (str[i] > '9'))
7210 {
7211 break;
7212 }
7213
7214 value *= 10;
7215
7216 value += ((str[i] - '0') * sign);
7217 }
7218
7219 return value;
7220 }
7221
7222
edflib_write_tal(struct edfhdrblock * hdr,FILE * file)7223 static int edflib_write_tal(struct edfhdrblock *hdr, FILE *file)
7224 {
7225 int p;
7226
7227 char str[EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)];
7228
7229 p = edflib_snprint_ll_number_nonlocalized(str, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1, EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1));
7230 if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset))
7231 {
7232 str[p++] = '.';
7233 p += edflib_snprint_ll_number_nonlocalized(str + p, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0, (EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)) - p);
7234 }
7235 str[p++] = 20;
7236 str[p++] = 20;
7237 for(; p<hdr->total_annot_bytes; p++)
7238 {
7239 str[p] = 0;
7240 }
7241
7242 if(fwrite(str, hdr->total_annot_bytes, 1, file) != 1)
7243 {
7244 return -1;
7245 }
7246
7247 return 0;
7248 }
7249
7250
edflib_strlcpy(char * dst,const char * src,int sz)7251 static int edflib_strlcpy(char *dst, const char *src, int sz)
7252 {
7253 int srclen;
7254
7255 sz--;
7256
7257 srclen = strlen(src);
7258
7259 if(srclen > sz) srclen = sz;
7260
7261 memcpy(dst, src, srclen);
7262
7263 dst[srclen] = 0;
7264
7265 return srclen;
7266 }
7267
7268
edflib_strlcat(char * dst,const char * src,int sz)7269 static int edflib_strlcat(char *dst, const char *src, int sz)
7270 {
7271 int srclen,
7272 dstlen;
7273
7274 dstlen = strlen(dst);
7275
7276 sz -= dstlen + 1;
7277
7278 if(!sz) return dstlen;
7279
7280 srclen = strlen(src);
7281
7282 if(srclen > sz) srclen = sz;
7283
7284 memcpy(dst + dstlen, src, srclen);
7285
7286 dst[dstlen + srclen] = 0;
7287
7288 return (dstlen + srclen);
7289 }
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317