diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index f35f6bde..70aa2724 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -10,9 +10,9 @@ jobs: OS: ${{ matrix.os }} PYTHON: '3.9' steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@master + uses: actions/setup-python@v5 with: python-version: 3.9 - name: Generate coverage report @@ -23,7 +23,7 @@ jobs: pip install -r requirements-test.txt pytest --cov=./pyedflib/ --cov-report=xml --cov-config=.coveragerc - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v5 with: directory: . env_vars: OS,PYTHON diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d75f9abe..7194f985 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,11 +9,11 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-2019, windows-latest, macos-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install packages diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index e81def40..4661c290 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -20,16 +20,16 @@ jobs: name: Make SDist runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.8' - name: Install deps run: python -m pip install build twine - name: Build SDist run: python -m build --sdist - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: path: dist/*.tar.gz - name: Check metadata @@ -42,10 +42,10 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Used to host cibuildwheel - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: '3.8' - name: Install cibuildwheel @@ -58,7 +58,7 @@ jobs: CIBW_SKIP: pp* CIBW_PRERELEASE_PYTHONS: False - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: path: wheelhouse/*.whl @@ -67,16 +67,16 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: [37, 38, 39, 310, 311] + python: [38, 39, 310, 311, 312, 313] include: - os: ubuntu-latest arch: aarch64 platform_id: manylinux_aarch64 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Install cibuildwheel run: python -m pip install cibuildwheel @@ -86,7 +86,7 @@ jobs: env: CIBW_ARCHS_LINUX: ${{matrix.arch}} CIBW_BUILD: cp${{ matrix.python }}-${{ matrix.platform_id }} - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: path: wheelhouse/*.whl @@ -95,7 +95,7 @@ jobs: needs: [build_wheels, build_aarch64_wheels, make_sdist] runs-on: ubuntu-20.04 steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: artifact path: dist diff --git a/pyedflib/_extensions/_pyedflib.pyx b/pyedflib/_extensions/_pyedflib.pyx index 472be1b2..d3b9625e 100644 --- a/pyedflib/_extensions/_pyedflib.pyx +++ b/pyedflib/_extensions/_pyedflib.pyx @@ -4,7 +4,7 @@ __doc__ = """Cython wrapper for low-level C edflib implementation.""" __all__ = ['lib_version', 'CyEdfReader', 'set_patientcode', 'set_starttime_subsecond', - 'write_annotation_latin1', 'write_annotation_utf8', 'set_technician', 'EdfAnnotation', + 'write_annotation_latin1_hr', 'write_annotation_utf8_hr', 'set_technician', 'EdfAnnotation', 'get_annotation', 'read_int_samples', 'blockwrite_digital_samples', 'blockwrite_physical_samples', 'set_recording_additional', 'write_physical_samples' ,'set_patientname', 'set_physical_minimum', 'read_physical_samples', 'close_file', 'set_physical_maximum', 'open_file_writeonly', @@ -277,7 +277,7 @@ cdef class CyEdfReader: property gender: def __get__(self): warnings.warn("Variable 'gender' is deprecated, use 'sex' instead.", DeprecationWarning, stacklevel=2) - return self.hdr.gender + return self.hdr.sex property birthdate: def __get__(self): @@ -436,11 +436,11 @@ def set_patientcode(int handle, char *patientcode): # check if rw? return c_edf.edf_set_patientcode(handle, patientcode) -cpdef int write_annotation_latin1(int handle, long long onset, long long duration, char *description): - return c_edf.edfwrite_annotation_latin1(handle, onset, duration, description) +cpdef int write_annotation_latin1_hr(int handle, long long onset, long long duration, char *description): + return c_edf.edfwrite_annotation_latin1_hr(handle, onset, duration, description) -cpdef int write_annotation_utf8(int handle, long long onset, long long duration, char *description): - return c_edf.edfwrite_annotation_utf8(handle, onset, duration, description) +cpdef int write_annotation_utf8_hr(int handle, long long onset, long long duration, char *description): + return c_edf.edfwrite_annotation_utf8_hr(handle, onset, duration, description) cpdef int set_technician(int handle, char *technician): return c_edf.edf_set_technician(handle, technician) @@ -598,11 +598,11 @@ def rewind(handle, edfsignal): def set_sex(handle, sex): """int edf_set_sex(int handle, int sex)""" if sex is None: return 0 #don't set sex at all to prevent default 'F' - return c_edf.edf_set_gender(handle, sex) + return c_edf.edf_set_sex(handle, sex) def set_gender(handle, gender): warnings.warn("Function 'set_gender' is deprecated, use 'set_sex' instead.", DeprecationWarning, stacklevel=2) - return set_sex(handle, gender) + return c_edf.edf_set_sex(handle, gender) def set_physical_dimension(handle, edfsignal, phys_dim): """int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim)""" diff --git a/pyedflib/_extensions/c/edflib.c b/pyedflib/_extensions/c/edflib.c index 8820bb06..cb536f69 100644 --- a/pyedflib/_extensions/c/edflib.c +++ b/pyedflib/_extensions/c/edflib.c @@ -1,7 +1,7 @@ /* ***************************************************************************** * -* Copyright (c) 2009 - 2020 Teunis van Beelen +* Copyright (c) 2009 - 2023 Teunis van Beelen * All rights reserved. * * Email: teuniz@protonmail.com @@ -31,22 +31,14 @@ ***************************************************************************** */ - - - /* compile with options "-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE" */ -#pragma warning( disable : 4996 ) // ignore unsafe strncpy -#pragma warning( disable : 4244 ) // ignore precision loss - #include "edflib.h" - -#define EDFLIB_VERSION (117) +#define EDFLIB_VERSION (124) #define EDFLIB_MAXFILES (64) - -#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__HAIKU__) +#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__HAIKU__) || defined(__ANDROID__) #define fopeno fopen @@ -58,7 +50,6 @@ #endif - #ifdef _WIN32 #ifndef __MINGW32__ @@ -76,117 +67,123 @@ #endif - - /* max size of annotationtext */ #define EDFLIB_WRITE_MAX_ANNOTATION_LEN (40) /* bytes in datarecord for EDF annotations, must be an integer multiple of three and two */ -#define EDFLIB_ANNOTATION_BYTES (114) +#define EDFLIB_ANNOTATION_BYTES (120) /* for writing only */ #define EDFLIB_MAX_ANNOTATION_CHANNELS (64) #define EDFLIB_ANNOT_MEMBLOCKSZ (1000) +typedef struct +{ + char label[17]; + char transducer[81]; + char physdimension[9]; + double phys_min; + double phys_max; + int dig_min; + int dig_max; + char prefilter[81]; + int smp_per_record; + char reserved[33]; + double offset; + int buf_offset; + double bitvalue; + int annotation; + long long sample_pntr; +} edfparamblock_t; + +typedef struct +{ + FILE *file_hdl; + char path[1024]; + int writemode; + char version[32]; + char patient[81]; + char recording[81]; + char plus_patientcode[81]; + char plus_sex[16]; + char plus_birthdate[16]; + int plus_birthdate_day; + int plus_birthdate_month; + int plus_birthdate_year; + char plus_patient_name[81]; + char plus_patient_additional[81]; + char plus_startdate[16]; + char plus_admincode[81]; + char plus_technician[81]; + char plus_equipment[81]; + char plus_recording_additional[81]; + long long l_starttime; + int startdate_day; + int startdate_month; + int startdate_year; + int starttime_second; + int starttime_minute; + int starttime_hour; + char reserved[45]; + int hdrsize; + int edfsignals; + long long datarecords; + int recordsize; + int annot_ch[EDFLIB_MAXSIGNALS]; + int nr_annot_chns; + int mapped_signals[EDFLIB_MAXSIGNALS]; + int edf; + int edfplus; + int bdf; + int bdfplus; + int discontinuous; + int signal_write_sequence_pos; + long long starttime_offset; + double data_record_duration; + long long long_data_record_duration; + int annots_in_file; + int annotlist_sz; + int total_annot_bytes; + int eq_sf; + char *wrbuf; + int wrbufsize; + edfparamblock_t *edfparam; +} edfhdrblock_t; + +typedef struct +{ + long long onset; + long long duration_l; + char duration[20]; + char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; +} edf_read_annotationblock_t; + +static edf_read_annotationblock_t *annotationslist[EDFLIB_MAXFILES]; + +typedef struct +{ + long long onset; + long long duration; + char annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1]; +} edf_write_annotationblock_t; -struct edfparamblock{ - char label[17]; - char transducer[81]; - char physdimension[9]; - double phys_min; - double phys_max; - int dig_min; - int dig_max; - char prefilter[81]; - int smp_per_record; - char reserved[33]; - double offset; - int buf_offset; - double bitvalue; - int annotation; - long long sample_pntr; - }; - -struct edfhdrblock{ - FILE *file_hdl; - char path[1024]; - int writemode; - char version[32]; - char patient[81]; - char recording[81]; - char plus_patientcode[81]; - char plus_gender[16]; - char plus_birthdate[16]; - char plus_patient_name[81]; - char plus_patient_additional[81]; - char plus_startdate[16]; - char plus_admincode[81]; - char plus_technician[81]; - char plus_equipment[81]; - char plus_recording_additional[81]; - long long l_starttime; - int startdate_day; - int startdate_month; - int startdate_year; - int starttime_second; - int starttime_minute; - int starttime_hour; - char reserved[45]; - int hdrsize; - int edfsignals; - long long datarecords; - int recordsize; - int annot_ch[EDFLIB_MAXSIGNALS]; - int nr_annot_chns; - int mapped_signals[EDFLIB_MAXSIGNALS]; - int edf; - int edfplus; - int bdf; - int bdfplus; - int discontinuous; - int signal_write_sequence_pos; - long long starttime_offset; - double data_record_duration; - long long long_data_record_duration; - int annots_in_file; - int annotlist_sz; - int total_annot_bytes; - int eq_sf; - char *wrbuf; - int wrbufsize; - struct edfparamblock *edfparam; - }; - - -static struct edf_annotationblock{ - long long onset; - char duration[16]; - char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; - } *annotationslist[EDFLIB_MAXFILES]; - - -static struct edf_write_annotationblock{ - long long onset; - long long duration; - char annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1]; - } *write_annotationslist[EDFLIB_MAXFILES]; +static edf_write_annotationblock_t *write_annotationslist[EDFLIB_MAXFILES]; static int edf_files_open=0; -static struct edfhdrblock *hdrlist[EDFLIB_MAXFILES]; - +static edfhdrblock_t *hdrlist[EDFLIB_MAXFILES]; -static struct edfhdrblock * edflib_check_edf_file(FILE *, int *, int); -static int edflib_repair_file_size(const char *path, struct edfhdrblock *edfhdr); +static edfhdrblock_t * edflib_check_edf_file(FILE *, int *, int); +static int edflib_repair_file_size(const char *, edfhdrblock_t *); static int edflib_is_integer_number(char *); static int edflib_is_number(char *); static long long edflib_get_long_duration(char *); -static int edflib_get_annotations(struct edfhdrblock *, int, int); +static int edflib_get_annotations(edfhdrblock_t *, int, int); static int edflib_is_duration_number(char *); static int edflib_is_onset_number(char *); static long long edflib_get_long_time(char *); -static int edflib_write_edf_header(struct edfhdrblock *); +static int edflib_write_edf_header(edfhdrblock_t *); static void edflib_latin1_to_ascii(char *, int); static void edflib_latin12utf8(char *, int); static void edflib_remove_padding_trailing_spaces(char *); @@ -199,41 +196,34 @@ static int edflib_sprint_int_number_nonlocalized(char *, int, int, int); static int edflib_snprint_ll_number_nonlocalized(char *, long long, int, int, int); static int edflib_fprint_int_number_nonlocalized(FILE *, int, int, int); static int edflib_fprint_ll_number_nonlocalized(FILE *, long long, int, int); -static int edflib_write_tal(struct edfhdrblock *, FILE *); +static int edflib_write_tal(edfhdrblock_t *, FILE *); static int edflib_strlcpy(char *, const char *, int); static int edflib_strlcat(char *, const char *, int); - - -int edflib_is_file_used(const char *path) +EDFLIB_API int edflib_is_file_used(const char *path) { - int i, file_used=0; + int i; for(i=0; ipath))) - { - file_used= 1; - - break; - } + if(!(strcmp(path, hdrlist[i]->path))) return 1; } } - return file_used ; + return 0; } -int edflib_get_number_of_open_files() +EDFLIB_API int edflib_get_number_of_open_files() { return edf_files_open; } -int edflib_get_handle(int file_number) +EDFLIB_API int edflib_get_handle(int file_number) { int i, file_count=0; @@ -241,10 +231,7 @@ int edflib_get_handle(int file_number) { if(hdrlist[i]!=NULL) { - if(file_count++ == file_number) - { - return i; - } + if(file_count++ == file_number) return i; } } @@ -252,7 +239,7 @@ int edflib_get_handle(int file_number) } -int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int read_annotations, int check_file_size) +EDFLIB_API int edfopen_file_readonly(const char *path, edflib_hdr_t *edfhdr, int read_annotations_mode, int check_file_size) { int i, j, channel, @@ -260,17 +247,42 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r FILE *file; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; + + union + { + char four[4]; + int one; + } byte_order_test_var; + memset(edfhdr, 0, sizeof(edflib_hdr_t)); - if(read_annotations<0) + /* avoid surprises! */ + if((sizeof(char) != 1) || + (sizeof(short) != 2) || + (sizeof(int) != 4) || + (sizeof(long long) != 8) || + (sizeof(float) != 4) || + (sizeof(double) != 8)) { - edfhdr->filetype = EDFLIB_INVALID_READ_ANNOTS_VALUE; + edfhdr->filetype = EDFLIB_ARCH_ERROR; + + return -1; + } + + /* check endianness! */ + byte_order_test_var.one = 0x03020100; + if((byte_order_test_var.four[0] != 0) || + (byte_order_test_var.four[1] != 1) || + (byte_order_test_var.four[2] != 2) || + (byte_order_test_var.four[3] != 3)) + { + edfhdr->filetype = EDFLIB_ARCH_ERROR; return -1; } - if(read_annotations>2) + if((read_annotations_mode<0)||(read_annotations_mode>2)) { edfhdr->filetype = EDFLIB_INVALID_READ_ANNOTS_VALUE; @@ -280,19 +292,13 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r if(check_file_size<0) { edfhdr->filetype = EDFLIB_INVALID_CHECK_SIZE_VALUE; - - return -1; } - if(check_file_size>2) { edfhdr->filetype = EDFLIB_INVALID_CHECK_SIZE_VALUE; - return -1; } - - memset(edfhdr, 0, sizeof(struct edf_hdr_struct)); if(edf_files_open>=EDFLIB_MAXFILES) { @@ -322,8 +328,8 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r return -1; } - hdr = edflib_check_edf_file(file, &edf_error,check_file_size); - if (hdr==NULL && edf_error == EDFLIB_FILE_CONTAINS_FORMAT_ERRORS && check_file_size == EDFLIB_REPAIR_FILE_SIZE_IF_WRONG) + hdr = edflib_check_edf_file(file, &edf_error, check_file_size); + if (hdr==NULL && edf_error==EDFLIB_FILE_CONTAINS_FORMAT_ERRORS && check_file_size==EDFLIB_REPAIR_FILE_SIZE_IF_WRONG) { hdr = edflib_check_edf_file(file, &edf_error, EDFLIB_DO_NOT_CHECK_FILE_SIZE); fclose(file); @@ -333,7 +339,6 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r file = fopeno(path, "rb"); hdr = edflib_check_edf_file(file, &edf_error, EDFLIB_CHECK_FILE_SIZE); } - if(hdr==NULL) { edfhdr->filetype = edf_error; @@ -355,8 +360,6 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r return -1; } - hdr->writemode = 0; - for(i=0; ipatient, hdr->patient, 81); edflib_strlcpy(edfhdr->recording, hdr->recording, 81); - edfhdr->patientcode[0] = 0; - edfhdr->gender[0] = 0; - edfhdr->birthdate[0] = 0; - edfhdr->patient_name[0] = 0; - edfhdr->patient_additional[0] = 0; - edfhdr->admincode[0] = 0; - edfhdr->technician[0] = 0; - edfhdr->equipment[0] = 0; - edfhdr->recording_additional[0] = 0; } else { - edfhdr->patient[0] = 0; - edfhdr->recording[0] = 0; edflib_strlcpy(edfhdr->patientcode, hdr->plus_patientcode, 81); - edflib_strlcpy(edfhdr->gender, hdr->plus_gender, 16); + edflib_strlcpy(edfhdr->sex, hdr->plus_sex, 16); +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + edflib_strlcpy(edfhdr->gender, hdr->plus_sex, 16); +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif edflib_strlcpy(edfhdr->birthdate, hdr->plus_birthdate, 16); + edfhdr->birthdate_day = hdr->plus_birthdate_day; + edfhdr->birthdate_month = hdr->plus_birthdate_month; + edfhdr->birthdate_year = hdr->plus_birthdate_year; edflib_strlcpy(edfhdr->patient_name, hdr->plus_patient_name, 81); edflib_strlcpy(edfhdr->patient_additional, hdr->plus_patient_additional, 81); edflib_strlcpy(edfhdr->admincode, hdr->plus_admincode, 81); @@ -437,28 +440,25 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r edflib_strlcpy(edfhdr->equipment, hdr->plus_equipment, 81); edflib_strlcpy(edfhdr->recording_additional, hdr->plus_recording_additional, 81); - if((read_annotations==EDFLIB_READ_ANNOTATIONS)||(read_annotations==EDFLIB_READ_ALL_ANNOTATIONS)) + if(edflib_get_annotations(hdr, edfhdr->handle, read_annotations_mode)) { - if(edflib_get_annotations(hdr, edfhdr->handle, read_annotations)) - { - edfhdr->filetype = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; - - fclose(file); + edfhdr->filetype = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; - free(hdr->edfparam); - hdr->edfparam = NULL; - free(hdr); - hdr = NULL; - hdrlist[edfhdr->handle] = NULL; - free(annotationslist[edfhdr->handle]); - annotationslist[edfhdr->handle] = NULL; + fclose(file); - return -1; - } + free(hdr->edfparam); + hdr->edfparam = NULL; + free(hdr); + hdr = NULL; + hdrlist[edfhdr->handle] = NULL; + free(annotationslist[edfhdr->handle]); + annotationslist[edfhdr->handle] = NULL; - edfhdr->starttime_subsecond = hdr->starttime_offset; + return -1; } + edfhdr->starttime_subsecond = hdr->starttime_offset; + edfhdr->annotations_in_file = hdr->annots_in_file; } @@ -496,9 +496,9 @@ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int r } -int edfclose_file(int handle) +EDFLIB_API int edfclose_file(int handle) { - struct edf_write_annotationblock *annot2; + edf_write_annotationblock_t *annot2; int i, j, k, n, p, err, datrecsize, @@ -509,23 +509,12 @@ int edfclose_file(int handle) char str[EDFLIB_ANNOTATION_BYTES * 2]; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; hdr = hdrlist[handle]; @@ -553,13 +542,10 @@ int edfclose_file(int handle) edf_files_open--; return err; - } for(k=0; kannots_in_file; k++) { - annot2 = write_annotationslist[handle] + k; - p = edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1); if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset)) @@ -618,7 +604,7 @@ int edfclose_file(int handle) { annot2 = write_annotationslist[handle] + k; - annot2->onset += hdr->starttime_offset / 1000LL; + annot2->onset += hdr->starttime_offset / 10LL; p = 0; @@ -642,23 +628,23 @@ int edfclose_file(int handle) str[p++] = 0; } - n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->onset / 10000LL, 0, 1, (EDFLIB_ANNOTATION_BYTES * 2) - p); + n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->onset / 1000000LL, 0, 1, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; - if(annot2->onset % 10000LL) + if(annot2->onset % 1000000LL) { str[p++] = '.'; - n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->onset % 10000LL, 4, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); + n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->onset % 1000000LL, 6, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; } if(annot2->duration>=0LL) { str[p++] = 21; - n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->duration / 10000LL, 0, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); + n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->duration / 1000000LL, 0, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; - if(annot2->duration % 10000LL) + if(annot2->duration % 1000000LL) { str[p++] = '.'; - n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->duration % 10000LL, 4, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); + n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->duration % 1000000LL, 6, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; } } @@ -726,42 +712,21 @@ int edfclose_file(int handle) } -long long edfseek(int handle, int edfsignal, long long offset, int whence) +EDFLIB_API long long edfseek(int handle, int edfsignal, long long offset, int whence) { long long smp_in_file; int channel; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(edfsignal<0) - { - return -1; - } + if(edfsignal<0) return -1; - if(hdrlist[handle]->writemode) - { - return -1; - } + if(hdrlist[handle]->writemode) return -1; - if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) - { - return -1; - } + if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) return -1; channel = hdrlist[handle]->mapped_signals[edfsignal]; @@ -797,40 +762,19 @@ long long edfseek(int handle, int edfsignal, long long offset, int whence) } -long long edftell(int handle, int edfsignal) +EDFLIB_API long long edftell(int handle, int edfsignal) { int channel; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(edfsignal<0) - { - return -1; - } + if(edfsignal<0) return -1; - if(hdrlist[handle]->writemode) - { - return -1; - } + if(hdrlist[handle]->writemode) return -1; - if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) - { - return -1; - } + if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) return -1; channel = hdrlist[handle]->mapped_signals[edfsignal]; @@ -838,40 +782,19 @@ long long edftell(int handle, int edfsignal) } -void edfrewind(int handle, int edfsignal) +EDFLIB_API void edfrewind(int handle, int edfsignal) { int channel; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return; - if(handle<0) - { - return; - } - - if(handle>=EDFLIB_MAXFILES) - { - return; - } - - if(hdrlist[handle]==NULL) - { - return; - } + if(hdrlist[handle]==NULL) return; - if(edfsignal<0) - { - return; - } + if(edfsignal<0) return; - if(hdrlist[handle]->writemode) - { - return; - } + if(hdrlist[handle]->writemode) return; - if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) - { - return; - } + if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) return; channel = hdrlist[handle]->mapped_signals[edfsignal]; @@ -879,7 +802,7 @@ void edfrewind(int handle, int edfsignal) } -int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) +EDFLIB_API int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) { int bytes_per_smpl=2, tmp, @@ -895,7 +818,7 @@ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) smp_per_record, jump; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; union { unsigned int one; @@ -907,48 +830,21 @@ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) FILE *file; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(edfsignal<0) - { - return -1; - } + if(edfsignal<0) return -1; - if(hdrlist[handle]->writemode) - { - return -1; - } + if(hdrlist[handle]->writemode) return -1; - if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) - { - return -1; - } + if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) return -1; channel = hdrlist[handle]->mapped_signals[edfsignal]; - if(n<0LL) - { - return -1; - } + if(n<0LL) return -1; - if(n==0LL) - { - return 0LL; - } + if(n==0LL) return 0LL; hdr = hdrlist[handle]; @@ -968,15 +864,9 @@ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) { n = smp_in_file - hdr->edfparam[channel].sample_pntr; - if(n==0) - { - return 0LL; - } + if(n==0) return 0LL; - if(n<0) - { - return -1; - } + if(n<0) return -1; } file = hdr->file_hdl; @@ -1018,6 +908,15 @@ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) } var.four[1] = tmp; + if(var.two_signed[0] > hdr->edfparam[channel].dig_max) + { + var.two_signed[0] = hdr->edfparam[channel].dig_max; + } + else if(var.two_signed[0] < hdr->edfparam[channel].dig_min) + { + var.two_signed[0] = hdr->edfparam[channel].dig_min; + } + buf[i] = phys_bitvalue * (phys_offset + (double)var.two_signed[0]); sample_pntr++; @@ -1039,10 +938,7 @@ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) var.four[0] = fgetc(file); var.four[1] = fgetc(file); tmp = fgetc(file); - if(tmp==EOF) - { - return -1; - } + if(tmp==EOF) return -1; var.four[2] = tmp; if(var.four[2]&0x80) @@ -1054,6 +950,15 @@ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) var.four[3] = 0x00; } + if(var.one_signed > hdr->edfparam[channel].dig_max) + { + var.one_signed = hdr->edfparam[channel].dig_max; + } + else if(var.one_signed < hdr->edfparam[channel].dig_min) + { + var.one_signed = hdr->edfparam[channel].dig_min; + } + buf[i] = phys_bitvalue * (phys_offset + (double)var.one_signed); sample_pntr++; @@ -1066,7 +971,7 @@ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) } -int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) +EDFLIB_API int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) { int bytes_per_smpl=2, tmp, @@ -1079,7 +984,7 @@ int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) smp_per_record, jump; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; union { unsigned int one; @@ -1091,48 +996,21 @@ int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) FILE *file; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(edfsignal<0) - { - return -1; - } + if(edfsignal<0) return -1; - if(hdrlist[handle]->writemode) - { - return -1; - } + if(hdrlist[handle]->writemode) return -1; - if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) - { - return -1; - } + if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) return -1; channel = hdrlist[handle]->mapped_signals[edfsignal]; - if(n<0LL) - { - return -1; - } + if(n<0LL) return -1; - if(n==0LL) - { - return 0LL; - } + if(n==0LL) return 0LL; hdr = hdrlist[handle]; @@ -1192,11 +1070,17 @@ int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) var.four[0] = fgetc(file); tmp = fgetc(file); - if(tmp==EOF) + if(tmp==EOF) return -1; + var.four[1] = tmp; + + if(var.two_signed[0] > hdr->edfparam[channel].dig_max) { - return -1; + var.two_signed[0] = hdr->edfparam[channel].dig_max; } - var.four[1] = tmp; + else if(var.two_signed[0] < hdr->edfparam[channel].dig_min) + { + var.two_signed[0] = hdr->edfparam[channel].dig_min; + } buf[i] = var.two_signed[0]; @@ -1219,10 +1103,7 @@ int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) var.four[0] = fgetc(file); var.four[1] = fgetc(file); tmp = fgetc(file); - if(tmp==EOF) - { - return -1; - } + if(tmp==EOF) return -1; var.four[2] = tmp; if(var.four[2]&0x80) @@ -1234,6 +1115,15 @@ int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) var.four[3] = 0x00; } + if(var.one_signed > hdr->edfparam[channel].dig_max) + { + var.one_signed = hdr->edfparam[channel].dig_max; + } + else if(var.one_signed < hdr->edfparam[channel].dig_min) + { + var.one_signed = hdr->edfparam[channel].dig_min; + } + buf[i] = var.one_signed; sample_pntr++; @@ -1246,49 +1136,30 @@ int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) } -int edf_get_annotation(int handle, int n, struct edf_annotation_struct *annot) +EDFLIB_API int edf_get_annotation(int handle, int n, edflib_annotation_t *annot) { - memset(annot, 0, sizeof(struct edf_annotation_struct)); - - if(handle<0) - { - return -1; - } + memset(annot, 0, sizeof(edflib_annotation_t)); - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(hdrlist[handle]->writemode) - { - return -1; - } + if(hdrlist[handle]->writemode) return -1; - if(n<0) - { - return -1; - } + if(n<0) return -1; - if(n>=hdrlist[handle]->annots_in_file) - { - return -1; - } + if(n>=hdrlist[handle]->annots_in_file) return -1; annot->onset = (annotationslist[handle] + n)->onset; - edflib_strlcpy(annot->duration, (annotationslist[handle] + n)->duration, 16); + annot->duration_l = (annotationslist[handle] + n)->duration_l; + edflib_strlcpy(annot->duration, (annotationslist[handle] + n)->duration, 20); edflib_strlcpy(annot->annotation, (annotationslist[handle] + n)->annotation, EDFLIB_MAX_ANNOTATION_LEN + 1); return 0; } -static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_error, int check_file_size) +static edfhdrblock_t * edflib_check_edf_file(FILE *inputfile, int *edf_error, int check_file_size) { int i, j, p, r=0, n, dotposition, @@ -1298,7 +1169,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro scratchpad[128], scratchpad2[64]; - struct edfhdrblock *edfhdr; + edfhdrblock_t *edfhdr; /***************** check header ******************************/ @@ -1309,7 +1180,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - edfhdr = (struct edfhdrblock *)calloc(1, sizeof(struct edfhdrblock)); + edfhdr = (edfhdrblock_t *)calloc(1, sizeof(edfhdrblock_t)); if(edfhdr==NULL) { free(edf_hdr); @@ -1457,7 +1328,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro scratchpad[5] = 0; scratchpad[8] = 0; - if((edflib_atof_nonlocalized(scratchpad)<1)||(edflib_atof_nonlocalized(scratchpad)>31)) + if((edflib_atoi_nonlocalized(scratchpad)<1)||(edflib_atoi_nonlocalized(scratchpad)>31)) { strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; @@ -1467,7 +1338,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - if((edflib_atof_nonlocalized(scratchpad+3)<1)||(edflib_atof_nonlocalized(scratchpad+3)>12)) + if((edflib_atoi_nonlocalized(scratchpad+3)<1)||(edflib_atoi_nonlocalized(scratchpad+3)>12)) { strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; @@ -1477,9 +1348,9 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - edfhdr->startdate_day = edflib_atof_nonlocalized(scratchpad); - edfhdr->startdate_month = edflib_atof_nonlocalized(scratchpad + 3); - edfhdr->startdate_year = edflib_atof_nonlocalized(scratchpad + 6); + edfhdr->startdate_day = edflib_atoi_nonlocalized(scratchpad); + edfhdr->startdate_month = edflib_atoi_nonlocalized(scratchpad + 3); + edfhdr->startdate_year = edflib_atoi_nonlocalized(scratchpad + 6); if(edfhdr->startdate_year>84) { edfhdr->startdate_year += 1900; @@ -1530,7 +1401,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro scratchpad[5] = 0; scratchpad[8] = 0; - if(edflib_atof_nonlocalized(scratchpad)>23) + if(edflib_atoi_nonlocalized(scratchpad)>23) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; @@ -1540,7 +1411,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - if(edflib_atof_nonlocalized(scratchpad+3)>59) + if(edflib_atoi_nonlocalized(scratchpad+3)>59) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; @@ -1550,7 +1421,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - if(edflib_atof_nonlocalized(scratchpad+6)>59) + if(edflib_atoi_nonlocalized(scratchpad+6)>59) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; @@ -1560,13 +1431,13 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - edfhdr->starttime_hour = edflib_atof_nonlocalized(scratchpad); - edfhdr->starttime_minute = edflib_atof_nonlocalized(scratchpad + 3); - edfhdr->starttime_second = edflib_atof_nonlocalized(scratchpad + 6); + edfhdr->starttime_hour = edflib_atoi_nonlocalized(scratchpad); + edfhdr->starttime_minute = edflib_atoi_nonlocalized(scratchpad + 3); + edfhdr->starttime_second = edflib_atoi_nonlocalized(scratchpad + 6); - edfhdr->l_starttime = 3600 * edflib_atof_nonlocalized(scratchpad); - edfhdr->l_starttime += 60 * edflib_atof_nonlocalized(scratchpad + 3); - edfhdr->l_starttime += edflib_atof_nonlocalized(scratchpad + 6); + edfhdr->l_starttime = 3600 * edflib_atoi_nonlocalized(scratchpad); + edfhdr->l_starttime += 60 * edflib_atoi_nonlocalized(scratchpad + 3); + edfhdr->l_starttime += edflib_atoi_nonlocalized(scratchpad + 6); edfhdr->l_starttime *= EDFLIB_TIME_DIMENSION; @@ -1592,7 +1463,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro free(edfhdr); return NULL; } - edfhdr->edfsignals = edflib_atof_nonlocalized(scratchpad); + edfhdr->edfsignals = edflib_atoi_nonlocalized(scratchpad); if(edfhdr->edfsignals<1) { *edf_error = EDFLIB_FILE_ERRORS_NUMBER_SIGNALS; @@ -1633,7 +1504,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - n = edflib_atof_nonlocalized(scratchpad); + n = edflib_atoi_nonlocalized(scratchpad); if((edfhdr->edfsignals * 256 + 256)!=n) { *edf_error = EDFLIB_FILE_ERRORS_BYTES_HEADER; @@ -1662,26 +1533,34 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro if(edfhdr->edf) { - if(!strncmp(scratchpad, "EDF+C", 5)) + if(!strncmp(scratchpad, "EDF+C ", 44)) { edfhdr->edfplus = 1; + edfhdr->discontinuous = 0; } - - if(!strncmp(scratchpad, "EDF+D", 5)) - { - edfhdr->edfplus = 1; - edfhdr->discontinuous = 1; - } + else if(!strncmp(scratchpad, "EDF+D ", 44)) + { + edfhdr->edfplus = 1; + edfhdr->discontinuous = 1; + } + else if(strncmp(scratchpad, " ", 44)) + { + *edf_error = EDFLIB_FILE_ERRORS_RESERVED_FIELD; + free(edf_hdr); + free(edfhdr); + return NULL; + } } if(edfhdr->bdf) { - if(!strncmp(scratchpad, "BDF+C", 5)) + if(!strncmp(scratchpad, "BDF+C ", 44)) { edfhdr->bdfplus = 1; + edfhdr->discontinuous = 0; } - if(!strncmp(scratchpad, "BDF+D", 5)) + if(!strncmp(scratchpad, "BDF+D ", 44)) { edfhdr->bdfplus = 1; edfhdr->discontinuous = 1; @@ -1715,7 +1594,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - edfhdr->datarecords = edflib_atof_nonlocalized(scratchpad); + edfhdr->datarecords = edflib_atoi_nonlocalized(scratchpad); if(edfhdr->datarecords<1) { *edf_error = EDFLIB_FILE_ERRORS_NUMBER_DATARECORDS; @@ -1780,7 +1659,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - edfhdr->edfparam = (struct edfparamblock *)calloc(1, sizeof(struct edfparamblock) * edfhdr->edfsignals); + edfhdr->edfparam = (edfparamblock_t *)calloc(1, sizeof(edfparamblock_t) * edfhdr->edfsignals); if(edfhdr->edfparam==NULL) { *edf_error = EDFLIB_MALLOC_ERROR; @@ -1845,8 +1724,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro } if((edfhdr->edfsignals!=edfhdr->nr_annot_chns)||((!edfhdr->edfplus)&&(!edfhdr->bdfplus))) { - //if(edfhdr->data_record_duration<0.0000001) - if(edfhdr->data_record_duration<0) + if(edfhdr->data_record_duration<0.0000001) { *edf_error = EDFLIB_FILE_ERRORS_LABEL; free(edf_hdr); @@ -2012,12 +1890,12 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - n = edflib_atof_nonlocalized(scratchpad); + n = edflib_atoi_nonlocalized(scratchpad); if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { - if(n!=-32768) + if(n!=-0x8000) { *edf_error = EDFLIB_FILE_ERRORS_DIG_MIN; free(edf_hdr); @@ -2031,7 +1909,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro { if(edfhdr->edfparam[i].annotation) { - if(n!=-8388608) + if(n!=-0x800000) { *edf_error = EDFLIB_FILE_ERRORS_DIG_MIN; free(edf_hdr); @@ -2043,7 +1921,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro } if(edfhdr->edf) { - if((n>32767)||(n<-32768)) + if((n>0x7fff)||(n<-0x8000)) { *edf_error = EDFLIB_FILE_ERRORS_DIG_MIN; free(edf_hdr); @@ -2054,7 +1932,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro } if(edfhdr->bdf) { - if((n>8388607)||(n<-8388608)) + if((n>0x7fffff)||(n<-0x800000)) { *edf_error = EDFLIB_FILE_ERRORS_DIG_MIN; free(edf_hdr); @@ -2094,12 +1972,12 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - n = edflib_atof_nonlocalized(scratchpad); + n = edflib_atoi_nonlocalized(scratchpad); if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { - if(n!=32767) + if(n!=0x7fff) { *edf_error = EDFLIB_FILE_ERRORS_DIG_MAX; free(edf_hdr); @@ -2113,7 +1991,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro { if(edfhdr->edfparam[i].annotation) { - if(n!=8388607) + if(n!=0x7fffff) { *edf_error = EDFLIB_FILE_ERRORS_DIG_MAX; free(edf_hdr); @@ -2125,7 +2003,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro } if(edfhdr->edf) { - if((n>32767)||(n<-32768)) + if((n>0x7fff)||(n<-0x8000)) { *edf_error = EDFLIB_FILE_ERRORS_DIG_MAX; free(edf_hdr); @@ -2136,7 +2014,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro } else { - if((n>8388607)||(n<-8388608)) + if((n>0x7fffff)||(n<-0x800000)) { *edf_error = EDFLIB_FILE_ERRORS_DIG_MAX; free(edf_hdr); @@ -2206,7 +2084,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - n = edflib_atof_nonlocalized(scratchpad); + n = edflib_atoi_nonlocalized(scratchpad); if(n<1) { *edf_error = EDFLIB_FILE_ERRORS_SAMPLES_DATARECORD; @@ -2312,7 +2190,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro if((scratchpad2[8]<48)||(scratchpad2[8]>57)) error = 1; if((scratchpad2[9]<48)||(scratchpad2[9]>57)) error = 1; if((scratchpad2[10]<48)||(scratchpad2[10]>57)) error = 1; - if((edflib_atof_nonlocalized(scratchpad2)<1)||(edflib_atof_nonlocalized(scratchpad2)>31)) error = 1; + if((edflib_atoi_nonlocalized(scratchpad2)<1)||(edflib_atoi_nonlocalized(scratchpad2)>31)) error = 1; if(strcmp(scratchpad2 + 3, "JAN")) if(strcmp(scratchpad2 + 3, "FEB")) if(strcmp(scratchpad2 + 3, "MAR")) @@ -2360,15 +2238,15 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro if(edfhdr->patient[p]=='M') { - edflib_strlcpy(edfhdr->plus_gender, "Male", 16); + edflib_strlcpy(edfhdr->plus_sex, "Male", 16); } if(edfhdr->patient[p]=='F') { - edflib_strlcpy(edfhdr->plus_gender, "Female", 16); + edflib_strlcpy(edfhdr->plus_sex, "Female", 16); } if(edfhdr->patient[p]=='X') { - edfhdr->plus_gender[0] = 0; + edfhdr->plus_sex[0] = 0; } for(i=0; i<(80-p);i++) { @@ -2379,9 +2257,12 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro } p += i + 1; - if(edfhdr->patient[p]=='X') + if(edfhdr->patient[p]=='X' && edfhdr->patient[p+1]==' ') { edfhdr->plus_birthdate[0] = 0; + edfhdr->plus_birthdate_day = 0; + edfhdr->plus_birthdate_month = 0; + edfhdr->plus_birthdate_year = 0; p += 2; } else @@ -2401,19 +2282,73 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro edfhdr->plus_birthdate[6] = ' '; edfhdr->plus_birthdate[11] = 0; p += i + 1; - } - - for(i=0; i<(80-p);i++) - { - if(edfhdr->patient[i+p]==' ') + edfhdr->plus_birthdate_day = edflib_atoi_nonlocalized(edfhdr->plus_birthdate); + if(!strncmp(edfhdr->plus_birthdate + 3, "jan", 3)) { - break; + edfhdr->plus_birthdate_month = 1; } - edfhdr->plus_patient_name[i] = edfhdr->patient[i+p]; - if(edfhdr->plus_patient_name[i]=='_') edfhdr->plus_patient_name[i] = ' '; - } - edfhdr->plus_patient_name[i] = 0; - p += i + 1; + else if(!strncmp(edfhdr->plus_birthdate + 3, "feb", 3)) + { + edfhdr->plus_birthdate_month = 2; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "mar", 3)) + { + edfhdr->plus_birthdate_month = 3; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "apr", 3)) + { + edfhdr->plus_birthdate_month = 4; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "may", 3)) + { + edfhdr->plus_birthdate_month = 5; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "jun", 3)) + { + edfhdr->plus_birthdate_month = 6; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "jul", 3)) + { + edfhdr->plus_birthdate_month = 7; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "aug", 3)) + { + edfhdr->plus_birthdate_month = 8; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "sep", 3)) + { + edfhdr->plus_birthdate_month = 9; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "oct", 3)) + { + edfhdr->plus_birthdate_month = 10; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "nov", 3)) + { + edfhdr->plus_birthdate_month = 11; + } + else if(!strncmp(edfhdr->plus_birthdate + 3, "dec", 3)) + { + edfhdr->plus_birthdate_month = 12; + } + else + { + edfhdr->plus_birthdate_month = 0; + } + edfhdr->plus_birthdate_year = edflib_atoi_nonlocalized(edfhdr->plus_birthdate + 7); + } + + for(i=0; i<(80-p);i++) + { + if(edfhdr->patient[i+p]==' ') + { + break; + } + edfhdr->plus_patient_name[i] = edfhdr->patient[i+p]; + if(edfhdr->plus_patient_name[i]=='_') edfhdr->plus_patient_name[i] = ' '; + } + edfhdr->plus_patient_name[i] = 0; + p += i + 1; for(i=0; i<(80-p);i++) { @@ -2453,7 +2388,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro if((scratchpad2[8]<48)||(scratchpad2[8]>57)) error = 1; if((scratchpad2[9]<48)||(scratchpad2[9]>57)) error = 1; if((scratchpad2[10]<48)||(scratchpad2[10]>57)) error = 1; - if((edflib_atof_nonlocalized(scratchpad2)<1)||(edflib_atof_nonlocalized(scratchpad2)>31)) error = 1; + if((edflib_atoi_nonlocalized(scratchpad2)<1)||(edflib_atoi_nonlocalized(scratchpad2)>31)) error = 1; r = 0; if(!strcmp(scratchpad2 + 3, "JAN")) r = 1; else if(!strcmp(scratchpad2 + 3, "FEB")) r = 2; @@ -2508,9 +2443,9 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro scratchpad[5] = 0; scratchpad[8] = 0; - if(edflib_atof_nonlocalized(scratchpad)!=edflib_atof_nonlocalized(scratchpad2)) error = 1; - if(edflib_atof_nonlocalized(scratchpad+3)!=r) error = 1; - if(edflib_atof_nonlocalized(scratchpad+6)!=edflib_atof_nonlocalized(scratchpad2+9)) error = 1; + if(edflib_atoi_nonlocalized(scratchpad)!=edflib_atoi_nonlocalized(scratchpad2)) error = 1; + if(edflib_atoi_nonlocalized(scratchpad+3)!=r) error = 1; + if(edflib_atoi_nonlocalized(scratchpad+6)!=edflib_atoi_nonlocalized(scratchpad2+9)) error = 1; if(error) { *edf_error = EDFLIB_FILE_ERRORS_RECORDINGFIELD; @@ -2520,9 +2455,7 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro return NULL; } - edfhdr->startdate_year = edflib_atof_nonlocalized(scratchpad2 + 7); - - if(edfhdr->startdate_year<1970) + if(edfhdr->startdate_year != edflib_atoi_nonlocalized(scratchpad2 + 7)) { *edf_error = EDFLIB_FILE_ERRORS_RECORDINGFIELD; free(edf_hdr); @@ -2624,17 +2557,17 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro if (check_file_size != EDFLIB_DO_NOT_CHECK_FILE_SIZE) { fseeko(inputfile, 0LL, SEEK_END); - if(ftello(inputfile)<(edfhdr->recordsize * edfhdr->datarecords + edfhdr->hdrsize)) + if(ftello(inputfile)<(edfhdr->recordsize * edfhdr->datarecords + edfhdr->hdrsize)) { - printf("filesize %d != %d*%d+%d ",ftello(inputfile),edfhdr->recordsize, edfhdr->datarecords, edfhdr->hdrsize); - *edf_error = EDFLIB_FILE_ERRORS_FILESIZE; - free(edf_hdr); - free(edfhdr->edfparam); - free(edfhdr); - return NULL; + printf("filesize %ld != %d*%lld+%d ",ftello(inputfile),edfhdr->recordsize, edfhdr->datarecords, edfhdr->hdrsize); + *edf_error = EDFLIB_FILE_ERRORS_FILESIZE; + free(edf_hdr); + free(edfhdr->edfparam); + free(edfhdr); + return NULL; } - } + n = 0; for(i=0; iedfsignals; i++) @@ -2642,16 +2575,16 @@ static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_erro edfhdr->edfparam[i].buf_offset = n; if(edfhdr->bdf) n += edfhdr->edfparam[i].smp_per_record * 3; else n += edfhdr->edfparam[i].smp_per_record * 2; - if ((edfhdr->edfparam[i].dig_max == edfhdr->edfparam[i].dig_min) || (edfhdr->edfparam[i].phys_max == edfhdr->edfparam[i].phys_min)) - { - edfhdr->edfparam[i].bitvalue = 1; - edfhdr->edfparam[i].offset = 0; - } - else - { - edfhdr->edfparam[i].bitvalue = (edfhdr->edfparam[i].phys_max - edfhdr->edfparam[i].phys_min) / (edfhdr->edfparam[i].dig_max - edfhdr->edfparam[i].dig_min); - edfhdr->edfparam[i].offset = edfhdr->edfparam[i].phys_max / edfhdr->edfparam[i].bitvalue - edfhdr->edfparam[i].dig_max; + if (edfhdr->edfparam[i].dig_max==edfhdr->edfparam[i].dig_min || edfhdr->edfparam[i].phys_max==edfhdr->edfparam[i].phys_min) + { + edfhdr->edfparam[i].bitvalue = 1; + edfhdr->edfparam[i].offset = 0; + } + else + { + edfhdr->edfparam[i].bitvalue = (edfhdr->edfparam[i].phys_max - edfhdr->edfparam[i].phys_min) / (edfhdr->edfparam[i].dig_max - edfhdr->edfparam[i].dig_min); + edfhdr->edfparam[i].offset = edfhdr->edfparam[i].phys_max / edfhdr->edfparam[i].bitvalue - edfhdr->edfparam[i].dig_max; } } @@ -2824,6 +2757,7 @@ static int edflib_is_number(char *str) static long long edflib_get_long_duration(char *str) { int i, len=8, hasdot=0, dotposition=0; + long long value=0, radix; if((str[0] == '+') || (str[0] == '-')) @@ -2832,9 +2766,10 @@ static long long edflib_get_long_duration(char *str) { str[i] = str[i+1]; } + str[7] = ' '; } - + for(i=0; i<8; i++) { if(str[i]==' ') @@ -2887,16 +2822,16 @@ static long long edflib_get_long_duration(char *str) } -int edflib_version(void) +EDFLIB_API int edflib_version(void) { return EDFLIB_VERSION; } -int edflib_repair_file_size(const char *path, struct edfhdrblock *edfhdr) + +static int edflib_repair_file_size(const char *path, edfhdrblock_t *edfhdr) { int p; FILE *file; - file = fopeno(path, "wb"); if(edfhdr->datarecords<100000000LL) { @@ -2911,7 +2846,8 @@ int edflib_repair_file_size(const char *path, struct edfhdrblock *edfhdr) return 0; } -static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_annotations) + +static int edflib_get_annotations(edfhdrblock_t *edfhdr, int hdl, int read_annotations_mode) { int i, j, k, p, r=0, n, edfsignals, @@ -2931,22 +2867,22 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ annots_in_tal, samplesize=2; - char *scratchpad, - *cnv_buf, - *time_in_txt, - *duration_in_txt; + char *scratchpad=NULL, + *cnv_buf=NULL, + *time_in_txt=NULL, + *duration_in_txt=NULL; long long data_record_duration, elapsedtime, time_tmp=0; - FILE *inputfile; + FILE *inputfile=NULL; - struct edfparamblock *edfparam; + edfparamblock_t *edfparam=NULL; - struct edf_annotationblock *new_annotation=NULL, - *malloc_list; + edf_read_annotationblock_t *new_annotation=NULL, + *malloc_list=NULL; inputfile = edfhdr->file_hdl; edfsignals = edfhdr->edfsignals; @@ -2980,6 +2916,8 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ if(max_tal_ln=EDFLIB_TIME_DIMENSION) + if((time_tmp>=EDFLIB_TIME_DIMENSION) || (time_tmp<0LL)) { error = 2; goto END; @@ -3108,6 +3046,11 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ else { edfhdr->starttime_offset = time_tmp; + if(read_annotations_mode==EDFLIB_DO_NOT_READ_ANNOTATIONS) + { + error = 0; + goto END_OUT; + } } } elapsedtime = time_tmp; @@ -3171,8 +3114,8 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ { if(edfhdr->annots_in_file >= edfhdr->annotlist_sz) { - malloc_list = (struct edf_annotationblock *)realloc(annotationslist[hdl], - sizeof(struct edf_annotationblock) * (edfhdr->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); + malloc_list = (edf_read_annotationblock_t *)realloc(annotationslist[hdl], + sizeof(edf_read_annotationblock_t) * (edfhdr->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); if(malloc_list==NULL) { free(cnv_buf); @@ -3191,8 +3134,16 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ new_annotation->annotation[0] = 0; - if(duration) edflib_strlcpy(new_annotation->duration, duration_in_txt, 16); - else new_annotation->duration[0] = 0; + if(duration) + { + edflib_strlcpy(new_annotation->duration, duration_in_txt, 20); + new_annotation->duration_l = edflib_get_long_time(duration_in_txt); + } + else + { + new_annotation->duration[0] = 0; + new_annotation->duration_l = -EDFLIB_TIME_DIMENSION; + } for(j=0; jannots_in_file++; - if(read_annotations==EDFLIB_READ_ANNOTATIONS) + if(read_annotations_mode==EDFLIB_READ_ANNOTATIONS) { if(!(strncmp(new_annotation->annotation, "Recording ends", 14))) { @@ -3285,6 +3236,8 @@ static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_ } } + END_OUT: + free(cnv_buf); free(scratchpad); free(time_in_txt); @@ -3321,7 +3274,6 @@ static int edflib_is_duration_number(char *str) } - static int edflib_is_onset_number(char *str) { int i, l, hasdot = 0; @@ -3351,7 +3303,6 @@ static int edflib_is_onset_number(char *str) } - static long long edflib_get_long_time(char *str) { int i, len, hasdot=0, dotposition=0, neg=0; @@ -3417,8 +3368,12 @@ static long long edflib_get_long_time(char *str) static void edflib_latin1_to_ascii(char *str, int len) { + /* ISO 8859-1 except for characters 0x80 to 0x9f which are taken from the extension CP-1252 */ + int i, value; + const char conv_table[]=".E.,F\".++^.Se.zY.i....|....<...-....\'u.....>...?AAAAAAECEEEEIIIIDNOOOOOxOUUUUYtsaaaaaaeceeeeiiiidnooooo:0uuuuyty"; + for(i=0; i=EDFLIB_MAXFILES) { @@ -3720,13 +3593,13 @@ int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals return EDFLIB_NUMBER_OF_SIGNALS_INVALID; } - hdr = (struct edfhdrblock *)calloc(1, sizeof(struct edfhdrblock)); + hdr = (edfhdrblock_t *)calloc(1, sizeof(edfhdrblock_t)); if(hdr==NULL) { return EDFLIB_MALLOC_ERROR; } - hdr->edfparam = (struct edfparamblock *)calloc(1, sizeof(struct edfparamblock) * number_of_signals); + hdr->edfparam = (edfparamblock_t *)calloc(1, sizeof(edfparamblock_t) * number_of_signals); if(hdr->edfparam==NULL) { free(hdr); @@ -3789,24 +3662,22 @@ int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals { hdr->edf = 1; hdr->edfplus = 1; - hdr->nr_annot_chns = 1; - } - + if(filetype==EDFLIB_FILETYPE_EDF) { hdr->edf = 1; hdr->edfplus = 0; hdr->nr_annot_chns = 0; } - + if(filetype==EDFLIB_FILETYPE_BDFPLUS) { hdr->bdf = 1; hdr->bdfplus = 1; - hdr->nr_annot_chns = 1; + hdr->nr_annot_chns = 1; } - + if(filetype==EDFLIB_FILETYPE_BDF) { hdr->bdf = 1; @@ -3822,47 +3693,21 @@ int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals } -int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency) +EDFLIB_API int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(edfsignal<0) return -1; - if(edfsignal<0) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if(edfsignal>=hdrlist[handle]->edfsignals) return -1; - if(samplefrequency<1) - { - return -1; - } + if(samplefrequency<1) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; hdrlist[handle]->edfparam[edfsignal].smp_per_record = samplefrequency; @@ -3870,37 +3715,17 @@ int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency) } -int edf_set_number_of_annotation_signals(int handle, int annot_signals) +EDFLIB_API int edf_set_number_of_annotation_signals(int handle, int annot_signals) { - if(handle<0) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } - - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if((annot_signals < 1) || (annot_signals > EDFLIB_MAX_ANNOTATION_CHANNELS)) - { - return -1; - } + if((annot_signals < 1) || (annot_signals > EDFLIB_MAX_ANNOTATION_CHANNELS)) return -1; hdrlist[handle]->nr_annot_chns = annot_signals; @@ -3908,37 +3733,17 @@ int edf_set_number_of_annotation_signals(int handle, int annot_signals) } -int edf_set_datarecord_duration(int handle, int duration) +EDFLIB_API int edf_set_datarecord_duration(int handle, int duration) { - if(handle<0) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if((duration < 100) || (duration > 6000000)) - { - return -1; - } + if((duration < 100) || (duration > 6000000)) return -1; hdrlist[handle]->long_data_record_duration = (long long)duration * 100LL; @@ -3961,37 +3766,17 @@ int edf_set_datarecord_duration(int handle, int duration) } -int edf_set_micro_datarecord_duration(int handle, int duration) +EDFLIB_API int edf_set_micro_datarecord_duration(int handle, int duration) { - if(handle<0) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } - - if((duration < 1) || (duration > 9999)) - { - return -1; - } + if((duration < 1) || (duration > 9999)) return -1; hdrlist[handle]->long_data_record_duration = (long long)duration * 10LL; @@ -4001,37 +3786,17 @@ int edf_set_micro_datarecord_duration(int handle, int duration) } -int edf_set_subsecond_starttime(int handle, int subsecond) +EDFLIB_API int edf_set_subsecond_starttime(int handle, int subsecond) { - if(handle<0) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } - - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if((subsecond < 0) || (subsecond > 9999999)) - { - return -1; - } + if((subsecond < 0) || (subsecond > 9999999)) return -1; hdrlist[handle]->starttime_offset = (long long)subsecond; @@ -4039,7 +3804,7 @@ int edf_set_subsecond_starttime(int handle, int subsecond) } -int edfwrite_digital_short_samples(int handle, short *buf) +EDFLIB_API int edfwrite_digital_short_samples(int handle, short *buf) { int i, error, @@ -4051,38 +3816,17 @@ int edfwrite_digital_short_samples(int handle, short *buf) FILE *file; - struct edfhdrblock *hdr; - - - if(handle<0) - { - return -1; - } + edfhdrblock_t *hdr; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->edfsignals == 0) - { - return -1; - } + if(hdrlist[handle]->edfsignals == 0) return -1; - if(hdrlist[handle]->bdf == 1) - { - return -1; - } + if(hdrlist[handle]->bdf == 1) return -1; hdr = hdrlist[handle]; @@ -4096,10 +3840,7 @@ int edfwrite_digital_short_samples(int handle, short *buf) { error = edflib_write_edf_header(hdr); - if(error) - { - return error; - } + if(error) return error; } } @@ -4111,26 +3852,17 @@ int edfwrite_digital_short_samples(int handle, short *buf) if(hdr->edf) { - if((digmax != 32767) || (digmin != -32768)) + if((digmax != 0x7fff) || (digmin != -0x8000)) { for(i=0; idigmax) - { - buf[i] = digmax; - } + if(buf[i]>digmax) buf[i] = digmax; - if(buf[i]wrbuf = (char *)malloc(sf * 3); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; - } for(i=0; idigmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 3] = value & 0xff; @@ -4172,10 +3894,7 @@ int edfwrite_digital_short_samples(int handle, short *buf) hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) return -1; } hdr->signal_write_sequence_pos++; @@ -4184,10 +3903,7 @@ int edfwrite_digital_short_samples(int handle, short *buf) { hdr->signal_write_sequence_pos = 0; - if(edflib_write_tal(hdr, file)) - { - return -1; - } + if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; @@ -4198,7 +3914,7 @@ int edfwrite_digital_short_samples(int handle, short *buf) } -int edfwrite_digital_samples(int handle, int *buf) +EDFLIB_API int edfwrite_digital_samples(int handle, int *buf) { int i, error, @@ -4210,33 +3926,15 @@ int edfwrite_digital_samples(int handle, int *buf) FILE *file; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } - - if(!(hdrlist[handle]->writemode)) - { - return -1; - } - - if(hdrlist[handle]->edfsignals == 0) - { - return -1; - } + if(hdrlist[handle]->edfsignals == 0) return -1; hdr = hdrlist[handle]; @@ -4250,10 +3948,7 @@ int edfwrite_digital_samples(int handle, int *buf) { error = edflib_write_edf_header(hdr); - if(error) - { - return error; - } + if(error) return error; } } @@ -4273,10 +3968,7 @@ int edfwrite_digital_samples(int handle, int *buf) hdr->wrbuf = (char *)malloc(sf * 2); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 2; } @@ -4285,25 +3977,16 @@ int edfwrite_digital_samples(int handle, int *buf) { value = buf[i]; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 2] = value & 0xff; hdr->wrbuf[i * 2 + 1] = (value >> 8) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1) return -1; } else // BDF { @@ -4315,10 +3998,7 @@ int edfwrite_digital_samples(int handle, int *buf) hdr->wrbuf = (char *)malloc(sf * 3); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } @@ -4327,28 +4007,18 @@ int edfwrite_digital_samples(int handle, int *buf) { value = buf[i]; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 3] = value & 0xff; hdr->wrbuf[i * 3 + 1] = (value >> 8) & 0xff; hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff; - } - if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) return -1; } hdr->signal_write_sequence_pos++; @@ -4357,10 +4027,7 @@ int edfwrite_digital_samples(int handle, int *buf) { hdr->signal_write_sequence_pos = 0; - if(edflib_write_tal(hdr, file)) - { - return -1; - } + if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; @@ -4371,7 +4038,7 @@ int edfwrite_digital_samples(int handle, int *buf) } -int edf_blockwrite_digital_samples(int handle, int *buf) +EDFLIB_API int edf_blockwrite_digital_samples(int handle, int *buf) { int i, j, error, @@ -4384,38 +4051,17 @@ int edf_blockwrite_digital_samples(int handle, int *buf) FILE *file; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->signal_write_sequence_pos) - { - return -1; - } + if(hdrlist[handle]->edfsignals == 0) return -1; - if(hdrlist[handle]->edfsignals == 0) - { - return -1; - } + if(hdrlist[handle]->signal_write_sequence_pos) return -1; hdr = hdrlist[handle]; @@ -4427,10 +4073,7 @@ int edf_blockwrite_digital_samples(int handle, int *buf) { error = edflib_write_edf_header(hdr); - if(error) - { - return error; - } + if(error) return error; } buf_offset = 0; @@ -4453,10 +4096,7 @@ int edf_blockwrite_digital_samples(int handle, int *buf) hdr->wrbuf = (char *)malloc(sf * 2); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 2; } @@ -4465,25 +4105,16 @@ int edf_blockwrite_digital_samples(int handle, int *buf) { value = buf[i + buf_offset]; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 2] = value & 0xff; hdr->wrbuf[i * 2 + 1] = (value >> 8) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1) return -1; } else // BDF { @@ -4495,10 +4126,7 @@ int edf_blockwrite_digital_samples(int handle, int *buf) hdr->wrbuf = (char *)malloc(sf * 3); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } @@ -4507,15 +4135,9 @@ int edf_blockwrite_digital_samples(int handle, int *buf) { value = buf[i + buf_offset]; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 3] = value & 0xff; @@ -4524,19 +4146,13 @@ int edf_blockwrite_digital_samples(int handle, int *buf) hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) return -1; } buf_offset += sf; } - if(edflib_write_tal(hdr, file)) - { - return -1; - } + if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; @@ -4546,7 +4162,7 @@ int edf_blockwrite_digital_samples(int handle, int *buf) } -int edf_blockwrite_digital_short_samples(int handle, short *buf) +EDFLIB_API int edf_blockwrite_digital_short_samples(int handle, short *buf) { int i, j, error, @@ -4559,43 +4175,19 @@ int edf_blockwrite_digital_short_samples(int handle, short *buf) FILE *file; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(hdrlist[handle]->edfsignals == 0) return -1; - if(hdrlist[handle]->signal_write_sequence_pos) - { - return -1; - } + if(hdrlist[handle]->signal_write_sequence_pos) return -1; - if(hdrlist[handle]->edfsignals == 0) - { - return -1; - } - - if(hdrlist[handle]->bdf == 1) - { - return -1; - } + if(hdrlist[handle]->bdf == 1) return -1; hdr = hdrlist[handle]; @@ -4625,7 +4217,7 @@ int edf_blockwrite_digital_short_samples(int handle, short *buf) if(hdr->edf) { - if((digmax != 32767) || (digmin != -32768)) + if((digmax != 0x7fff) || (digmin != -0x8000)) { for(i=0; iwrbuf = (char *)malloc(sf * 3); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } @@ -4668,15 +4254,9 @@ int edf_blockwrite_digital_short_samples(int handle, short *buf) { value = buf[i + buf_offset]; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 3] = value & 0xff; @@ -4685,19 +4265,13 @@ int edf_blockwrite_digital_short_samples(int handle, short *buf) hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) return -1; } buf_offset += sf; } - if(edflib_write_tal(hdr, file)) - { - return -1; - } + if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; @@ -4707,7 +4281,7 @@ int edf_blockwrite_digital_short_samples(int handle, short *buf) } -int edf_blockwrite_digital_3byte_samples(int handle, void *buf) +EDFLIB_API int edf_blockwrite_digital_3byte_samples(int handle, void *buf) { int j, error, @@ -4716,43 +4290,19 @@ int edf_blockwrite_digital_3byte_samples(int handle, void *buf) FILE *file; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->signal_write_sequence_pos) - { - return -1; - } + if(hdrlist[handle]->edfsignals == 0) return -1; - if(hdrlist[handle]->edfsignals == 0) - { - return -1; - } + if(hdrlist[handle]->signal_write_sequence_pos) return -1; - if(hdrlist[handle]->bdf != 1) - { - return -1; - } + if(hdrlist[handle]->bdf != 1) return -1; hdr = hdrlist[handle]; @@ -4764,10 +4314,7 @@ int edf_blockwrite_digital_3byte_samples(int handle, void *buf) { error = edflib_write_edf_header(hdr); - if(error) - { - return error; - } + if(error) return error; } for(j=0; jedfparam[j].smp_per_record; } - if(fwrite(buf, total_samples * 3, 1, file) != 1) - { - return -1; - } + if(fwrite(buf, total_samples * 3, 1, file) != 1) return -1; - if(edflib_write_tal(hdr, file)) - { - return -1; - } + if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; @@ -4793,7 +4334,7 @@ int edf_blockwrite_digital_3byte_samples(int handle, void *buf) } -int edfwrite_physical_samples(int handle, double *buf) +EDFLIB_API int edfwrite_physical_samples(int handle, double *buf) { int i, error, @@ -4808,33 +4349,15 @@ int edfwrite_physical_samples(int handle, double *buf) FILE *file; - struct edfhdrblock *hdr; + edfhdrblock_t *hdr; + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->edfsignals == 0) - { - return -1; - } + if(hdrlist[handle]->edfsignals == 0) return -1; hdr = hdrlist[handle]; @@ -4848,10 +4371,7 @@ int edfwrite_physical_samples(int handle, double *buf) { error = edflib_write_edf_header(hdr); - if(error) - { - return error; - } + if(error) return error; } } @@ -4875,10 +4395,7 @@ int edfwrite_physical_samples(int handle, double *buf) hdr->wrbuf = (char *)malloc(sf * 2); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 2; } @@ -4887,25 +4404,16 @@ int edfwrite_physical_samples(int handle, double *buf) { value = (buf[i] / bitvalue) - phys_offset; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 2] = value & 0xff; hdr->wrbuf[i * 2 + 1] = (value >> 8) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1) return -1; } else // BDF { @@ -4917,10 +4425,7 @@ int edfwrite_physical_samples(int handle, double *buf) hdr->wrbuf = (char *)malloc(sf * 3); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } @@ -4929,15 +4434,9 @@ int edfwrite_physical_samples(int handle, double *buf) { value = (buf[i] / bitvalue) - phys_offset; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 3] = value & 0xff; @@ -4946,10 +4445,7 @@ int edfwrite_physical_samples(int handle, double *buf) hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) return -1; } hdr->signal_write_sequence_pos++; @@ -4958,10 +4454,7 @@ int edfwrite_physical_samples(int handle, double *buf) { hdr->signal_write_sequence_pos = 0; - if(edflib_write_tal(hdr, file)) - { - return -1; - } + if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; @@ -4972,7 +4465,7 @@ int edfwrite_physical_samples(int handle, double *buf) } -int edf_blockwrite_physical_samples(int handle, double *buf) +EDFLIB_API int edf_blockwrite_physical_samples(int handle, double *buf) { int i, j, error, @@ -4988,38 +4481,17 @@ int edf_blockwrite_physical_samples(int handle, double *buf) FILE *file; - struct edfhdrblock *hdr; - + edfhdrblock_t *hdr; - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->signal_write_sequence_pos) - { - return -1; - } + if(hdrlist[handle]->edfsignals == 0) return -1; - if(hdrlist[handle]->edfsignals == 0) - { - return -1; - } + if(hdrlist[handle]->signal_write_sequence_pos) return -1; hdr = hdrlist[handle]; @@ -5031,10 +4503,7 @@ int edf_blockwrite_physical_samples(int handle, double *buf) { error = edflib_write_edf_header(hdr); - if(error) - { - return error; - } + if(error) return error; } buf_offset = 0; @@ -5061,10 +4530,7 @@ int edf_blockwrite_physical_samples(int handle, double *buf) hdr->wrbuf = (char *)malloc(sf * 2); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 2; } @@ -5073,25 +4539,16 @@ int edf_blockwrite_physical_samples(int handle, double *buf) { value = (buf[i + buf_offset] / bitvalue) - phys_offset; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 2] = value & 0xff; hdr->wrbuf[i * 2 + 1] = (value >> 8) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 2, 1, file) != 1) return -1; } else // BDF { @@ -5103,10 +4560,7 @@ int edf_blockwrite_physical_samples(int handle, double *buf) hdr->wrbuf = (char *)malloc(sf * 3); - if(hdr->wrbuf == NULL) - { - return -1; - } + if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } @@ -5115,15 +4569,9 @@ int edf_blockwrite_physical_samples(int handle, double *buf) { value = (buf[i + buf_offset] / bitvalue) - phys_offset; - if(value>digmax) - { - value = digmax; - } + if(value>digmax) value = digmax; - if(valuewrbuf[i * 3] = value & 0xff; @@ -5132,19 +4580,13 @@ int edf_blockwrite_physical_samples(int handle, double *buf) hdr->wrbuf[i * 3 + 2] = (value >> 16) & 0xff; } - if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) - { - return -1; - } + if(fwrite(hdr->wrbuf, sf * 3, 1, file) != 1) return -1; } buf_offset += sf; } - if(edflib_write_tal(hdr, file)) - { - return -1; - } + if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; @@ -5154,7 +4596,7 @@ int edf_blockwrite_physical_samples(int handle, double *buf) } -static int edflib_write_edf_header(struct edfhdrblock *hdr) +static int edflib_write_edf_header(edfhdrblock_t *hdr) { int i, j, p, q, len, @@ -5169,20 +4611,13 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) FILE *file; - file = hdr->file_hdl; edfsignals = hdr->edfsignals; - if(edfsignals<0) - { - return EDFLIB_NO_SIGNALS; - } + if(edfsignals<0) return EDFLIB_NO_SIGNALS; - if(edfsignals>EDFLIB_MAXSIGNALS) - { - return EDFLIB_TOO_MANY_SIGNALS; - } + if(edfsignals>EDFLIB_MAXSIGNALS) return EDFLIB_TOO_MANY_SIGNALS; hdr->eq_sf = 1; @@ -5192,11 +4627,11 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) for(i=0; iedfplus || hdr->bdfplus) - { + if (hdr->edfplus || hdr->bdfplus) + { if(hdr->edfparam[i].smp_per_record<1) { - return EDFLIB_NO_SAMPLES_IN_RECORD ; + return EDFLIB_NO_SAMPLES_IN_RECORD; } if(hdr->edfparam[i].dig_max==hdr->edfparam[i].dig_min) @@ -5214,9 +4649,9 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) return EDFLIB_PHYSMIN_IS_PHYSMAX; } - hdr->recordsize += hdr->edfparam[i].smp_per_record; - + hdr->recordsize += hdr->edfparam[i].smp_per_record; } + if(i > 0) { if(hdr->edfparam[i].smp_per_record != hdr->edfparam[i-1].smp_per_record) @@ -5225,7 +4660,6 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) } } } - if(hdr->edf) { @@ -5254,16 +4688,16 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) for(i=0; iedfparam[i].phys_max == hdr->edfparam[i].phys_min) || (hdr->edfparam[i].dig_max == hdr->edfparam[i].dig_min)) - { - hdr->edfparam[i].bitvalue = 1; - hdr->edfparam[i].offset = 0; - } - else - { - hdr->edfparam[i].bitvalue = (hdr->edfparam[i].phys_max - hdr->edfparam[i].phys_min) / (hdr->edfparam[i].dig_max - hdr->edfparam[i].dig_min); - hdr->edfparam[i].offset = hdr->edfparam[i].phys_max / hdr->edfparam[i].bitvalue - hdr->edfparam[i].dig_max; - } + if ((hdr->edfparam[i].phys_max == hdr->edfparam[i].phys_min) || (hdr->edfparam[i].dig_max == hdr->edfparam[i].dig_min)) + { + hdr->edfparam[i].bitvalue = 1; + hdr->edfparam[i].offset = 0; + } + else + { + hdr->edfparam[i].bitvalue = (hdr->edfparam[i].phys_max - hdr->edfparam[i].phys_min) / (hdr->edfparam[i].dig_max - hdr->edfparam[i].dig_min); + hdr->edfparam[i].offset = hdr->edfparam[i].phys_max / hdr->edfparam[i].bitvalue - hdr->edfparam[i].dig_max; + } } rewind(file); @@ -5274,8 +4708,7 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) } else { - fputc(255, file); - fprintf(file, "BIOSEMI"); + fprintf(file, "\xff" "BIOSEMI"); } p = 0; @@ -5318,13 +4751,13 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) p += fprintf(file, "X "); } - if(hdr->plus_gender[0]=='M') + if(hdr->plus_sex[0]=='M') { fputc('M', file); } else { - if(hdr->plus_gender[0]=='F') + if(hdr->plus_sex[0]=='F') { fputc('F', file); } @@ -5348,7 +4781,7 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) fputc(hdr->plus_birthdate[0], file); fputc(hdr->plus_birthdate[1], file); fputc('-', file); - q = edflib_atof_nonlocalized(&(hdr->plus_birthdate[3])); + q = edflib_atoi_nonlocalized(&(hdr->plus_birthdate[3])); switch(q) { case 1: fprintf(file, "JAN"); break; @@ -5827,47 +5260,22 @@ static int edflib_write_edf_header(struct edfhdrblock *hdr) { fputc(' ', file); } - + return 0; } -int edf_set_label(int handle, int edfsignal, const char *label) +EDFLIB_API int edf_set_label(int handle, int edfsignal, const char *label) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(edfsignal<0) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; strncpy(hdrlist[handle]->edfparam[edfsignal].label, label, 16); @@ -5879,42 +5287,17 @@ int edf_set_label(int handle, int edfsignal, const char *label) } -int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim) +EDFLIB_API int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(edfsignal<0) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; strncpy(hdrlist[handle]->edfparam[edfsignal].physdimension, phys_dim, 8); @@ -5926,42 +5309,17 @@ int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim) } -int edf_set_physical_maximum(int handle, int edfsignal, double phys_max) +EDFLIB_API int edf_set_physical_maximum(int handle, int edfsignal, double phys_max) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(edfsignal<0) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; hdrlist[handle]->edfparam[edfsignal].phys_max = phys_max; @@ -5969,42 +5327,17 @@ int edf_set_physical_maximum(int handle, int edfsignal, double phys_max) } -int edf_set_physical_minimum(int handle, int edfsignal, double phys_min) +EDFLIB_API int edf_set_physical_minimum(int handle, int edfsignal, double phys_min) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(edfsignal<0) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; hdrlist[handle]->edfparam[edfsignal].phys_min = phys_min; @@ -6012,56 +5345,25 @@ int edf_set_physical_minimum(int handle, int edfsignal, double phys_min) } -int edf_set_digital_maximum(int handle, int edfsignal, int dig_max) +EDFLIB_API int edf_set_digital_maximum(int handle, int edfsignal, int dig_max) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal<0) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; if(hdrlist[handle]->edf) { - if(dig_max > 32767) - { - return -1; - } + if(dig_max > 0x7fff) return -1; } else { - if(dig_max > 8388607) - { - return -1; - } - } - - if(hdrlist[handle]->datarecords) - { - return -1; + if(dig_max > 0x7fffff) return -1; } hdrlist[handle]->edfparam[edfsignal].dig_max = dig_max; @@ -6070,56 +5372,25 @@ int edf_set_digital_maximum(int handle, int edfsignal, int dig_max) } -int edf_set_digital_minimum(int handle, int edfsignal, int dig_min) +EDFLIB_API int edf_set_digital_minimum(int handle, int edfsignal, int dig_min) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal<0) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; if(hdrlist[handle]->edf) { - if(dig_min < (-32768)) - { - return -1; - } + if(dig_min < (-0x8000)) return -1; } else { - if(dig_min < (-8388608)) - { - return -1; - } - } - - if(hdrlist[handle]->datarecords) - { - return -1; + if(dig_min < (-0x800000)) return -1; } hdrlist[handle]->edfparam[edfsignal].dig_min = dig_min; @@ -6128,32 +5399,15 @@ int edf_set_digital_minimum(int handle, int edfsignal, int dig_min) } -int edf_set_patientname(int handle, const char *patientname) +EDFLIB_API int edf_set_patientname(int handle, const char *patientname) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_patient_name, patientname, 80); @@ -6165,32 +5419,15 @@ int edf_set_patientname(int handle, const char *patientname) } -int edf_set_patientcode(int handle, const char *patientcode) +EDFLIB_API int edf_set_patientcode(int handle, const char *patientcode) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_patientcode, patientcode, 80); @@ -6202,79 +5439,48 @@ int edf_set_patientcode(int handle, const char *patientcode) } -int edf_set_gender(int handle, int gender) +EDFLIB_API int edf_set_sex(int handle, int sex) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if((gender<0)||(gender>1)) - { - return -1; - } + if((sex<0)||(sex>1)) return -1; - if(gender) + if(sex) { - hdrlist[handle]->plus_gender[0] = 'M'; + hdrlist[handle]->plus_sex[0] = 'M'; } else { - hdrlist[handle]->plus_gender[0] = 'F'; + hdrlist[handle]->plus_sex[0] = 'F'; } - hdrlist[handle]->plus_gender[1] = 0; + hdrlist[handle]->plus_sex[1] = 0; return 0; } -int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day) +EDFLIB_API int edf_set_gender(int handle, int sex) { - if(handle<0) - { - return -1; - } + return edf_set_sex(handle, sex); +} - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - if(hdrlist[handle]==NULL) - { - return -1; - } +EDFLIB_API int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day) +{ + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; + + if(hdrlist[handle]->datarecords) return -1; if((birthdate_year<1800) || (birthdate_year>3000) || (birthdate_month<1) || (birthdate_month>12) || @@ -6291,32 +5497,15 @@ int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int b } -int edf_set_patient_additional(int handle, const char *patient_additional) +EDFLIB_API int edf_set_patient_additional(int handle, const char *patient_additional) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_patient_additional, patient_additional, 80); @@ -6328,32 +5517,15 @@ int edf_set_patient_additional(int handle, const char *patient_additional) } -int edf_set_admincode(int handle, const char *admincode) +EDFLIB_API int edf_set_admincode(int handle, const char *admincode) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_admincode, admincode, 80); @@ -6365,32 +5537,15 @@ int edf_set_admincode(int handle, const char *admincode) } -int edf_set_technician(int handle, const char *technician) +EDFLIB_API int edf_set_technician(int handle, const char *technician) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_technician, technician, 80); @@ -6402,32 +5557,15 @@ int edf_set_technician(int handle, const char *technician) } -int edf_set_equipment(int handle, const char *equipment) +EDFLIB_API int edf_set_equipment(int handle, const char *equipment) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_equipment, equipment, 80); @@ -6439,32 +5577,15 @@ int edf_set_equipment(int handle, const char *equipment) } -int edf_set_recording_additional(int handle, const char *recording_additional) +EDFLIB_API int edf_set_recording_additional(int handle, const char *recording_additional) { - if(handle<0) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } - - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_recording_additional, recording_additional, 80); @@ -6476,35 +5597,18 @@ int edf_set_recording_additional(int handle, const char *recording_additional) } -int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day, - int starttime_hour, int starttime_minute, int starttime_second) +EDFLIB_API int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day, + int starttime_hour, int starttime_minute, int starttime_second) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if((startdate_year<1970) || (startdate_year>3000) || + if((startdate_year<1985) || (startdate_year>2084) || (startdate_month<1) || (startdate_month>12) || (startdate_day<1) || (startdate_day>31) || (starttime_hour<0) || (starttime_hour>23) || @@ -6525,42 +5629,32 @@ int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, i } -int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description) +EDFLIB_API int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description) { - int i; + if(duration > 0LL) duration *= 100LL; + + return edfwrite_annotation_utf8_hr(handle, onset * 100LL, duration, description); +} - struct edf_write_annotationblock *list_annot, *malloc_list; +EDFLIB_API int edfwrite_annotation_utf8_hr(int handle, long long onset, long long duration, const char *description) +{ + int i; - if(handle<0) - { - return -1; - } + edf_write_annotationblock_t *list_annot, *malloc_list; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(onset<0LL) - { - return -1; - } + if(onset<0LL) return -1; if(hdrlist[handle]->annots_in_file >= hdrlist[handle]->annotlist_sz) { - malloc_list = (struct edf_write_annotationblock *)realloc(write_annotationslist[handle], - sizeof(struct edf_write_annotationblock) * (hdrlist[handle]->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); + malloc_list = (edf_write_annotationblock_t *)realloc(write_annotationslist[handle], + sizeof(edf_write_annotationblock_t) * (hdrlist[handle]->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); if(malloc_list==NULL) { return -1; @@ -6585,7 +5679,7 @@ int edfwrite_annotation_utf8(int handle, long long onset, long long duration, co break; } - if(list_annot->annotation[i] < 32) + if(((unsigned char *)(list_annot->annotation))[i] < 32) { list_annot->annotation[i] = '.'; } @@ -6597,42 +5691,32 @@ int edfwrite_annotation_utf8(int handle, long long onset, long long duration, co } -int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description) +EDFLIB_API int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description) { - struct edf_write_annotationblock *list_annot, *malloc_list; + if(duration > 0LL) duration *= 100LL; - char str[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1]; + return edfwrite_annotation_latin1_hr(handle, onset * 100LL, duration, description); +} - if(handle<0) - { - return -1; - } +EDFLIB_API int edfwrite_annotation_latin1_hr(int handle, long long onset, long long duration, const char *description) +{ + edf_write_annotationblock_t *list_annot, *malloc_list; - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + char str[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1]; - if(hdrlist[handle]==NULL) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(onset<0LL) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; + + if(onset<0LL) return -1; if(hdrlist[handle]->annots_in_file >= hdrlist[handle]->annotlist_sz) { - malloc_list = (struct edf_write_annotationblock *)realloc(write_annotationslist[handle], - sizeof(struct edf_write_annotationblock) * (hdrlist[handle]->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); + malloc_list = (edf_write_annotationblock_t *)realloc(write_annotationslist[handle], + sizeof(edf_write_annotationblock_t) * (hdrlist[handle]->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); if(malloc_list==NULL) { return -1; @@ -6690,42 +5774,19 @@ static void edflib_remove_padding_trailing_spaces(char *str) } -int edf_set_prefilter(int handle, int edfsignal, const char *prefilter) +EDFLIB_API int edf_set_prefilter(int handle, int edfsignal, const char *prefilter) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal<0) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->edfparam[edfsignal].prefilter, prefilter, 80); @@ -6737,42 +5798,19 @@ int edf_set_prefilter(int handle, int edfsignal, const char *prefilter) } -int edf_set_transducer(int handle, int edfsignal, const char *transducer) +EDFLIB_API int edf_set_transducer(int handle, int edfsignal, const char *transducer) { - if(handle<0) - { - return -1; - } - - if(handle>=EDFLIB_MAXFILES) - { - return -1; - } + if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; - if(hdrlist[handle]==NULL) - { - return -1; - } + if(hdrlist[handle]==NULL) return -1; - if(!(hdrlist[handle]->writemode)) - { - return -1; - } + if(!hdrlist[handle]->writemode) return -1; - if(edfsignal<0) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; - if(edfsignal>=hdrlist[handle]->edfsignals) - { - return -1; - } + if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; - if(hdrlist[handle]->datarecords) - { - return -1; - } + if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->edfparam[edfsignal].transducer, transducer, 80); @@ -6808,7 +5846,7 @@ static int edflib_fprint_int_number_nonlocalized(FILE *file, int q, int minimum, j++; - q = -q; + base = -base; } else { @@ -6880,7 +5918,7 @@ static int edflib_fprint_ll_number_nonlocalized(FILE *file, long long q, int min j++; - q = -q; + base = -base; } else { @@ -7020,7 +6058,7 @@ static int edflib_snprint_ll_number_nonlocalized(char *dest, long long q, int mi { dest[j++] = '-'; - q = -q; + base = -base; } else { @@ -7079,7 +6117,8 @@ static int edflib_snprint_ll_number_nonlocalized(char *dest, long long q, int mi dest[j] = 0; - return j;} + return j; +} static int edflib_snprint_number_nonlocalized(char *dest, double val, int sz) @@ -7100,7 +6139,7 @@ static int edflib_snprint_number_nonlocalized(char *dest, double val, int sz) if(q < 0) { - q = -q; + base = -base; } } @@ -7154,7 +6193,7 @@ static int edflib_snprint_number_nonlocalized(char *dest, double val, int sz) if(q < 0) { - q = -q; + base = -base; } if(!q) @@ -7369,18 +6408,19 @@ static int edflib_atoi_nonlocalized(const char *str) value *= 10; - value += (str[i] - '0'); + value += ((str[i] - '0') * sign); } - return value * sign; + return value; } -static int edflib_write_tal(struct edfhdrblock *hdr, FILE *file) +static int edflib_write_tal(edfhdrblock_t *hdr, FILE *file) { - if ((hdr->edf||hdr->bdf) && !(hdr->edfplus||hdr->bdfplus)){ - // EDF/BDF = means no annotations will be written. - return 0; + if((hdr->edf||hdr->bdf) && !(hdr->edfplus||hdr->bdfplus)) + { + // EDF/BDF = no annotations will be written. + return 0; } int p; @@ -7472,6 +6512,5 @@ static int edflib_strlcat(char *dst, const char *src, int sz) - diff --git a/pyedflib/_extensions/c/edflib.h b/pyedflib/_extensions/c/edflib.h index f45f92e8..5fe1f75f 100644 --- a/pyedflib/_extensions/c/edflib.h +++ b/pyedflib/_extensions/c/edflib.h @@ -1,7 +1,7 @@ /* ***************************************************************************** * -* Copyright (c) 2009 - 2020 Teunis van Beelen +* Copyright (c) 2009 - 2023 Teunis van Beelen * All rights reserved. * * Email: teuniz@protonmail.com @@ -31,22 +31,130 @@ ***************************************************************************** */ +/**************************************************************************** + * + * For more info about the EDF and EDF+ format, visit: http://edfplus.info/specs/ + * + * For more info about the BDF and BDF+ format, visit: http://www.teuniz.net/edfbrowser/bdfplus%20format%20description.html + * + * note: In EDF, the resolution (or sensitivity) (e.g. uV/bit) and offset are stored using four parameters: + * digital maximum and minimum, and physical maximum and minimum. + * Here, digital means the raw data coming from a sensor or ADC. Physical means the units like uV. + * The resolution in units per least significant bit is calculated as follows: + * + * units per bit = (physical max - physical min) / (digital max - digital min) + * + * The digital offset is calculated as follows: + * + * offset = (physical max / units per bit) - digital max + * + * For a better explanation about the relation between digital data and physical data, + * read the document "Coding Schemes Used with Data Converters" (PDF): + * + * https://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=sbaa042 + * + * note: An EDF file usually contains multiple so-called datarecords. One datarecord usually has a duration of one second (this is the default but it is not mandatory!). + * In that case a file with a duration of five minutes contains 300 datarecords. The duration of a datarecord can be freely chosen but, if possible, use values from + * 0.1 to 1 second for easier handling. Just make sure that the total size of one datarecord, expressed in bytes, does not exceed 10MByte (15MBytes for BDF(+)). + * + * The RECOMMENDATION of a maximum datarecord size of 61440 bytes in the EDF and EDF+ specification was useful in the time people were still using DOS as their main operating system. + * Using DOS and fast (near) pointers (16-bit pointers), the maximum allocatable block of memory was 64KByte. + * This is not a concern anymore so the maximum datarecord size now is limited to 10MByte for EDF(+) and 15MByte for BDF(+). This helps to accommodate for higher sampling rates + * used by modern Analog to Digital Converters. + * + * EDF header character encoding: The EDF specification says that only (printable) ASCII characters are allowed. + * When writing the header info, EDFlib will assume you are using Latin1 encoding and it will automatically convert + * characters with accents, umlauts, tilde, etc. to their "normal" equivalent without the accent/umlaut/tilde/etc. + * in order to create a valid EDF file. + * The description of an EDF+ annotation on the other hand, is always encoded in UTF-8 (which is forward compatible with ASCII). + * + * The sample frequency of a signal is calculated as follows: sf = (smp_in_datarecord * EDFLIB_TIME_DIMENSION) / datarecord_duration + * + * Annotation signals + * ================== + * + * EDF+ and BDF+ store the annotations in one or more signals (in order to be backwards compatible with EDF and BDF). + * The numbering of the signals in the file is zero based (starts at 0). Signals used for annotations are skipped by EDFlib. + * This means that the annotationsignal(s) in the file are hidden. + * Use the function edf_get_annotation() to get the annotations. + * + * So, when a file contains 5 signals and the third signal is an annotations signal, the library will + * report that there are only 4 signals in the file. + * The library will "map" the signal numbers as follows: 0->0, 1->1, 2->3, 3->4. + * This way you don't need to worry about which signals are annotationsignals, the library will take care of it. + * + * How the library stores time values + * ================================== + * + * To avoid rounding errors, the library stores some time values in variables of type long long int. + * In order not to lose the sub-second precision, all time values are scaled with a scaling factor: 10000000. + * This will limit the time resolution to 100 nanoseconds. To calculate the amount of seconds, divide + * the timevalue by 10000000 or use the macro EDFLIB_TIME_DIMENSION which is declared in edflib.h. + * The following variables use this scaling when you open a file in read mode: "file_duration", "starttime_subsecond" and "onset". + * + * EDFlib and thread-safety + * ======================== + * The following functions are always MT-unsafe: + * edfopen_file_readonly() (race condition) + * edfclose_file() (race condition) + * edflib_get_handle() (race condition) + * + * When writing to or reading from the same file, all EDFlib functions are MT-unsafe (race condition). + * + */ /* compile with options "-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE" */ - #ifndef EDFLIB_INCLUDED #define EDFLIB_INCLUDED - #include #include #include #include +/* + * If both EDFLIB_SO_DLL and EDFLIB_BUILD are defined: compile only EDFlib as a shared library (so, dll). + * When compiling on unix-like systems, add the -fvisibility=hidden to hide all symbols by + * default so that this macro can reveal them. + * + * If only EDFLIB_SO_DLL is defined: link with EDFlib as an external library (so, dll). + * EDFlib must be installed on your system (as an .so or .dll) when running your program. + * + * If both EDFLIB_SO_DLL and EDFLIB_BUILD are not defined: EDFlib will not be used as a shared library, + * it will be an integral part of your program instead. + * + */ + +/* +#define EDFLIB_SO_DLL +#define EDFLIB_BUILD +*/ + +#if defined(EDFLIB_SO_DLL) +# if defined(EDFLIB_BUILD) +# if defined(_WIN32) +# define EDFLIB_API __declspec(dllexport) +# elif defined(__ELF__) +# define EDFLIB_API __attribute__ ((visibility ("default"))) +# else +# define EDFLIB_API +# endif +# else +# if defined(_WIN32) +# define EDFLIB_API __declspec(dllimport) +# else +# define EDFLIB_API +# endif +# endif +#else +# define EDFLIB_API +#endif + + #define EDFLIB_TIME_DIMENSION (10000000LL) #define EDFLIB_MAXSIGNALS (640) @@ -56,10 +164,8 @@ #define EDFSEEK_CUR (1) #define EDFSEEK_END (2) - - -/* the following defines are used in the member "filetype" of the edf_hdr_struct */ -/* and as return value for the function edfopen_file_readonly() */ +/* the following defines are used in the member "filetype" of the edf_hdr_struct + and as return value for the function edfopen_file_readonly() */ #define EDFLIB_FILETYPE_EDF (0) #define EDFLIB_FILETYPE_EDFPLUS (1) #define EDFLIB_FILETYPE_BDF (2) @@ -79,7 +185,7 @@ #define EDFLIB_NUMBER_OF_SIGNALS_INVALID (-9) #define EDFLIB_FILE_IS_DISCONTINUOUS (-10) #define EDFLIB_INVALID_READ_ANNOTS_VALUE (-11) -#define EDFLIB_INVALID_CHECK_SIZE_VALUE (-12) +#define EDFLIB_ARCH_ERROR (-12) /* values for annotations */ #define EDFLIB_DO_NOT_READ_ANNOTATIONS (0) @@ -101,7 +207,7 @@ #define EDFLIB_DATARECORD_SIZE_TOO_BIG (-26) /* added for pyedflib */ - +#define EDFLIB_INVALID_CHECK_SIZE_VALUE (-13) #define EDFLIB_FILE_ERRORS_STARTDATE (-30) #define EDFLIB_FILE_ERRORS_STARTTIME (-31) #define EDFLIB_FILE_ERRORS_NUMBER_SIGNALS (-32) @@ -122,604 +228,582 @@ #define EDFLIB_FILE_ERRORS_RECORDINGFIELD (-47) #define EDFLIB_FILE_ERRORS_PATIENTNAME (-48) - - #ifdef __cplusplus extern "C" { #endif - - -/* For more info about the EDF and EDF+ format, visit: https://edfplus.info/specs/ */ - -/* For more info about the BDF and BDF+ format, visit: https://www.teuniz.net/edfbrowser/bdfplus%20format%20description.html */ - -/* - * note: In EDF, the sensitivity (e.g. uV/bit) and offset are stored using four parameters: - * digital maximum and minimum, and physical maximum and minimum. - * Here, digital means the raw data coming from a sensor or ADC. Physical means the units like uV. - * The sensitivity in units/bit is calculated as follows: - * - * units per bit = (physical max - physical min) / (digital max - digital min) - * - * The digital offset is calculated as follows: - * - * offset = (physical max / units per bit) - digital max - * - * For a better explanation about the relation between digital data and physical data, - * read the document "Coding Schemes Used with Data Converters" (PDF): - * - * https://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=sbaa042 - * - * note: An EDF file usually contains multiple so-called datarecords. One datarecord usually has a duration of one second (this is the default but it is not mandatory!). - * In that case a file with a duration of five minutes contains 300 datarecords. The duration of a datarecord can be freely choosen but, if possible, use values from - * 0.1 to 1 second for easier handling. Just make sure that the total size of one datarecord, expressed in bytes, does not exceed 10MByte (15MBytes for BDF(+)). - * - * The RECOMMENDATION of a maximum datarecordsize of 61440 bytes in the EDF and EDF+ specification was usefull in the time people were still using DOS as their main operating system. - * Using DOS and fast (near) pointers (16-bit pointers), the maximum allocatable block of memory was 64KByte. - * This is not a concern anymore so the maximum datarecord size now is limited to 10MByte for EDF(+) and 15MByte for BDF(+). This helps to accommodate for higher samplingrates - * used by modern Analog to Digital Converters. - * - * EDF header character encoding: The EDF specification says that only ASCII characters are allowed. - * EDFlib will automatically convert characters with accents, umlauts, tilde, etc. to their "normal" equivalent without the accent/umlaut/tilde/etc. - * - * The description/name of an EDF+ annotation on the other hand, is encoded in UTF-8. - * - */ - - -struct edf_param_struct{ /* this structure contains all the relevant EDF-signal parameters of one signal */ +typedef struct edf_param_struct +{ /* this structure contains all the relevant EDF-signal parameters of one signal */ char label[17]; /* label (name) of the signal, null-terminated string */ long long smp_in_file; /* number of samples of this signal in the file */ double phys_max; /* physical maximum, usually the maximum input of the ADC */ double phys_min; /* physical minimum, usually the minimum input of the ADC */ - int dig_max; /* digital maximum, usually the maximum output of the ADC, can not not be higher than 32767 for EDF or 8388607 for BDF */ - int dig_min; /* digital minimum, usually the minimum output of the ADC, can not not be lower than -32768 for EDF or -8388608 for BDF */ - int smp_in_datarecord; /* number of samples of this signal in a datarecord, if the datarecord has a duration of one second (default), then it equals the samplerate */ + int dig_max; /* digital maximum, usually the maximum output of the ADC, cannot not be higher than 32767 for EDF or 8388607 for BDF */ + int dig_min; /* digital minimum, usually the minimum output of the ADC, cannot not be lower than -32768 for EDF or -8388608 for BDF */ + int smp_in_datarecord; /* number of samples of this signal in a datarecord, if the datarecord has a duration of one second (default), then it equals the sample rate */ char physdimension[9]; /* physical dimension (uV, bpm, mA, etc.), null-terminated string */ char prefilter[81]; /* null-terminated string */ char transducer[81]; /* null-terminated string */ - }; - +} edflib_param_t; -struct edf_annotation_struct{ /* this structure is used for annotations */ - long long onset; /* onset time of the event, expressed in units of 100 nanoSeconds and relative to the start of the file */ - char duration[16]; /* duration time, this is a null-terminated ASCII text-string */ +typedef struct edf_annotation_struct +{ /* this structure is used for annotations */ + long long onset; /* onset time of the event, expressed in units of 100 nanoseconds and relative to the start of the file */ + long long duration_l; /* duration time, expressed in units of 100 nanoseconds, if less than zero: unused or not applicable */ + char duration[20]; /* duration time, this is a null-terminated ASCII text-string */ char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; /* description of the event in UTF-8, this is a null terminated string */ - }; - - -struct edf_hdr_struct{ /* this structure contains all the relevant EDF header info and will be filled when calling the function edf_open_file_readonly() */ - int handle; /* a handle (identifier) used to distinguish the different files */ - int filetype; /* 0: EDF, 1: EDFplus, 2: BDF, 3: BDFplus, a negative number means an error */ - int edfsignals; /* number of EDF signals in the file, annotation channels are NOT included */ - long long file_duration; /* duration of the file expressed in units of 100 nanoSeconds */ +} edflib_annotation_t; + +typedef struct edf_hdr_struct +{ /* this structure contains all the relevant EDF header info and will be filled when calling the function edf_open_file_readonly() */ + int handle; /* a handle (identifier) used to distinguish the different files */ + int filetype; /* 0: EDF, 1: EDF+, 2: BDF, 3: BDF+, a negative number means an error */ + int edfsignals; /* number of EDF signals in the file, annotation channels are NOT included */ + long long file_duration; /* duration of the file expressed in units of 100 nanoseconds */ int startdate_day; int startdate_month; int startdate_year; - long long starttime_subsecond; /* starttime offset expressed in units of 100 nanoSeconds. Is always less than 10000000 (one second). Only used by EDFplus and BDFplus */ + long long starttime_subsecond; /* starttime offset expressed in units of 100 nanoseconds. Is always less than 10000000 (one second). Only used by EDF+ and BDF+ */ int starttime_second; int starttime_minute; int starttime_hour; - char patient[81]; /* null-terminated string, contains patientfield of header, is always empty when filetype is EDFPLUS or BDFPLUS */ - char recording[81]; /* null-terminated string, contains recordingfield of header, is always empty when filetype is EDFPLUS or BDFPLUS */ + char patient[81]; /* null-terminated string, contains patient field of header, is always empty when filetype is EDFPLUS or BDFPLUS */ + char recording[81]; /* null-terminated string, contains recording field of header, is always empty when filetype is EDFPLUS or BDFPLUS */ char patientcode[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ - char gender[16]; /* null-terminated string, is always empty when filetype is EDF or BDF */ + char sex[16]; /* null-terminated string, is always empty when filetype is EDF or BDF */ +#if defined(__GNUC__) + char gender[16] __attribute__ ((deprecated ("use sex"))); /* DEPRECATED!! use "sex" */ +#else + char gender[16]; /* DEPRECATED!! use "sex" */ +#endif char birthdate[16]; /* null-terminated string, is always empty when filetype is EDF or BDF */ + int birthdate_day; /* 1 - 31 */ + int birthdate_month; /* 1 - 12 */ + int birthdate_year; char patient_name[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char patient_additional[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char admincode[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char technician[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char equipment[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char recording_additional[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ - long long datarecord_duration; /* duration of a datarecord expressed in units of 100 nanoSeconds */ + long long datarecord_duration; /* duration of a datarecord expressed in units of 100 nanoseconds */ long long datarecords_in_file; /* number of datarecords in the file */ long long annotations_in_file; /* number of annotations in the file */ - struct edf_param_struct signalparam[EDFLIB_MAXSIGNALS]; /* array of structs which contain the relevant signal parameters */ - }; - - - + edflib_param_t signalparam[EDFLIB_MAXSIGNALS]; /* array of structs which contain the relevant signal parameters */ +} edflib_hdr_t; /***************** the following functions are used to read files **************************/ -int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int read_annotations, int check_file_size); - -/* opens an existing file for reading */ -/* path is a null-terminated string containing the path to the file */ -/* hdr is a pointer to an edf_hdr_struct, all fields in this struct will be overwritten */ -/* the edf_hdr_struct will be filled with all the relevant header- and signalinfo/parameters */ - -/* read_annotations must have one of the following values: */ -/* EDFLIB_DO_NOT_READ_ANNOTATIONS annotations will not be read (this saves time when opening a very large EDFplus or BDFplus file */ -/* EDFLIB_READ_ANNOTATIONS annotations will be read immediately, stops when an annotation has */ -/* been found which contains the description "Recording ends" */ -/* EDFLIB_READ_ALL_ANNOTATIONS all annotations will be read immediately - */ -/* check_file_size must have one of the following values: */ -/* EDFLIB_CHECK_FILE_SIZE file size is checked and if wrong, the file will not be opened*/ -/* EDFLIB_DO_NOT_CHECK_FILE_SIZE the file will alsways be opened and the file size is not checked*/ -/* EDFLIB_REPAIR_FILE_SIZE_IF_WRONG the file size is checked and if it is wrong it will be fixed*/ - -/* returns 0 on success, in case of an error it returns -1 and an errorcode will be set in the member "filetype" of struct edf_hdr_struct */ -/* This function is required if you want to read a file */ - - - -int edfread_physical_samples(int handle, int edfsignal, int n, double *buf); - -/* reads n samples from edfsignal, starting from the current sample position indicator, into buf (edfsignal starts at 0) */ -/* the values are converted to their physical values e.g. microVolts, beats per minute, etc. */ -/* bufsize should be equal to or bigger than sizeof(double[n]) */ -/* the sample position indicator will be increased with the amount of samples read */ -/* returns the amount of samples read (this can be less than n or zero!) */ -/* or -1 in case of an error */ - - -int edfread_digital_samples(int handle, int edfsignal, int n, int *buf); - -/* reads n samples from edfsignal, starting from the current sample position indicator, into buf (edfsignal starts at 0) */ -/* the values are the "raw" digital values */ -/* bufsize should be equal to or bigger than sizeof(int[n]) */ -/* the sample position indicator will be increased with the amount of samples read */ -/* returns the amount of samples read (this can be less than n or zero!) */ -/* or -1 in case of an error */ - - -long long edfseek(int handle, int edfsignal, long long offset, int whence); - -/* The edfseek() function sets the sample position indicator for the edfsignal pointed to by edfsignal. */ -/* The new position, measured in samples, is obtained by adding offset samples to the position specified by whence. */ -/* If whence is set to EDFSEEK_SET, EDFSEEK_CUR, or EDFSEEK_END, the offset is relative to the start of the file, */ -/* the current position indicator, or end-of-file, respectively. */ -/* Returns the current offset. Otherwise, -1 is returned. */ -/* note that every signal has it's own independent sample position indicator and edfseek() affects only one of them */ - - -long long edftell(int handle, int edfsignal); - -/* The edftell() function obtains the current value of the sample position indicator for the edfsignal pointed to by edfsignal. */ -/* Returns the current offset. Otherwise, -1 is returned */ -/* note that every signal has it's own independent sample position indicator and edftell() affects only one of them */ - - -void edfrewind(int handle, int edfsignal); - -/* The edfrewind() function sets the sample position indicator for the edfsignal pointed to by edfsignal to the beginning of the file. */ -/* It is equivalent to: (void) edfseek(int handle, int edfsignal, 0LL, EDFSEEK_SET) */ -/* note that every signal has it's own independent sample position indicator and edfrewind() affects only one of them */ - - -int edf_get_annotation(int handle, int n, struct edf_annotation_struct *annot); - -/* Fills the edf_annotation_struct with the annotation n, returns 0 on success, otherwise -1 */ -/* The string that describes the annotation/event is encoded in UTF-8 */ -/* To obtain the number of annotations in a file, check edf_hdr_struct -> annotations_in_file. */ -/* returns 0 on success or -1 in case of an error */ - -/* -Notes: - -Annotationsignals -================= - -EDFplus and BDFplus store the annotations in one or more signals (in order to be backwards compatibel with EDF and BDF). -The counting of the signals in the file starts at 0. Signals used for annotations are skipped by EDFlib. -This means that the annotationsignal(s) in the file are hided. -Use the function edf_get_annotation() to get the annotations. - -So, when a file contains 5 signals and the third signal is used to store the annotations, the library will -report that there are only 4 signals in the file. -The library will "map" the signalnumbers as follows: 0->0, 1->1, 2->3, 3->4. -This way you don't need to worry about which signals are annotationsignals, the library will take care of it. - -How the library stores time-values -================================== - -To avoid rounding errors, the library stores some timevalues in variables of type long long int. -In order not to loose the subsecond precision, all timevalues have been multiplied by 10000000. -This will limit the timeresolution to 100 nanoSeconds. To calculate the amount of seconds, divide -the timevalue by 10000000 or use the macro EDFLIB_TIME_DIMENSION which is declared in edflib.h. -The following variables do use this when you open a file in read mode: "file_duration", "starttime_subsecond" and "onset". -*/ - -/***************** the following functions are used to read or write files **************************/ - -int edfclose_file(int handle); - -/* closes (and in case of writing, finalizes) the file */ -/* returns -1 in case of an error, 0 on success */ -/* this function MUST be called when you are finished reading or writing */ -/* This function is required after reading or writing. Failing to do so will cause */ -/* unnessecary memory usage and in case of writing it will cause a corrupted and incomplete file */ - +EDFLIB_API int edfopen_file_readonly(const char *path, edflib_hdr_t *edfhdr, int read_annotations, int check_file_size); +/* opens an existing file for reading + * path is a null-terminated string containing the path to the file + * hdr is a pointer to an edf_hdr_struct, all fields in this struct will be overwritten + * the edf_hdr_struct will be filled with all the relevant header- and signalinfo/parameters + + * read_annotations must have one of the following values: + * EDFLIB_DO_NOT_READ_ANNOTATIONS annotations will not be read (this saves time when opening a very large EDF+ or BDF+ file + * EDFLIB_READ_ANNOTATIONS annotations will be read immediately, stops when an annotation has + * been found which contains the description "Recording ends" + * EDFLIB_READ_ALL_ANNOTATIONS all annotations will be read immediately + + * check_file_size must have one of the following values: + * EDFLIB_CHECK_FILE_SIZE file size is checked and if wrong, the file will not be opened + * EDFLIB_DO_NOT_CHECK_FILE_SIZE the file will alsways be opened and the file size is not checked + * EDFLIB_REPAIR_FILE_SIZE_IF_WRONG the file size is checked and if it is wrong it will be fixed + + * returns 0 on success, in case of an error it returns -1 and an error code will be set in the member "filetype" of edflib_hdr_t + * This function is required if you want to read a file + */ -int edflib_version(void); +EDFLIB_API int edfread_physical_samples(int handle, int edfsignal, int n, double *buf); +/* reads n samples from edfsignal, starting from the current sample position indicator, into buf (edfsignal starts at 0) + * the values are converted to their physical values e.g. microVolts, beats per minute, etc. + * bufsize should be equal to or bigger than sizeof(double[n]) + * the sample position indicator will be increased with the amount of samples read + * returns the amount of samples read (this can be less than n or zero!) + * or -1 in case of an error + */ -/* Returns the version number of this library, multiplied by hundred. if version is "1.00" than it will return 100 */ +EDFLIB_API int edfread_digital_samples(int handle, int edfsignal, int n, int *buf); +/* reads n samples from edfsignal, starting from the current sample position indicator, into buf (edfsignal starts at 0) + * the values are the "raw" digital values + * bufsize should be equal to or bigger than sizeof(int[n]) + * the sample position indicator will be increased with the amount of samples read + * returns the amount of samples read (this can be less than n or zero!) + * or -1 in case of an error + */ +EDFLIB_API long long edfseek(int handle, int edfsignal, long long offset, int whence); +/* The edfseek() function sets the sample position indicator for the edfsignal pointed to by edfsignal. + * The new position, measured in samples, is obtained by adding offset samples to the position specified by whence. + * If whence is set to EDFSEEK_SET, EDFSEEK_CUR, or EDFSEEK_END, the offset is relative to the start of the file, + * the current position indicator, or end-of-file, respectively. + * Returns the current offset. Otherwise, -1 is returned. + * note that every signal has it's own independent sample position indicator and edfseek() affects only one of them + */ -int edflib_is_file_used(const char *path); +EDFLIB_API long long edftell(int handle, int edfsignal); +/* The edftell() function obtains the current value of the sample position indicator for the edfsignal pointed to by edfsignal. + * Returns the current offset. Otherwise, -1 is returned + * note that every signal has it's own independent sample position indicator and edftell() affects only one of them + */ -/* returns 1 if the file is used, either for reading or writing */ -/* otherwise returns 0 */ +EDFLIB_API void edfrewind(int handle, int edfsignal); +/* The edfrewind() function sets the sample position indicator for the edfsignal pointed to by edfsignal to the beginning of the file. + * It is equivalent to: (void) edfseek(int handle, int edfsignal, 0LL, EDFSEEK_SET) + * note that every signal has it's own independent sample position indicator and edfrewind() affects only one of them + */ +EDFLIB_API int edf_get_annotation(int handle, int n, edflib_annotation_t *annot); +/* Fills the edflib_annotation_t structure with the annotation n, returns 0 on success, otherwise -1 + * The string that describes the annotation/event is encoded in UTF-8 + * To obtain the number of annotations in a file, check edf_hdr_struct -> annotations_in_file. + * returns 0 on success or -1 in case of an error + */ -int edflib_get_number_of_open_files(void); +/***************** the following functions are used in read and write mode **************************/ -/* returns the number of open files, either for reading or writing */ +EDFLIB_API int edfclose_file(int handle); +/* closes (and in case of writing, finalizes) the file + * returns -1 in case of an error, 0 on success + * this function MUST be called when you are finished reading or writing + * This function is required after reading or writing. Failing to do so will cause + * unnecessary memory usage and in case of writing it will cause a corrupted and incomplete file + */ +EDFLIB_API int edflib_version(void); +/* Returns the version number of this library, multiplied by hundred. if version is "1.00" than it will return 100 + */ -int edflib_get_handle(int file_number); +EDFLIB_API int edflib_is_file_used(const char *path); +/* returns 1 if the file is used, either for reading or writing, otherwise returns 0 + */ -/* returns the handle of an opened file, either for reading or writing */ -/* file_number starts with 0 */ -/* returns -1 if the file is not opened */ +EDFLIB_API int edflib_get_number_of_open_files(void); +/* returns the number of open files, either for reading or writing + */ +EDFLIB_API int edflib_get_handle(int file_number); +/* returns the handle of an opened file, either for reading or writing + * file_number is zero based (starts with 0) + * returns -1 if the file is not opened + */ /***************** the following functions are used to write files **************************/ +EDFLIB_API int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals); +/* opens an new file for writing. warning, an already existing file with the same name will be silently overwritten without advance warning! + * path is a null-terminated string containing the path and name of the file + * filetype must be EDFLIB_FILETYPE_EDFPLUS or EDFLIB_FILETYPE_BDFPLUS + * returns a handle on success, you need this handle for the other functions + * in case of an error it returns a negative number corresponding to one of the following values: + * EDFLIB_MALLOC_ERROR + * EDFLIB_NO_SUCH_FILE_OR_DIRECTORY + * EDFLIB_MAXFILES_REACHED + * EDFLIB_FILE_ALREADY_OPENED + * EDFLIB_NUMBER_OF_SIGNALS_INVALID + * EDFLIB_ARCH_ERROR + * This function is required if you want to write a file (or use edfopen_file_writeonly_with_params()) + */ -int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals); - -/* opens an new file for writing. warning, an already existing file with the same name will be silently overwritten without advance warning!! */ -/* path is a null-terminated string containing the path and name of the file */ -/* filetype must be EDFLIB_FILETYPE_EDFPLUS or EDFLIB_FILETYPE_BDFPLUS */ -/* returns a handle on success, you need this handle for the other functions */ -/* in case of an error it returns a negative number corresponding to one of the following values: */ -/* EDFLIB_MALLOC_ERROR */ -/* EDFLIB_NO_SUCH_FILE_OR_DIRECTORY */ -/* EDFLIB_MAXFILES_REACHED */ -/* EDFLIB_FILE_ALREADY_OPENED */ -/* EDFLIB_NUMBER_OF_SIGNALS_INVALID */ -/* This function is required if you want to write a file */ - - -int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency); - -/* Sets the samplefrequency of signal edfsignal. (In reallity, it sets the number of samples in a datarecord.) */ -/* Returns 0 on success, otherwise -1 */ -/* This function is required for every signal and can be called only after opening a */ -/* file in writemode and before the first sample write action */ - - -int edf_set_physical_maximum(int handle, int edfsignal, double phys_max); - -/* Sets the maximum physical value of signal edfsignal. (the value of the input of the ADC when the output equals the value of "digital maximum") */ -/* Returns 0 on success, otherwise -1 */ -/* This function is required for every signal and can be called only after opening a */ -/* file in writemode and before the first sample write action */ - - -int edf_set_physical_minimum(int handle, int edfsignal, double phys_min); - -/* Sets the minimum physical value of signal edfsignal. (the value of the input of the ADC when the output equals the value of "digital minimum") */ -/* Usually this will be (-(phys_max)) */ -/* Returns 0 on success, otherwise -1 */ -/* This function is required for every signal and can be called only after opening a */ -/* file in writemode and before the first sample write action */ - - -int edf_set_digital_maximum(int handle, int edfsignal, int dig_max); - -/* Sets the maximum digital value of signal edfsignal. The maximum value is 32767 for EDF+ and 8388607 for BDF+ */ -/* Usually it's the extreme output of the ADC */ -/* Returns 0 on success, otherwise -1 */ -/* This function is required for every signal and can be called only after opening a file in writemode */ -/* and before the first sample write action */ - - -int edf_set_digital_minimum(int handle, int edfsignal, int dig_min); - -/* Sets the minimum digital value of signal edfsignal. The minimum value is -32768 for EDF+ and -8388608 for BDF+ */ -/* Usually it's the extreme output of the ADC */ -/* Usually this will be (-(dig_max + 1)) */ -/* Returns 0 on success, otherwise -1 */ -/* This function is required for every signal and can be called only after opening a file in writemode */ -/* and before the first sample write action */ - - -int edf_set_label(int handle, int edfsignal, const char *label); - -/* Sets the label (name) of signal edfsignal. ("FP1", "SaO2", etc.) */ -/* label is a pointer to a NULL-terminated ASCII-string containing the label (name) of the signal edfsignal */ -/* Returns 0 on success, otherwise -1 */ -/* This function is recommended for every signal when you want to write a file */ -/* and can be called only after opening a file in writemode and before the first sample write action */ - - -int edf_set_prefilter(int handle, int edfsignal, const char *prefilter); - -/* Sets the prefilter of signal edfsignal ("HP:0.1Hz", "LP:75Hz N:50Hz", etc.). */ -/* prefilter is a pointer to a NULL-terminated ASCII-string containing the prefilter text of the signal edfsignal */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode and before */ -/* the first sample write action */ - - -int edf_set_transducer(int handle, int edfsignal, const char *transducer); - -/* Sets the transducer of signal edfsignal ("AgAgCl cup electrodes", etc.). */ -/* transducer is a pointer to a NULL-terminated ASCII-string containing the transducer text of the signal edfsignal */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode and before */ -/* the first sample write action */ - - -int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim); - -/* Sets the physical dimension (unit) of signal edfsignal. ("uV", "BPM", "mA", "Degr.", etc.) */ -/* phys_dim is a pointer to a NULL-terminated ASCII-string containing the physical dimension of the signal edfsignal */ -/* Returns 0 on success, otherwise -1 */ -/* This function is recommended for every signal when you want to write a file */ -/* and can be called only after opening a file in writemode and before the first sample write action */ - - -int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day, - int starttime_hour, int starttime_minute, int starttime_second); - -/* Sets the startdate and starttime. */ -/* year: 1970 - 3000, month: 1 - 12, day: 1 - 31 */ -/* hour: 0 - 23, minute: 0 - 59, second: 0 - 59 */ -/* If not called, the library will use the system date and time at runtime */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ - - -int edf_set_patientname(int handle, const char *patientname); +EDFLIB_API 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); +/* this is a convenience function that can create a new EDF file and initializes the most important parameters. + * it assumes that all signals are sharing the same parameters (you can still change them though). + * warning, an already existing file with the same name will be silently overwritten without advance warning! + * path is a null-terminated string containing the path and name of the file + * filetype must be EDFLIB_FILETYPE_EDFPLUS or EDFLIB_FILETYPE_BDFPLUS + * Sets the sample frequency of all signals. (In reality, it sets the number of samples per datarecord which equals the sample frequency only when + * the datarecords have a duration of 1 second) + * Sets the physical maximum of all signals to phys_max_min. + * Sets the physical minimum of all signals to -phys_max_min. + * Sets the physical dimension (unit) of all signals ("uV", "BPM", "mA", "Degr.", etc.). + * phys_dim is a pointer to a NULL-terminated ASCII-string containing the physical dimension of the signals + * returns a handle on success, you need this handle for the other functions + * in case of an error it returns a negative number corresponding to one of the following values: + * EDFLIB_MALLOC_ERROR + * EDFLIB_NO_SUCH_FILE_OR_DIRECTORY + * EDFLIB_MAXFILES_REACHED + * EDFLIB_FILE_ALREADY_OPENED + * EDFLIB_NUMBER_OF_SIGNALS_INVALID + * EDFLIB_ARCH_ERROR + * This function is required if you want to write a file (or use edfopen_file_writeonly()) + */ -/* Sets the patientname. patientname is a pointer to a null-terminated ASCII-string. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +EDFLIB_API int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency); +/* Sets the sample frequency of signal edfsignal. In reality, it sets the number of samples in a datarecord + * which equals the sample frequency only when the datarecords have a duration of 1 second. + * The effective sample frequency is: samplefrequency / datarecord duration + * Returns 0 on success, otherwise -1 + * This function is required for every signal and can be called only after opening a + * file in write mode and before the first sample write action + */ +EDFLIB_API int edf_set_physical_maximum(int handle, int edfsignal, double phys_max); +/* Sets the maximum physical value of signal edfsignal. (the value of the input of the ADC when the output equals the value of "digital maximum") + * It is the highest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level + * Must be un-equal to physical minimum + * Returns 0 on success, otherwise -1 + * This function is required for every signal and can be called only after opening a + * file in write mode and before the first sample write action + */ -int edf_set_patientcode(int handle, const char *patientcode); +EDFLIB_API int edf_set_physical_minimum(int handle, int edfsignal, double phys_min); +/* Sets the minimum physical value of signal edfsignal. (the value of the input of the ADC when the output equals the value of "digital minimum") + * It is the lowest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level + * Usually this will be (-(phys_max)) + * Must be un-equal to physical maximum + * Returns 0 on success, otherwise -1 + * This function is required for every signal and can be called only after opening a + * file in write mode and before the first sample write action + */ -/* Sets the patientcode. patientcode is a pointer to a null-terminated ASCII-string. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +EDFLIB_API int edf_set_digital_maximum(int handle, int edfsignal, int dig_max); +/* Sets the maximum digital value of signal edfsignal. The maximum value is 32767 for EDF+ and 8388607 for BDF+ + * It is the highest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level + * Usually it's the extreme output of the ADC + * Must be higher than digital minimum + * Returns 0 on success, otherwise -1 + * This function is required for every signal and can be called only after opening a file in write mode + * and before the first sample write action + */ +EDFLIB_API int edf_set_digital_minimum(int handle, int edfsignal, int dig_min); +/* Sets the minimum digital value of signal edfsignal. The minimum value is -32768 for EDF+ and -8388608 for BDF+ + * It is the lowest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level + * Usually it's the extreme output of the ADC + * Usually this will be (-(dig_max + 1)) + * Must be lower than digital maximum + * Returns 0 on success, otherwise -1 + * This function is required for every signal and can be called only after opening a file in write mode + * and before the first sample write action + */ -int edf_set_gender(int handle, int gender); +EDFLIB_API int edf_set_label(int handle, int edfsignal, const char *label); +/* Sets the label (name) of signal edfsignal. ("FP1", "SaO2", etc.) + * label is a pointer to a NULL-terminated ASCII-string containing the label (name) of the signal edfsignal + * Returns 0 on success, otherwise -1 + * This function is recommended for every signal when you want to write a file + * and can be called only after opening a file in write mode and before the first sample write action + */ -/* Sets the gender. 1 is male, 0 is female. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +EDFLIB_API int edf_set_prefilter(int handle, int edfsignal, const char *prefilter); +/* Sets the prefilter of signal edfsignal ("HP:0.1Hz", "LP:75Hz N:50Hz", etc.). + * prefilter is a pointer to a NULL-terminated ASCII-string containing the prefilter text of the signal edfsignal + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in write mode and before + * the first sample write action + */ +EDFLIB_API int edf_set_transducer(int handle, int edfsignal, const char *transducer); +/* Sets the transducer of signal edfsignal ("AgAgCl cup electrodes", etc.). + * transducer is a pointer to a NULL-terminated ASCII-string containing the transducer text of the signal edfsignal + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode and before + * the first sample write action + */ +EDFLIB_API int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim); +/* Sets the physical dimension (unit) of signal edfsignal. ("uV", "BPM", "mA", "Degr.", etc.) + * phys_dim is a pointer to a NULL-terminated ASCII-string containing the physical dimension of the signal edfsignal + * Returns 0 on success, otherwise -1 + * This function is recommended for every signal when you want to write a file + * and can be called only after opening a file in write mode and before the first sample write action + */ -int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day); +EDFLIB_API int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day, + int starttime_hour, int starttime_minute, int starttime_second); +/* Sets the startdate and starttime. + * year: 1985 - 2084, month: 1 - 12, day: 1 - 31 + * hour: 0 - 23, minute: 0 - 59, second: 0 - 59 + * If not called, the library will use the system date and time at runtime + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in write mode + * and before the first sample write action + * Note: for anonymization purposes, the consensus is to use 1985-01-01 00:00:00 for the startdate and starttime. + */ -/* Sets the birthdate. */ -/* year: 1800 - 3000, month: 1 - 12, day: 1 - 31 */ -/* This function is optional */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +EDFLIB_API int edf_set_patientname(int handle, const char *patientname); +/* Sets the patientname. patientname is a pointer to a null-terminated ASCII-string. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ +EDFLIB_API int edf_set_patientcode(int handle, const char *patientcode); +/* Sets the patientcode. patientcode is a pointer to a null-terminated ASCII-string. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ -int edf_set_patient_additional(int handle, const char *patient_additional); +EDFLIB_API int edf_set_sex(int handle, int sex); +/* Sets the sex. 1 is male, 0 is female. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ -/* Sets the additional patientinfo. patient_additional is a pointer to a null-terminated ASCII-string. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +#if defined(__GNUC__) +EDFLIB_API int edf_set_gender(int handle, int sex) __attribute__ ((deprecated ("use edf_set_sex()"))); +#else +EDFLIB_API int edf_set_gender(int handle, int sex); +#endif +/* DEPRECATED!! USE edf_set_sex() + * Sets the sex. 1 is male, 0 is female. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ +EDFLIB_API int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day); +/* Sets the birthdate. + * year: 1800 - 3000, month: 1 - 12, day: 1 - 31 + * This function is optional + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ -int edf_set_admincode(int handle, const char *admincode); +EDFLIB_API int edf_set_patient_additional(int handle, const char *patient_additional); +/* Sets the additional patientinfo. patient_additional is a pointer to a null-terminated ASCII-string. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ -/* Sets the admincode. admincode is a pointer to a null-terminated ASCII-string. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +EDFLIB_API int edf_set_admincode(int handle, const char *admincode); +/* Sets the admincode. admincode is a pointer to a null-terminated ASCII-string. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ +EDFLIB_API int edf_set_technician(int handle, const char *technician); +/* Sets the technicians name. technician is a pointer to a null-terminated ASCII-string. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ -int edf_set_technician(int handle, const char *technician); +EDFLIB_API int edf_set_equipment(int handle, const char *equipment); +/* Sets the name of the equipment used during the acquisition. equipment is a pointer to a null-terminated ASCII-string. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ -/* Sets the technicians name. technician is a pointer to a null-terminated ASCII-string. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +EDFLIB_API int edf_set_recording_additional(int handle, const char *recording_additional); +/* Sets the additional recordinginfo. recording_additional is a pointer to a null-terminated ASCII-string. + * Returns 0 on success, otherwise -1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + */ +EDFLIB_API int edfwrite_physical_samples(int handle, double *buf); +/* Writes n physical samples (uV, mA, Ohm) from *buf belonging to one signal + * where n is the samplefrequency of that signal. + * The physical samples will be converted to digital samples using the + * values of physical maximum, physical minimum, digital maximum and digital minimum + * The number of samples written is equal to the samplefrequency of the signal + * Size of buf should be equal to or bigger than sizeof(double[samplefrequency]) + * Call this function for every signal in the file. The order is important! + * When there are 4 signals in the file, the order of calling this function + * must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. + * Returns 0 on success, otherwise -1 + */ -int edf_set_equipment(int handle, const char *equipment); +EDFLIB_API int edf_blockwrite_physical_samples(int handle, double *buf); +/* Writes physical samples (uV, mA, Ohm) from *buf + * buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. + * where n is the samplefrequency of that signal. + * buf must be filled with samples from all signals, starting with signal 0, 1, 2, etc. + * one block equals one second + * The physical samples will be converted to digital samples using the + * values of physical maximum, physical minimum, digital maximum and digital minimum + * The number of samples written is equal to the sum of the samplefrequencies of all signals + * Size of buf should be equal to or bigger than sizeof(double) multiplied by the sum of the samplefrequencies of all signals + * Returns 0 on success, otherwise -1 + */ -/* Sets the name of the equipment used during the aquisition. equipment is a pointer to a null-terminated ASCII-string. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +EDFLIB_API int edfwrite_digital_short_samples(int handle, short *buf); +/* Writes n "raw" digital samples from *buf belonging to one signal + * where n is the samplefrequency of that signal. + * The samples will be written to the file without any conversion. + * Because the size of a short is 16-bit, do not use this function with BDF (24-bit) + * The number of samples written is equal to the samplefrequency of the signal + * Size of buf should be equal to or bigger than sizeof(short[samplefrequency]) + * Call this function for every signal in the file. The order is important! + * When there are 4 signals in the file, the order of calling this function + * must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. + * Returns 0 on success, otherwise -1 + */ +EDFLIB_API int edfwrite_digital_samples(int handle, int *buf); +/* Writes n "raw" digital samples from *buf belonging to one signal + * where n is the samplefrequency of that signal. + * The 16 (or 24 in case of BDF) least significant bits of the sample will be written to the + * file without any conversion. + * The number of samples written is equal to the samplefrequency of the signal + * Size of buf should be equal to or bigger than sizeof(int[samplefrequency]) + * Call this function for every signal in the file. The order is important! + * When there are 4 signals in the file, the order of calling this function + * must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. + * Returns 0 on success, otherwise -1 + */ -int edf_set_recording_additional(int handle, const char *recording_additional); +EDFLIB_API int edf_blockwrite_digital_3byte_samples(int handle, void *buf); +/* Writes "raw" digital samples from *buf. + * buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. + * where n is the samplefrequency of that signal. + * One block equals one second. One sample equals 3 bytes, order is little endian (least significant byte first) + * Encoding is second's complement, most significant bit of most significant byte is the sign-bit + * The samples will be written to the file without any conversion. + * Because the size of a 3-byte sample is 24-bit, this function can only be used when writing a BDF file + * The number of samples written is equal to the sum of the samplefrequencies of all signals. + * Size of buf should be equal to or bigger than: the sum of the samplefrequencies of all signals x 3 bytes + * Returns 0 on success, otherwise -1 + */ -/* Sets the additional recordinginfo. recording_additional is a pointer to a null-terminated ASCII-string. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ +EDFLIB_API int edf_blockwrite_digital_short_samples(int handle, short *buf); +/* Writes "raw" digital samples from *buf. + * buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. + * where n is the samplefrequency of that signal. + * One block equals one second. + * The samples will be written to the file without any conversion. + * Because the size of a short is 16-bit, do not use this function with BDF (24-bit) + * The number of samples written is equal to the sum of the samplefrequencies of all signals. + * Size of buf should be equal to or bigger than sizeof(short) multiplied by the sum of the samplefrequencies of all signals + * Returns 0 on success, otherwise -1 + */ +EDFLIB_API int edf_blockwrite_digital_samples(int handle, int *buf); +/* Writes "raw" digital samples from *buf. + * buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. + * where n is the samplefrequency of that signal. + * One block equals one second. + * The 16 (or 24 in case of BDF) least significant bits of the sample will be written to the + * file without any conversion. + * The number of samples written is equal to the sum of the samplefrequencies of all signals. + * Size of buf should be equal to or bigger than sizeof(int) multiplied by the sum of the samplefrequencies of all signals + * Returns 0 on success, otherwise -1 + */ -int edfwrite_physical_samples(int handle, double *buf); +EDFLIB_API int edfwrite_annotation_utf8_hr(int handle, long long onset, long long duration, const char *description); +/* writes an annotation/event to the file + * onset is relative to the start of the file + * onset and duration are in units of 1 microSecond resolution is 0.000001 second + * for example: 34.071 seconds must be written as 34071000 + * if duration is unknown or not applicable: set a negative number (-1) + * description is a null-terminated UTF8-string containing the text that describes the event + * This function is optional and can be called only after opening a file in writemode + * and before closing the file + */ -/* Writes n physical samples (uV, mA, Ohm) from *buf belonging to one signal */ -/* where n is the samplefrequency of that signal. */ -/* The physical samples will be converted to digital samples using the */ -/* values of physical maximum, physical minimum, digital maximum and digital minimum */ -/* The number of samples written is equal to the samplefrequency of the signal */ -/* Size of buf should be equal to or bigger than sizeof(double[samplefrequency]) */ -/* Call this function for every signal in the file. The order is important! */ -/* When there are 4 signals in the file, the order of calling this function */ -/* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. */ -/* Returns 0 on success, otherwise -1 */ +#if defined(__GNUC__) +EDFLIB_API int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description) __attribute__ ((deprecated ("use edfwrite_annotation_utf8_hr()"))); +#else +EDFLIB_API int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description); +#endif +/* DEPRECATED!! USE edfwrite_annotation_utf8_hr() + * writes an annotation/event to the file + * onset is relative to the start of the file + * onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! + * for example: 34.071 seconds must be written as 340710 + * if duration is unknown or not applicable: set a negative number (-1) + * description is a null-terminated UTF8-string containing the text that describes the event + * This function is optional and can be called only after opening a file in writemode + * and before closing the file + */ +EDFLIB_API int edfwrite_annotation_latin1_hr(int handle, long long onset, long long duration, const char *description); +/* writes an annotation/event to the file + * onset is relative to the start of the file + * onset and duration are in units of 1 microSecond resolution is 0.000001 second + * for example: 34.071 seconds must be written as 34071000 + * if duration is unknown or not applicable: set a negative number (-1) + * description is a null-terminated Latin1-string containing the text that describes the event + * This function is optional and can be called only after opening a file in writemode + * and before closing the file + */ -int edf_blockwrite_physical_samples(int handle, double *buf); +#if defined(__GNUC__) +EDFLIB_API int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description) __attribute__ ((deprecated ("use edfwrite_annotation_latin1_hr()"))); +#else +EDFLIB_API int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description); +#endif +/* DEPRECATED!! USE edfwrite_annotation_latin1_hr() + * writes an annotation/event to the file + * onset is relative to the start of the file + * onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! + * for example: 34.071 seconds must be written as 340710 + * if duration is unknown or not applicable: set a negative number (-1) + * description is a null-terminated Latin1-string containing the text that describes the event + * This function is optional and can be called only after opening a file in writemode + * and before closing the file + */ -/* Writes physical samples (uV, mA, Ohm) from *buf */ -/* buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. */ -/* where n is the samplefrequency of that signal. */ -/* buf must be filled with samples from all signals, starting with signal 0, 1, 2, etc. */ -/* one block equals one second */ -/* The physical samples will be converted to digital samples using the */ -/* values of physical maximum, physical minimum, digital maximum and digital minimum */ -/* The number of samples written is equal to the sum of the samplefrequencies of all signals */ -/* Size of buf should be equal to or bigger than sizeof(double) multiplied by the sum of the samplefrequencies of all signals */ -/* Returns 0 on success, otherwise -1 */ +EDFLIB_API int edf_set_datarecord_duration(int handle, int duration); +/* Sets the datarecord duration. The default value is 1 second. + * ATTENTION: the argument "duration" is expressed in units of 10 microSeconds! + * So, if you want to set the datarecord duration to 0.1 second, you must give + * the argument "duration" a value of "10000". + * This function is optional, normally you don't need to change the default value. + * The datarecord duration must be in the range 0.001 to 60 seconds. + * Returns 0 on success, otherwise -1 + * This function is NOT REQUIRED but can be called after opening a + * file in writemode and before the first sample write action. + * This function can be used when you want to use a samplerate + * which is not an integer. For example, if you want to use a samplerate of 0.5 Hz, + * set the samplefrequency to 5 Hz and the datarecord duration to 10 seconds, + * or set the samplefrequency to 1 Hz and the datarecord duration to 2 seconds. + * Do not use this function if not necessary. + */ +EDFLIB_API int edf_set_micro_datarecord_duration(int handle, int duration); +/* Sets the datarecord duration to a very small value. + * ATTENTION: the argument "duration" is expressed in units of 1 microSecond! + * This function is optional, normally you don't need to change the default value. + * The datarecord duration must be in the range 1 to 9999 micro-seconds. + * Returns 0 on success, otherwise -1 + * This function is NOT REQUIRED but can be called after opening a + * file in writemode and before the first sample write action. + * This function can be used when you want to use a very high samplerate. + * For example, if you want to use a samplerate of 5 GHz, + * set the samplefrequency to 5000 Hz and the datarecord duration to 1 micro-second. + * Do not use this function if not necessary. + * This function was added to accommodate for high speed ADC's e.g. Digital Sampling Oscilloscopes + */ -int edfwrite_digital_short_samples(int handle, short *buf); +EDFLIB_API int edf_set_number_of_annotation_signals(int handle, int annot_signals); +/* Sets the number of annotation signals. The default value is 1 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + * Normally you don't need to change the default value. Only when the number of annotations + * you want to write is higher than the number of datarecords in the recording, you can use + * this function to increase the storage space for annotations + * Minimum is 1, maximum is 64 + * Returns 0 on success, otherwise -1 + */ -/* Writes n "raw" digital samples from *buf belonging to one signal */ -/* where n is the samplefrequency of that signal. */ -/* The samples will be written to the file without any conversion. */ -/* Because the size of a short is 16-bit, do not use this function with BDF (24-bit) */ -/* The number of samples written is equal to the samplefrequency of the signal */ -/* Size of buf should be equal to or bigger than sizeof(short[samplefrequency]) */ -/* Call this function for every signal in the file. The order is important! */ -/* When there are 4 signals in the file, the order of calling this function */ -/* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. */ -/* Returns 0 on success, otherwise -1 */ +EDFLIB_API int edf_set_subsecond_starttime(int handle, int subsecond); +/* Sets the subsecond starttime expressed in units of 100 nanoseconds + * Valid range is 0 to 9999999 inclusive. Default is 0 + * This function is optional and can be called only after opening a file in writemode + * and before the first sample write action + * Returns 0 on success, otherwise -1 + * It is strongly recommended to use a maximum resolution of no more than 100 micro-Seconds. + * e.g. use 1234000 to set a starttime offset of 0.1234 seconds (instead of 1234567) + * in other words, leave the last 3 digits at zero + */ +#ifdef __cplusplus +} /* extern "C" */ +#endif -int edfwrite_digital_samples(int handle, int *buf); +#endif -/* Writes n "raw" digital samples from *buf belonging to one signal */ -/* where n is the samplefrequency of that signal. */ -/* The 16 (or 24 in case of BDF) least significant bits of the sample will be written to the */ -/* file without any conversion. */ -/* The number of samples written is equal to the samplefrequency of the signal */ -/* Size of buf should be equal to or bigger than sizeof(int[samplefrequency]) */ -/* Call this function for every signal in the file. The order is important! */ -/* When there are 4 signals in the file, the order of calling this function */ -/* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. */ -/* Returns 0 on success, otherwise -1 */ -int edf_blockwrite_digital_3byte_samples(int handle, void *buf); -/* Writes "raw" digital samples from *buf. */ -/* buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. */ -/* where n is the samplefrequency of that signal. */ -/* One block equals one second. One sample equals 3 bytes, order is little endian (least significant byte first) */ -/* Encoding is second's complement, most significant bit of most significant byte is the sign-bit */ -/* The samples will be written to the file without any conversion. */ -/* Because the size of a 3-byte sample is 24-bit, this function can only be used when writing a BDF file */ -/* The number of samples written is equal to the sum of the samplefrequencies of all signals. */ -/* Size of buf should be equal to or bigger than: the sum of the samplefrequencies of all signals x 3 bytes */ -/* Returns 0 on success, otherwise -1 */ - - -int edf_blockwrite_digital_short_samples(int handle, short *buf); - -/* Writes "raw" digital samples from *buf. */ -/* buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. */ -/* where n is the samplefrequency of that signal. */ -/* One block equals one second. */ -/* The samples will be written to the file without any conversion. */ -/* Because the size of a short is 16-bit, do not use this function with BDF (24-bit) */ -/* The number of samples written is equal to the sum of the samplefrequencies of all signals. */ -/* Size of buf should be equal to or bigger than sizeof(short) multiplied by the sum of the samplefrequencies of all signals */ -/* Returns 0 on success, otherwise -1 */ - - -int edf_blockwrite_digital_samples(int handle, int *buf); - -/* Writes "raw" digital samples from *buf. */ -/* buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. */ -/* where n is the samplefrequency of that signal. */ -/* One block equals one second. */ -/* The 16 (or 24 in case of BDF) least significant bits of the sample will be written to the */ -/* file without any conversion. */ -/* The number of samples written is equal to the sum of the samplefrequencies of all signals. */ -/* Size of buf should be equal to or bigger than sizeof(int) multiplied by the sum of the samplefrequencies of all signals */ -/* Returns 0 on success, otherwise -1 */ - - -int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description); - -/* writes an annotation/event to the file */ -/* onset is relative to the start of the file */ -/* onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! */ -/* for example: 34.071 seconds must be written as 340710 */ -/* if duration is unknown or not applicable: set a negative number (-1) */ -/* description is a null-terminated UTF8-string containing the text that describes the event */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before closing the file */ - - -int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description); - -/* writes an annotation/event to the file */ -/* onset is relative to the start of the file */ -/* onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! */ -/* for example: 34.071 seconds must be written as 340710 */ -/* if duration is unknown or not applicable: set a negative number (-1) */ -/* description is a null-terminated Latin1-string containing the text that describes the event */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before closing the file */ - - -int edf_set_datarecord_duration(int handle, int duration); - -/* Sets the datarecord duration. The default value is 1 second. */ -/* ATTENTION: the argument "duration" is expressed in units of 10 microSeconds! */ -/* So, if you want to set the datarecord duration to 0.1 second, you must give */ -/* the argument "duration" a value of "10000". */ -/* This function is optional, normally you don't need to change the default value. */ -/* The datarecord duration must be in the range 0.001 to 60 seconds. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is NOT REQUIRED but can be called after opening a */ -/* file in writemode and before the first sample write action. */ -/* This function can be used when you want to use a samplerate */ -/* which is not an integer. For example, if you want to use a samplerate of 0.5 Hz, */ -/* set the samplefrequency to 5 Hz and the datarecord duration to 10 seconds, */ -/* or set the samplefrequency to 1 Hz and the datarecord duration to 2 seconds. */ -/* Do not use this function if not necessary. */ - - -int edf_set_micro_datarecord_duration(int handle, int duration); - -/* Sets the datarecord duration to a very small value. */ -/* ATTENTION: the argument "duration" is expressed in units of 1 microSecond! */ -/* This function is optional, normally you don't need to change the default value. */ -/* The datarecord duration must be in the range 1 to 9999 micro-seconds. */ -/* Returns 0 on success, otherwise -1 */ -/* This function is NOT REQUIRED but can be called after opening a */ -/* file in writemode and before the first sample write action. */ -/* This function can be used when you want to use a very high samplerate. */ -/* For example, if you want to use a samplerate of 5 GHz, */ -/* set the samplefrequency to 5000 Hz and the datarecord duration to 1 micro-second. */ -/* Do not use this function if not necessary. */ -/* This function was added to accommodate for high speed ADC's e.g. Digital Sampling Oscilloscopes */ - - -int edf_set_number_of_annotation_signals(int handle, int annot_signals); - -/* Sets the number of annotation signals. The default value is 1 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ -/* Normally you don't need to change the default value. Only when the number of annotations */ -/* you want to write is higher than the number of datarecords in the recording, you can use */ -/* this function to increase the storage space for annotations */ -/* Minimum is 1, maximum is 64 */ -/* Returns 0 on success, otherwise -1 */ - - -int edf_set_subsecond_starttime(int handle, int subsecond); -/* Sets the subsecond starttime expressed in units of 100 nanoSeconds */ -/* Valid range is 0 to 9999999 inclusive. Default is 0 */ -/* This function is optional and can be called only after opening a file in writemode */ -/* and before the first sample write action */ -/* Returns 0 on success, otherwise -1 */ -/* It is strongly recommended to use a maximum resolution of no more than 100 micro-Seconds. */ -/* e.g. use 1234000 to set a starttime offset of 0.1234 seconds (instead of 1234567) */ -/* in other words, leave the last 3 digits at zero */ -#ifdef __cplusplus -} /* extern "C" */ -#endif -#endif diff --git a/pyedflib/_extensions/c_edf.pxd b/pyedflib/_extensions/c_edf.pxd index 356275cb..ba767e8f 100644 --- a/pyedflib/_extensions/c_edf.pxd +++ b/pyedflib/_extensions/c_edf.pxd @@ -7,8 +7,10 @@ include "edf.pxi" cdef extern from "c/edflib.h": int edf_set_patientcode(int, char *) - int edfwrite_annotation_latin1(int, long long int, long long int, char *) - int edfwrite_annotation_utf8(int, long long int, long long int, char *) + int edfwrite_annotation_utf8(int, long long, long long, const char *) + int edfwrite_annotation_latin1_hr(int, long long int, long long int, char *) + int edfwrite_annotation_latin1(int, long long, long long, const char *) + int edfwrite_annotation_utf8_hr(int, long long int, long long int, char *) int edflib_version() cdef struct edf_annotation_struct: long long int onset @@ -55,7 +57,7 @@ cdef extern from "c/edflib.h": char * patient char * recording char * patientcode - char * gender + char * sex char * birthdate char * patient_name char * patient_additional @@ -79,7 +81,7 @@ cdef extern from "c/edflib.h": int edf_blockwrite_digital_samples(int, int *) long long int edftell(int, int) void edfrewind(int, int) - int edf_set_gender(int, int) + int edf_set_sex(int, int) int edf_set_physical_dimension(int, int, char *) int edf_set_transducer(int, int, char *) int edf_set_prefilter(int, int, char *) diff --git a/pyedflib/edfwriter.py b/pyedflib/edfwriter.py index 5d6080b3..64d8d654 100644 --- a/pyedflib/edfwriter.py +++ b/pyedflib/edfwriter.py @@ -14,7 +14,7 @@ from ._extensions._pyedflib import set_birthdate, set_digital_minimum, set_technician, set_recording_additional, set_patientname from ._extensions._pyedflib import set_patientcode, set_equipment, set_admincode, set_sex, set_datarecord_duration, set_number_of_annotation_signals from ._extensions._pyedflib import set_startdatetime, set_starttime_subsecond, set_samples_per_record, set_physical_minimum, set_label, set_physical_dimension -from ._extensions._pyedflib import set_transducer, set_prefilter, write_physical_samples, close_file, write_annotation_latin1, write_annotation_utf8 +from ._extensions._pyedflib import set_transducer, set_prefilter, write_physical_samples, close_file, write_annotation_latin1_hr, write_annotation_utf8_hr from ._extensions._pyedflib import blockwrite_physical_samples, write_errors, blockwrite_digital_samples, write_digital_short_samples, write_digital_samples, blockwrite_digital_short_samples @@ -883,14 +883,14 @@ def writeAnnotation(self, onset_in_seconds, duration_in_seconds, description, st if str_format == 'utf_8': if duration_in_seconds >= 0: - return write_annotation_utf8(self.handle, np.round(onset_in_seconds*10000).astype(np.int64), np.round(duration_in_seconds*10000).astype(int), du(description)) + return write_annotation_utf8_hr(self.handle, np.round(onset_in_seconds*1000000).astype(np.int64), np.round(duration_in_seconds*1000000).astype(np.int64), du(description)) else: - return write_annotation_utf8(self.handle, np.round(onset_in_seconds*10000).astype(np.int64), -1, du(description)) + return write_annotation_utf8_hr(self.handle, np.round(onset_in_seconds*1000000).astype(np.int64), -1, du(description)) else: if duration_in_seconds >= 0: - return write_annotation_latin1(self.handle, np.round(onset_in_seconds*10000).astype(np.int64), np.round(duration_in_seconds*10000).astype(int), u(description).encode('latin1')) + return write_annotation_latin1_hr(self.handle, np.round(onset_in_seconds*1000000).astype(np.int64), np.round(duration_in_seconds*1000000).astype(np.int64), u(description).encode('latin1')) else: - return write_annotation_latin1(self.handle, np.round(onset_in_seconds*10000).astype(np.int64), -1, u(description).encode('latin1')) + return write_annotation_latin1_hr(self.handle, np.round(onset_in_seconds*1000000).astype(np.int64), -1, u(description).encode('latin1')) def close(self): """