edflib_124/000755 001750 000144 00000000000 14420677572 012707 5ustar00guvusers000000 000000 edflib_124/edflib.h000644 001750 000144 00000124774 14416743271 014317 0ustar00guvusers000000 000000 /* ***************************************************************************** * * Copyright (c) 2009 - 2023 Teunis van Beelen * All rights reserved. * * Email: teuniz@protonmail.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************** */ /**************************************************************************** * * 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) #define EDFLIB_MAX_ANNOTATION_LEN (512) #define EDFSEEK_SET (0) #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() */ #define EDFLIB_FILETYPE_EDF (0) #define EDFLIB_FILETYPE_EDFPLUS (1) #define EDFLIB_FILETYPE_BDF (2) #define EDFLIB_FILETYPE_BDFPLUS (3) #define EDFLIB_MALLOC_ERROR (-1) #define EDFLIB_NO_SUCH_FILE_OR_DIRECTORY (-2) /* when this error occurs, try to open the file with EDFbrowser, it will give you full details about the cause of the error. */ #define EDFLIB_FILE_CONTAINS_FORMAT_ERRORS (-3) #define EDFLIB_MAXFILES_REACHED (-4) #define EDFLIB_FILE_READ_ERROR (-5) #define EDFLIB_FILE_ALREADY_OPENED (-6) #define EDFLIB_FILETYPE_ERROR (-7) #define EDFLIB_FILE_WRITE_ERROR (-8) #define EDFLIB_NUMBER_OF_SIGNALS_INVALID (-9) #define EDFLIB_FILE_IS_DISCONTINUOUS (-10) #define EDFLIB_INVALID_READ_ANNOTS_VALUE (-11) #define EDFLIB_ARCH_ERROR (-12) /* values for annotations */ #define EDFLIB_DO_NOT_READ_ANNOTATIONS (0) #define EDFLIB_READ_ANNOTATIONS (1) #define EDFLIB_READ_ALL_ANNOTATIONS (2) /* the following defines are possible errors returned by the first sample write action */ #define EDFLIB_NO_SIGNALS (-20) #define EDFLIB_TOO_MANY_SIGNALS (-21) #define EDFLIB_NO_SAMPLES_IN_RECORD (-22) #define EDFLIB_DIGMIN_IS_DIGMAX (-23) #define EDFLIB_DIGMAX_LOWER_THAN_DIGMIN (-24) #define EDFLIB_PHYSMIN_IS_PHYSMAX (-25) #define EDFLIB_DATARECORD_SIZE_TOO_BIG (-26) #ifdef __cplusplus extern "C" { #endif 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, 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; 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 */ } 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 EDF+ and BDF+ */ int starttime_second; int starttime_minute; int starttime_hour; 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 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 datarecords_in_file; /* number of datarecords in the file */ long long annotations_in_file; /* number of annotations in the file */ 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 **************************/ EDFLIB_API int edfopen_file_readonly(const char *path, edflib_hdr_t *edfhdr, int read_annotations); /* 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 * 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 */ 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 */ 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 */ 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 */ 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 */ /***************** the following functions are used in read and write mode **************************/ 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 */ 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 */ 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()) */ 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()) */ 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 */ 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 */ 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 */ 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 */ 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 */ 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. */ 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 */ 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 */ #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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ #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 */ #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 */ 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 */ 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 */ 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 #endif edflib_124/sine_generator.c000644 001750 000144 00000010540 14416032226 016041 0ustar00guvusers000000 000000 /* ***************************************************************************** * * Copyright (c) 2009 - 2021 Teunis van Beelen * All rights reserved. * * Email: teuniz@protonmail.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY Teunis van Beelen ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Teunis van Beelen BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************** */ #include #include #include #include "edflib.h" #define SMP_FREQ (2048) #ifndef M_PI #define M_PI (3.14159265358979323846264338327) #endif int main(void) { int i, j, hdl, buf2[SMP_FREQ], chns; double buf[SMP_FREQ], q; chns = 2; hdl = edfopen_file_writeonly("sine.bdf", EDFLIB_FILETYPE_BDFPLUS, chns); if(hdl<0) { printf("error: edfopen_file_writeonly()\n"); return(1); } for(i=0; i #include #include #include "edflib.h" #define SMP_FREQ (200) #define SMP_FREQ_2 (256) #define SMP_FREQ_3 (217) #define FILE_DURATION (600) #ifndef M_PI #define M_PI (3.14159265358979323846264338327) #endif // Uncomment the next line to create a BDF+ file instead of EDF+: // #define BDF_FORMAT int main(void) { int i, j, hdl, chns; double buf[1000], q, sine_1, sine_8, sine_81777, sine_85, sine_15, sine_17, sine_50; struct{ long long samples; long long triggers[512]; int index; int code; int bitposition; int smp_in_bit; } dc_event_stat; memset(&dc_event_stat, 0, sizeof(dc_event_stat)); dc_event_stat.code = 0; dc_event_stat.triggers[0] = 1951; for(i=1; i<512; i++) { dc_event_stat.triggers[i] = (i * 1667) + 1951; } chns = 14; #ifdef BDF_FORMAT hdl = edfopen_file_writeonly("test_generator.bdf", EDFLIB_FILETYPE_BDFPLUS, chns); #else hdl = edfopen_file_writeonly("test_generator.edf", EDFLIB_FILETYPE_EDFPLUS, chns); #endif if(hdl<0) { printf("error: edfopen_file_writeonly()\n"); return(1); } for(i=0; i= 10) { dc_event_stat.smp_in_bit = 0; dc_event_stat.bitposition++; } if(dc_event_stat.bitposition > 10) { dc_event_stat.bitposition = 0; dc_event_stat.smp_in_bit = 0; dc_event_stat.code++; dc_event_stat.code &= 255; if(++dc_event_stat.index >= 512) { dc_event_stat.index = 0; dc_event_stat.code = 0; } } } else { if(dc_event_stat.samples == dc_event_stat.triggers[dc_event_stat.index]) { /* edfwrite_annotation_latin1(hdl, dc_event_stat.samples * 10LL, -1LL, "Trigger"); */ dc_event_stat.bitposition = 1; dc_event_stat.smp_in_bit = 1; buf[i] = 1.0; } else { buf[i] = 0.0; } } dc_event_stat.samples++; } if(edfwrite_physical_samples(hdl, buf)) { printf("error: edfwrite_physical_samples()\n"); return(1); } } edfwrite_annotation_latin1_hr(hdl, 0LL, -1LL, "Recording starts"); edfwrite_annotation_latin1_hr(hdl, 298000000LL, -1LL, "Test 1"); edfwrite_annotation_latin1_hr(hdl, 294000000LL + (long long)((1000000.0 / SMP_FREQ) * (SMP_FREQ - 2)), -1LL, "pulse 1"); edfwrite_annotation_latin1_hr(hdl, 295000000LL + (long long)((1000000.0 / SMP_FREQ_2) * (SMP_FREQ_2 - 2)), -1LL, "pulse 2"); edfwrite_annotation_latin1_hr(hdl, 296000000LL + (long long)((1000000.0 / SMP_FREQ_3) * (SMP_FREQ_3 - 2)), -1LL, "pulse 3"); edfwrite_annotation_latin1_hr(hdl, FILE_DURATION * 1000000LL, -1LL, "Recording ends"); edfclose_file(hdl); return(0); } edflib_124/lib/000755 001750 000144 00000000000 14413061402 013432 5ustar00guvusers000000 000000 edflib_124/lib/makefile000644 001750 000144 00000002271 14413061402 015134 0ustar00guvusers000000 000000 # # # Author: Teunis van Beelen # # email: teuniz@protonmail.com # # # GNU/Linux only for now. # # https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html # # nm -D libedf.so.1.2.4 # # objdump -T libedf.so.1.2.4 # CC := gcc CFLAGS := -O2 -fpic -fvisibility=hidden -std=gnu11 -Wall -Wextra -Wshadow -Wformat-nonliteral -Wformat-security \ -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -DEDFLIB_SO_DLL -DEDFLIB_BUILD LDLIBS := -lc TARGET := libedf.so.1.2.4 LBITS := $(shell getconf LONG_BIT) ifeq ($(LBITS),64) LIBDIR := /lib64 else LIBDIR := /lib endif ifeq ($(PREFIX),) PREFIX := /usr/local endif .PHONY: install clean objects = edflib.o all: $(TARGET) $(TARGET) : $(objects) $(CC) -shared -Wl,-soname,libedf.so.1 -o $(TARGET) edflib.o $(LDLIBS) edflib.o : ../edflib.h ../edflib.c $(CC) $(CFLAGS) -c ../edflib.c -o edflib.o install : all ifneq ($(shell id -u), 0) $(error You must be root to perform this action.) endif install -d $(DESTDIR)$(PREFIX)$(LIBDIR)/ install -m 755 $(TARGET) $(DESTDIR)$(PREFIX)$(LIBDIR)/ install -d $(DESTDIR)$(PREFIX)/include/ install -m 644 ../edflib.h $(DESTDIR)$(PREFIX)/include/ ldconfig clean : $(RM) $(TARGET) $(objects) edflib_124/lib/README000644 001750 000144 00000000614 14413061402 014313 0ustar00guvusers000000 000000 This makefile creates a shared libary of EDFlib. usage: make sudo make install the default install path is /usr/local/lib64 or /usr/local/lib in case of a 32bit architecture the header file will go into /usr/local/include sudo make install PREFIX=/usr will change the install path to /usr/lib64 or /usr/lib the header file will go into /usr/include System requirements: GNU/Linux edflib_124/Makefile000644 001750 000144 00000000441 14042105672 014331 0ustar00guvusers000000 000000 CC = gcc CFLAGS = -O2 -Wall -Wextra -Wshadow -Wformat-nonliteral -Wformat-security -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE LDLIBS = -lm programs = sine_generator sweep_generator test_edflib test_generator all: $(programs) $(programs): edflib.o clean: $(RM) *.o $(programs) *.[be]df edflib_124/unittest/000755 001750 000144 00000000000 14416304726 014557 5ustar00guvusers000000 000000 edflib_124/unittest/Makefile000644 001750 000144 00000001036 13702326546 016220 0ustar00guvusers000000 000000 # # # Author: Teunis van Beelen # # email: teuniz@gmail.com # # CC = gcc CFLAGS = -Wall -Wextra -Wshadow -Wformat-nonliteral -Wformat-security -Wtype-limits -Wfatal-errors -g -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE all: edflib_test edflib_test : edflib.o unittest.o $(CC) unittest.o edflib.o -o edflib_test unittest.o : unittest.c ../edflib.h ../edflib.c $(CC) $(CFLAGS) -c unittest.c -o unittest.o edflib.o : ../edflib.h ../edflib.c $(CC) $(CFLAGS) -c ../edflib.c -o edflib.o clean : $(RM) *.o edflib_test *.[be]df # # # # edflib_124/unittest/unittest.c000644 001750 000144 00000231522 14416304726 016607 0ustar00guvusers000000 000000 /* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2017- 2023 Teunis van Beelen * * Email: teuniz@protonmail.com * *************************************************************************** * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * *************************************************************************** */ #include #include #include #include #include "../edflib.h" #define JUMP_TO_EXIT_ERROR_PROC {line = __LINE__; goto OUT_ERROR;} #define EDFLIB_ANNOTATION_BYTES (120) #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif int dblcmp(double, double); int dblcmp_lim(double, double, double); int main(void) { int i, j, tmp, hdl=-1, chns=2, *ibuf=NULL, line, ival1, ival2; char *str=NULL, *pbuf=NULL; short *sbuf=NULL; long long l_tmp; double *dbuf=NULL; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; edflib_hdr_t hdr; edflib_annotation_t annot; FILE *fp=NULL; setlocale(LC_ALL, "C"); if(edflib_version() != 124) JUMP_TO_EXIT_ERROR_PROC ibuf = (int *)malloc(100 * sizeof(int)); if(ibuf == NULL) { JUMP_TO_EXIT_ERROR_PROC; } sbuf = (short *)malloc(100 * sizeof(short)); if(sbuf == NULL) { JUMP_TO_EXIT_ERROR_PROC; } dbuf = (double *)malloc(10240 * sizeof(double)); if(dbuf == NULL) { JUMP_TO_EXIT_ERROR_PROC; } str = (char *)malloc(4096 * sizeof(char)); if(str == NULL) { JUMP_TO_EXIT_ERROR_PROC; } str[0] = 0; pbuf = (char *)malloc(300 * sizeof(char)); if(pbuf == NULL) { JUMP_TO_EXIT_ERROR_PROC; } /********************************** EDF writing ******************************/ hdl = edfopen_file_writeonly_with_params("test.edf", EDFLIB_FILETYPE_EDFPLUS, 65, 633, 3000, "uV"); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<633; i++) { dbuf[i] = i; } for(i=0; i<10; i++) { for(j=0; j<65; j++) { if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC } } if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } /********************************** EDF reading ******************************/ if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS)) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(hdr.filetype != 1) JUMP_TO_EXIT_ERROR_PROC if(hdr.edfsignals != 65) JUMP_TO_EXIT_ERROR_PROC if(hdr.file_duration != 100000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.datarecord_duration != 10000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.datarecords_in_file != 10) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].smp_in_file != 6330) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].phys_max != 3000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].phys_min != -3000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].dig_max != 32767) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].dig_min != -32768) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].smp_in_datarecord != 633) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[0].physdimension, "uV ")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.patientcode, "")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.patient_name, "X")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.admincode, "")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.technician, "")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.equipment, "")) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /********************************** EDF writing ******************************/ hdl = edfopen_file_writeonly_with_params("test.edf", EDFLIB_FILETYPE_EDFPLUS, 65, 633, 3000, "uV"); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patientname(hdl, "XY_Z")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patientcode(hdl, "X2_3")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_admincode(hdl, "X6_7")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_technician(hdl, "X.Fo_o")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_equipment(hdl, "Xe_q")) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<633; i++) { dbuf[i] = i; } for(i=0; i<10; i++) { for(j=0; j<65; j++) { if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC } } if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } /********************************** EDF reading ******************************/ if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS)) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(hdr.filetype != 1) JUMP_TO_EXIT_ERROR_PROC if(hdr.edfsignals != 65) JUMP_TO_EXIT_ERROR_PROC if(hdr.file_duration != 100000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.datarecord_duration != 10000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.datarecords_in_file != 10) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].smp_in_file != 6330) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].phys_max != 3000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].phys_min != -3000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].dig_max != 32767) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].dig_min != -32768) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].smp_in_datarecord != 633) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[0].physdimension, "uV ")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.patientcode, "X2 3")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.patient_name, "XY Z")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.admincode, "X6 7")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.technician, "X.Fo o")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.equipment, "Xe q")) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /********************************** EDF writing ******************************/ hdl = edfopen_file_writeonly("test.edf", EDFLIB_FILETYPE_EDFPLUS, 512); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<512; i++) { if(edf_set_samplefrequency(hdl, i, 10239)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, i, -10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, i, -30000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, i, 10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, i, -10000)) JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<10239; i++) { dbuf[i] = 0; } if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = edfopen_file_writeonly("test.edf", EDFLIB_FILETYPE_EDFPLUS, 512); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<512; i++) { if(edf_set_samplefrequency(hdl, i, 10240)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, i, -10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, i, -30000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, i, 10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, i, -10000)) JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<10240; i++) { dbuf[i] = 0; } if(edfwrite_physical_samples(hdl, dbuf) != EDFLIB_DATARECORD_SIZE_TOO_BIG) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl) == 0) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = edfopen_file_writeonly("test.edf", EDFLIB_FILETYPE_EDFPLUS, chns); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC if(edf_set_samplefrequency(hdl, 0, 20)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_samplefrequency(hdl, 1, 23)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, 0, 10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, 0, -5000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, 1, -10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, 1, -30000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, 0, 10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, 0, -10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, 1, 30000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, 1, 10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_label(hdl, 0, "trace1")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_label(hdl, 1, "trace2")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_prefilter(hdl, 0, "qwerty")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_prefilter(hdl, 1, "zxcvbn")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_transducer(hdl, 0, "asdfgh")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_transducer(hdl, 1, "poklhyg")) JUMP_TO_EXIT_ERROR_PROC strcpy(str, "uVxxxxxxxxxxxxxxxxxxxx"); str[0] = 181; if(edf_set_physical_dimension(hdl, 0, str)) JUMP_TO_EXIT_ERROR_PROC strcpy(str, "dCxxxxxxxxxxxxxxxxxxxx"); str[0] = 176; str[2] = 248; if(edf_set_physical_dimension(hdl, 1, str)) JUMP_TO_EXIT_ERROR_PROC if(!edf_set_startdatetime(hdl, 2085, 12, 5, 12, 23, 8)) JUMP_TO_EXIT_ERROR_PROC if(!edf_set_startdatetime(hdl, 1984, 12, 5, 12, 23, 8)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_startdatetime(hdl, 2017, 12, 5, 12, 23, 8)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patientname(hdl, "John Doü")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patientcode(hdl, "01234")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_sex(hdl, 1)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_birthdate(hdl, 2010, 7, 4)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patient_additional(hdl, "nop")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_admincode(hdl, "789")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_technician(hdl, "Rìchard Roë")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_equipment(hdl, "device")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_number_of_annotation_signals(hdl, 3)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_datarecord_duration(hdl, 13000)) JUMP_TO_EXIT_ERROR_PROC if(edfwrite_annotation_latin1_hr(hdl, 0, -1, "Recording starts")) JUMP_TO_EXIT_ERROR_PROC if(edfwrite_annotation_latin1_hr(hdl, 900000, 100000, "Test 1")) JUMP_TO_EXIT_ERROR_PROC if(edfwrite_annotation_utf8_hr(hdl, 9123456, 1123456, "Test 2")) JUMP_TO_EXIT_ERROR_PROC if(edfwrite_annotation_latin1_hr(hdl, 1300000, -1, "Recording ends")) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { dbuf[i] = -5100 + (i * 800); } if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { dbuf[i] = -30100 + (i * 909); } if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { dbuf[i] = -5100 + (i * 800); } for(i=0; i<23; i++) { dbuf[i + 20] = -30100 + (i * 909); } if(edf_blockwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { sbuf[i] = -10100 + (i * 1053); } if(edfwrite_digital_short_samples(hdl, sbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { sbuf[i] = 9900 + (i * 1053); } if(edfwrite_digital_short_samples(hdl, sbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { sbuf[i] = -10100 + (i * 1053); } for(i=0; i<23; i++) { sbuf[i + 20] = 9900 + (i * 1053); } if(edf_blockwrite_digital_short_samples(hdl, sbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { ibuf[i] = -10100 + (i * 1053); } if(edfwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { ibuf[i] = 9900 + (i * 1053); } if(edfwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { ibuf[i] = -10100 + (i * 1053); } for(i=0; i<23; i++) { ibuf[i + 20] = 9900 + (i * 1053); } if(edf_blockwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC ival1 = -10100; ival2 = 9900; for(j=0; j<4; j++) { for(i=0; i<20; i++) { ibuf[i] = ival1; ival1 += 253; } if(edfwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { ibuf[i] = ival2; ival2 += 253; } if(edfwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC } if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } /********************************** BDF writing ******************************/ hdl = edfopen_file_writeonly("test.bdf", EDFLIB_FILETYPE_BDFPLUS, 512); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<512; i++) { if(edf_set_samplefrequency(hdl, i, 10239)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, i, -10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, i, -30000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, i, 10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, i, -10000)) JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<10239; i++) { dbuf[i] = 0; } if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = edfopen_file_writeonly("test.bdf", EDFLIB_FILETYPE_BDFPLUS, 512); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<512; i++) { if(edf_set_samplefrequency(hdl, i, 10240)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, i, -10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, i, -30000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, i, 10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, i, -10000)) JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<10240; i++) { dbuf[i] = 0; } if(edfwrite_physical_samples(hdl, dbuf) != EDFLIB_DATARECORD_SIZE_TOO_BIG) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl) == 0) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = edfopen_file_writeonly("test.bdf", EDFLIB_FILETYPE_BDFPLUS, chns); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC if(edf_set_samplefrequency(hdl, 0, 20)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_samplefrequency(hdl, 1, 23)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, 0, 10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, 0, -5000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, 1, -10000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, 1, -30000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, 0, 1000000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, 0, -1000000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, 1, 3000000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, 1, 1000000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_label(hdl, 0, "trace1")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_label(hdl, 1, "trace2")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_prefilter(hdl, 0, "qwerty")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_prefilter(hdl, 1, "zxcvbn")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_transducer(hdl, 0, "asdfgh")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_transducer(hdl, 1, "poklhyg")) JUMP_TO_EXIT_ERROR_PROC strcpy(str, "uVxxxxxxxxxxxxxxxxxxxx"); str[0] = 181; if(edf_set_physical_dimension(hdl, 0, str)) JUMP_TO_EXIT_ERROR_PROC strcpy(str, "dCxxxxxxxxxxxxxxxxxxxx"); str[0] = 176; str[2] = 248; if(edf_set_physical_dimension(hdl, 1, str)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_startdatetime(hdl, 2017, 12, 5, 12, 23, 8)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patientname(hdl, "John Doe")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patientcode(hdl, "01234")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_sex(hdl, 0)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_birthdate(hdl, 2010, 7, 4)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patient_additional(hdl, "nop")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_admincode(hdl, "789")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_technician(hdl, "Richard Roe")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_equipment(hdl, "device")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_number_of_annotation_signals(hdl, 3)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_datarecord_duration(hdl, 13000)) JUMP_TO_EXIT_ERROR_PROC if(edfwrite_annotation_latin1(hdl, 0, -1, "Recording starts")) JUMP_TO_EXIT_ERROR_PROC if(edfwrite_annotation_latin1(hdl, 6000, 2000, "Test 2")) JUMP_TO_EXIT_ERROR_PROC if(edfwrite_annotation_latin1(hdl, 11700, -1, "Recording ends")) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { dbuf[i] = -5100 + (i * 800); } if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { dbuf[i] = -30100 + (i * 909); } if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { dbuf[i] = -5100 + (i * 800); } for(i=0; i<23; i++) { dbuf[i + 20] = -30100 + (i * 909); } if(edf_blockwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { tmp = -1010000 + (i * 105300); pbuf[i * 3] = tmp & 0xff; pbuf[i * 3 + 1] = (tmp >> 8) & 0xff; pbuf[i * 3 + 2] = (tmp >> 16) & 0xff; } for(i=0; i<23; i++) { tmp = 990000 + (i * 105300); pbuf[i * 3 + 60] = tmp & 0xff; pbuf[i * 3 + 61] = (tmp >> 8) & 0xff; pbuf[i * 3 + 62] = (tmp >> 16) & 0xff; } if(edf_blockwrite_digital_3byte_samples(hdl, pbuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { ibuf[i] = -1010000 + (i * 105300); } if(edfwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { ibuf[i] = 990000 + (i * 105300); } if(edfwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { ibuf[i] = -1010000 + (i * 105300); } for(i=0; i<23; i++) { ibuf[i + 20] = 990000 + (i * 105300); } if(edf_blockwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC ival1 = -1010000; ival2 = 990000; for(j=0; j<4; j++) { for(i=0; i<20; i++) { ibuf[i] = ival1; ival1 += 25300; } if(edfwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { ibuf[i] = ival2; ival2 += 25300; } if(edfwrite_digital_samples(hdl, ibuf)) JUMP_TO_EXIT_ERROR_PROC } if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /********************************** EDF reading ******************************/ if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS)) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(hdr.filetype != 1) JUMP_TO_EXIT_ERROR_PROC if(hdr.edfsignals != 2) JUMP_TO_EXIT_ERROR_PROC if(hdr.file_duration != 13000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.startdate_day != 5) JUMP_TO_EXIT_ERROR_PROC if(hdr.startdate_month != 12) JUMP_TO_EXIT_ERROR_PROC if(hdr.startdate_year != 2017) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_second != 8) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_minute != 23) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_hour != 12) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_subsecond != 0) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.patient_name, "John Dou")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.patientcode, "01234")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.sex, "Male")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.gender, "Male")) JUMP_TO_EXIT_ERROR_PROC /* DEPRECATED */ if(strcmp(hdr.birthdate, "04 jul 2010")) JUMP_TO_EXIT_ERROR_PROC if(hdr.birthdate_day != 4) JUMP_TO_EXIT_ERROR_PROC if(hdr.birthdate_month != 7) JUMP_TO_EXIT_ERROR_PROC if(hdr.birthdate_year != 2010) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.patient_additional, "nop", 3)) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.admincode, "789")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.technician, "Richard Roe")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.equipment, "device")) JUMP_TO_EXIT_ERROR_PROC if(hdr.datarecord_duration != 1300000) JUMP_TO_EXIT_ERROR_PROC if(hdr.datarecords_in_file != 10) JUMP_TO_EXIT_ERROR_PROC if(hdr.annotations_in_file != 4) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[0].label, "trace1 ")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[1].label, "trace2 ")) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].smp_in_file != 200) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].smp_in_file != 230) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].phys_max != 10000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].phys_max != -10000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].phys_min != -5000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].phys_min != -30000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].dig_max != 10000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].dig_max != 30000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].dig_min != -10000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].dig_min != 10000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].smp_in_datarecord != 20) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].smp_in_datarecord != 23) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[0].physdimension, "uVxxxxxx")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[1].physdimension, ".C0xxxxx")) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.signalparam[0].prefilter, "qwerty ", 9)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.signalparam[1].prefilter, "zxcvbn ", 9)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.signalparam[0].transducer, "asdfgh ", 9)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.signalparam[1].transducer, "poklhyg ", 9)) JUMP_TO_EXIT_ERROR_PROC if(edf_get_annotation(hdl, 0, &annot)) JUMP_TO_EXIT_ERROR_PROC if(annot.onset != 0) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.duration, "")) JUMP_TO_EXIT_ERROR_PROC if(annot.duration_l != -10000000LL) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.annotation, "Recording starts")) JUMP_TO_EXIT_ERROR_PROC if(edf_get_annotation(hdl, 1, &annot)) JUMP_TO_EXIT_ERROR_PROC if(annot.onset != 9000000) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.duration, "0.100000")) JUMP_TO_EXIT_ERROR_PROC if(annot.duration_l != 1000000LL) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.annotation, "Test 1")) JUMP_TO_EXIT_ERROR_PROC if(edf_get_annotation(hdl, 2, &annot)) JUMP_TO_EXIT_ERROR_PROC if(annot.onset != 91234560) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.duration, "1.123456")) JUMP_TO_EXIT_ERROR_PROC if(annot.duration_l != 11234560LL) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.annotation, "Test 2")) JUMP_TO_EXIT_ERROR_PROC if(edf_get_annotation(hdl, 3, &annot)) JUMP_TO_EXIT_ERROR_PROC if(annot.onset != 13000000) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.duration, "")) JUMP_TO_EXIT_ERROR_PROC if(annot.duration_l != -10000000LL) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.annotation, "Recording ends")) JUMP_TO_EXIT_ERROR_PROC if(edfseek(hdl, 1, 400, EDFSEEK_SET) == 400) JUMP_TO_EXIT_ERROR_PROC if(edfseek(hdl, 0, 412, EDFSEEK_SET) == 412) JUMP_TO_EXIT_ERROR_PROC if(edfseek(hdl, 0, 20, EDFSEEK_SET) != 20) JUMP_TO_EXIT_ERROR_PROC if(edfread_physical_samples(hdl, 0, 20, dbuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%f %i\n", dbuf[i], -5100 + (i * 800)); if(i == 0) { if(dblcmp(dbuf[i], -5000)) JUMP_TO_EXIT_ERROR_PROC continue; } if(i == 19) { if(dblcmp(dbuf[i], 10000)) JUMP_TO_EXIT_ERROR_PROC continue; } if(dblcmp_lim(dbuf[i], -5100 + (i * 800), 0.75)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 1, 23, EDFSEEK_SET) != 23) JUMP_TO_EXIT_ERROR_PROC if(edfread_physical_samples(hdl, 1, 23, dbuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%f %i\n", dbuf[i], -30100 + (i * 909)); if(i == 0) { if(dblcmp(dbuf[i], -30000)) JUMP_TO_EXIT_ERROR_PROC continue; } if(dblcmp(dbuf[i], -30100 + (i * 909))) JUMP_TO_EXIT_ERROR_PROC } edfrewind(hdl, 0); if(edfread_physical_samples(hdl, 0, 20, dbuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%f %i\n", dbuf[i], -5100 + (i * 800)); if(i == 0) { if(dblcmp(dbuf[i], -5000)) JUMP_TO_EXIT_ERROR_PROC continue; } if(i == 19) { if(dblcmp(dbuf[i], 10000)) JUMP_TO_EXIT_ERROR_PROC continue; } if(dblcmp_lim(dbuf[i], -5100 + (i * 800), 0.75)) JUMP_TO_EXIT_ERROR_PROC } edfrewind(hdl, 1); if(edfread_physical_samples(hdl, 1, 23, dbuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%f %i\n", dbuf[i], -30100 + (i * 909)); if(i == 0) { if(dblcmp(dbuf[i], -30000)) JUMP_TO_EXIT_ERROR_PROC continue; } if(dblcmp(dbuf[i], -30100 + (i * 909))) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 0, 40, EDFSEEK_SET) != 40) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 0, 20, ibuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i %i\n", ibuf[i], -10100 + (i * 1053)); if(i == 0) { if(ibuf[i] != -10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != -10100 + (i * 1053)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 1, 46, EDFSEEK_SET) != 46) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 1, 23, ibuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %i %i\n", i, ibuf[i], 9900 + (i * 1053)); if(i == 0) { if(ibuf[i] != 10000) JUMP_TO_EXIT_ERROR_PROC continue; } if((i == 20) || (i == 21)) { if(ibuf[i] != 30000) JUMP_TO_EXIT_ERROR_PROC continue; } if(i == 22) { if(ibuf[i] != 10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != 9900 + (i * 1053)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 0, 80, EDFSEEK_SET) != 80) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 0, 20, ibuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i %i\n", ibuf[i], -10100 + (i * 1053)); if(i == 0) { if(ibuf[i] != -10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != -10100 + (i * 1053)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 1, 92, EDFSEEK_SET) != 92) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 1, 23, ibuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %i %i\n", i, ibuf[i], 9900 + (i * 1053)); if(i == 0) { if(ibuf[i] != 10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(i >= 20) { if(ibuf[i] != 30000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != 9900 + (i * 1053)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 0, 60, EDFSEEK_SET) != 60) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 0, 20, ibuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i %i\n", ibuf[i], -10100 + (i * 1053)); if(i == 0) { if(ibuf[i] != -10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != -10100 + (i * 1053)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 1, 69, EDFSEEK_SET) != 69) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 1, 23, ibuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %i %i\n", i, ibuf[i], 9900 + (i * 1053)); if(i == 0) { if(ibuf[i] != 10000) JUMP_TO_EXIT_ERROR_PROC continue; } if((i == 20) || (i == 21)) { if(ibuf[i] != 30000) JUMP_TO_EXIT_ERROR_PROC continue; } if(i == 22) { if(ibuf[i] != 10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != 9900 + (i * 1053)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 0, 100, EDFSEEK_SET) != 100) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 0, 20, ibuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i %i\n", ibuf[i], -10100 + (i * 1053)); if(i == 0) { if(ibuf[i] != -10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != -10100 + (i * 1053)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 1, 115, EDFSEEK_SET) != 115) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 1, 23, ibuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %i %i\n", i, ibuf[i], 9900 + (i * 1053)); if(i == 0) { if(ibuf[i] != 10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(i >= 20) { if(ibuf[i] != 30000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != 9900 + (i * 1053)) JUMP_TO_EXIT_ERROR_PROC } if(edfread_digital_samples(hdl, 0, 80, ibuf) != 80) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<80; i++) { // printf("%i: %i %i\n", i, ibuf[i], -10100 + (i * 253)); if(i == 0) { if(ibuf[i] != -10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != -10100 + (i * 253)) JUMP_TO_EXIT_ERROR_PROC } if(edfread_digital_samples(hdl, 1, 92, ibuf) != 92) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<92; i++) { // printf("%i: %i %i\n", i, ibuf[i], 9900 + (i * 253)); if(i == 0) { if(ibuf[i] != 10000) JUMP_TO_EXIT_ERROR_PROC continue; } if(i >= 80) { if(ibuf[i] != 30000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != 9900 + (i * 253)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 0, 185, EDFSEEK_SET) != 185) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 0, 20, ibuf) != 15) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<15; i++) { // printf("%i %i\n", ibuf[i], -10100 + ((i + 65) * 253)); if(ibuf[i] != -10100 + ((i + 65) * 253)) JUMP_TO_EXIT_ERROR_PROC } if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 1, SEEK_SET); fputc('1', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 1, SEEK_SET); fputc(' ', fp); fseek(fp, 16, SEEK_SET); fputc(' ', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 16, SEEK_SET); fputc('0', fp); fseek(fp, 0xaa, SEEK_SET); fputc(':', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xaa, SEEK_SET); fputc('.', fp); fseek(fp, 0xab, SEEK_SET); fputc('9', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xab, SEEK_SET); fputc('1', fp); fseek(fp, 0xac, SEEK_SET); fputc('q', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xac, SEEK_SET); fputc('2', fp); fseek(fp, 0xc4, SEEK_SET); fputc('D', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_IS_DISCONTINUOUS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xc4, SEEK_SET); fputc('C', fp); fseek(fp, 0x12e, SEEK_SET); fputc(' ', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x12e, SEEK_SET); fputc('s', fp); fseek(fp, 0x1ac, SEEK_SET); fputc(181, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x1ac, SEEK_SET); fputc(' ', fp); fseek(fp, 0x308, SEEK_SET); fputc(' ', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x308, SEEK_SET); fputc('-', fp); fseek(fp, 0x30d, SEEK_SET); fputc(',', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x30d, SEEK_SET); fputc(' ', fp); fseek(fp, 0x3a5, SEEK_SET); fputc('.', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x3a5, SEEK_SET); fputc(' ', fp); fseek(fp, 0x3bc, SEEK_SET); fputc(207, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x3bc, SEEK_SET); fputc(' ', fp); fseek(fp, 0x40b, SEEK_SET); fputc(247, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x40b, SEEK_SET); fputc(' ', fp); fseek(fp, 0x560, SEEK_SET); fputc(127, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x560, SEEK_SET); fputc(' ', fp); fseek(fp, 0x5ff, SEEK_SET); fputc(13, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x5ff, SEEK_SET); fputc(' ', fp); fseek(fp, 0x54a, SEEK_SET); fputc('.', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x54a, SEEK_SET); fputc(' ', fp); fseek(fp, 0xad, SEEK_SET); fputc('-', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xad, SEEK_SET); fputc('.', fp); #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x803, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x815, SEEK_SET); #endif fwrite("0.12", 4, 1, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x803, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x815, SEEK_SET); #endif fwrite("0.131", 5, 1, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x803, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x815, SEEK_SET); #endif fwrite("0.130", 5, 1, fp); #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x802, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x814, SEEK_SET); #endif fputc('0', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x802, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x814, SEEK_SET); #endif fputc('-', fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x802, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x814, SEEK_SET); #endif fputc('+', fp); #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x750, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x75e, SEEK_SET); #endif fputc(0, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x750, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x75e, SEEK_SET); #endif fputc(0x14, fp); fputc(1, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x751, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x75f, SEEK_SET); #endif fputc(0, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS)) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x358, SEEK_SET); fwrite("-32769 ", 8, 1, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x358, SEEK_SET); fwrite("-10000 ", 8, 1, fp); fseek(fp, 0x380, SEEK_SET); fwrite("32768 ", 8, 1, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x380, SEEK_SET); fwrite("10000 ", 8, 1, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) != 0) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x600, SEEK_SET); if(fread(str, 40, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<20; i++) { // printf("buf[%i]: %i value: %f\n", i, ((signed short *)str)[i], ((-5100 + (i * 800)) / 0.75) - 3333.333333); if(i == 0) { if(((signed short *)str)[i] != -10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(i >= 19) { if(((signed short *)str)[i] != 10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(dblcmp_lim(((signed short *)str)[i], ((-5100 + (i * 800)) / 0.75) - 3333.333333, 1.0001)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x628, SEEK_SET); if(fread(str, 46, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<23; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], (-30100 + (i * 909)) + 40000); if(i == 0) { if(((signed short *)str)[i] != 10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != (-30100 + (i * 909)) + 40000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x7ac, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x7be, SEEK_SET); #endif if(fread(str, 40, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<20; i++) { // printf("buf[%i]: %i value: %f\n", i, ((signed short *)str)[i], ((-5100 + (i * 800)) / 0.75) - 3333.333333); if(i == 0) { if(((signed short *)str)[i] != -10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(i >= 19) { if(((signed short *)str)[i] != 10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(dblcmp_lim(((signed short *)str)[i], ((-5100 + (i * 800)) / 0.75) - 3333.333333, 1.0001)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x7d4, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x7e6, SEEK_SET); #endif if(fread(str, 46, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<23; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], (-30100 + (i * 909)) + 40000); if(i == 0) { if(((signed short *)str)[i] != 10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != (-30100 + (i * 909)) + 40000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x958, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x97c, SEEK_SET); #endif if(fread(str, 40, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<20; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], -10100 + (i * 1053)); if(i == 0) { if(((signed short *)str)[i] != -10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != -10100 + (i * 1053)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0x980, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0x9a4, SEEK_SET); #endif if(fread(str, 46, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<23; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], 9900 + (i * 1053)); if((i == 0) || (i == 22)) { if(((signed short *)str)[i] != 10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if((i == 20) || (i == 21)) { if(((signed short *)str)[i] != 30000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != 9900 + (i * 1053)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0xb04, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0xb3a, SEEK_SET); #endif if(fread(str, 40, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<20; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], -10100 + (i * 1053)); if(i == 0) { if(((signed short *)str)[i] != -10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != -10100 + (i * 1053)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0xb2c, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0xb62, SEEK_SET); #endif if(fread(str, 46, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<23; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], 9900 + (i * 1053)); if((i == 0) || (i == 22)) { if(((signed short *)str)[i] != 10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if((i == 20) || (i == 21)) { if(((signed short *)str)[i] != 30000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != 9900 + (i * 1053)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0xcb0, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0xcf8, SEEK_SET); #endif if(fread(str, 40, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<20; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], -10100 + (i * 1053)); if(i == 0) { if(((signed short *)str)[i] != -10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != -10100 + (i * 1053)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0xcd8, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0xd20, SEEK_SET); #endif if(fread(str, 46, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<23; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], 9900 + (i * 1053)); if(i == 0) { if(((signed short *)str)[i] != 10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(i >= 20) { if(((signed short *)str)[i] != 30000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != 9900 + (i * 1053)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0xe5c, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0xeb6, SEEK_SET); #endif if(fread(str, 40, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<20; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], -10100 + (i * 1053)); if(i == 0) { if(((signed short *)str)[i] != -10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != -10100 + (i * 1053)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC #if (EDFLIB_ANNOTATION_BYTES == 114) fseek(fp, 0xe84, SEEK_SET); #endif #if (EDFLIB_ANNOTATION_BYTES == 120) fseek(fp, 0xede, SEEK_SET); #endif if(fread(str, 46, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<23; i++) { // printf("buf[%i]: %i value: %i\n", i, ((signed short *)str)[i], 9900 + (i * 1053)); if(i == 0) { if(((signed short *)str)[i] != 10000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(i >= 20) { if(((signed short *)str)[i] != 30000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(((signed short *)str)[i] != 9900 + (i * 1053)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /********************************** BDF reading ******************************/ if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS)) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(hdr.filetype != 3) JUMP_TO_EXIT_ERROR_PROC if(hdr.edfsignals != 2) JUMP_TO_EXIT_ERROR_PROC if(hdr.file_duration != 11700000) JUMP_TO_EXIT_ERROR_PROC if(hdr.startdate_day != 5) JUMP_TO_EXIT_ERROR_PROC if(hdr.startdate_month != 12) JUMP_TO_EXIT_ERROR_PROC if(hdr.startdate_year != 2017) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_second != 8) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_minute != 23) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_hour != 12) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_subsecond != 0) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.patient_name, "John Doe")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.patientcode, "01234")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.sex, "Female")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.birthdate, "04 jul 2010")) JUMP_TO_EXIT_ERROR_PROC if(hdr.birthdate_day != 4) JUMP_TO_EXIT_ERROR_PROC if(hdr.birthdate_month != 7) JUMP_TO_EXIT_ERROR_PROC if(hdr.birthdate_year != 2010) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.patient_additional, "nop", 3)) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.admincode, "789")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.technician, "Richard Roe")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.equipment, "device")) JUMP_TO_EXIT_ERROR_PROC if(hdr.datarecord_duration != 1300000) JUMP_TO_EXIT_ERROR_PROC if(hdr.datarecords_in_file != 9) JUMP_TO_EXIT_ERROR_PROC if(hdr.annotations_in_file != 3) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[0].label, "trace1 ")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[1].label, "trace2 ")) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].smp_in_file != 180) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].smp_in_file != 207) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].phys_max != 10000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].phys_max != -10000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].phys_min != -5000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].phys_min != -30000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].dig_max != 1000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].dig_max != 3000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].dig_min != -1000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].dig_min != 1000000) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[0].smp_in_datarecord != 20) JUMP_TO_EXIT_ERROR_PROC if(hdr.signalparam[1].smp_in_datarecord != 23) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[0].physdimension, "uVxxxxxx")) JUMP_TO_EXIT_ERROR_PROC if(strcmp(hdr.signalparam[1].physdimension, ".C0xxxxx")) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.signalparam[0].prefilter, "qwerty ", 9)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.signalparam[1].prefilter, "zxcvbn ", 9)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.signalparam[0].transducer, "asdfgh ", 9)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.signalparam[1].transducer, "poklhyg ", 9)) JUMP_TO_EXIT_ERROR_PROC if(edf_get_annotation(hdl, 0, &annot)) JUMP_TO_EXIT_ERROR_PROC if(annot.onset != 0) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.duration, "")) JUMP_TO_EXIT_ERROR_PROC if(annot.duration_l != -10000000LL) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.annotation, "Recording starts")) JUMP_TO_EXIT_ERROR_PROC if(edf_get_annotation(hdl, 1, &annot)) JUMP_TO_EXIT_ERROR_PROC if(annot.onset != 6000000) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.duration, "0.200000")) JUMP_TO_EXIT_ERROR_PROC if(annot.duration_l != 2000000LL) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.annotation, "Test 2")) JUMP_TO_EXIT_ERROR_PROC if(edf_get_annotation(hdl, 2, &annot)) JUMP_TO_EXIT_ERROR_PROC if(annot.onset != 11700000) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.duration, "")) JUMP_TO_EXIT_ERROR_PROC if(annot.duration_l != -10000000LL) JUMP_TO_EXIT_ERROR_PROC if(strcmp(annot.annotation, "Recording ends")) JUMP_TO_EXIT_ERROR_PROC if(edfseek(hdl, 1, 500, EDFSEEK_SET) == 500) JUMP_TO_EXIT_ERROR_PROC if(edfseek(hdl, 0, 333, EDFSEEK_SET) == 333) JUMP_TO_EXIT_ERROR_PROC if(edfseek(hdl, 0, 20, EDFSEEK_SET) != 20) JUMP_TO_EXIT_ERROR_PROC if(edfread_physical_samples(hdl, 0, 20, dbuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i: %f %i\n", i, dbuf[i], -5100 + (i * 800)); if(i == 0) { if(dblcmp_lim(dbuf[i], -5000, 0.00001)) JUMP_TO_EXIT_ERROR_PROC continue; } if(i == 19) { if(dblcmp_lim(dbuf[i], 10000, 0.00001)) JUMP_TO_EXIT_ERROR_PROC continue; } if(dblcmp_lim(dbuf[i], -5100 + (i * 800), 0.0075)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 1, 23, EDFSEEK_SET) != 23) JUMP_TO_EXIT_ERROR_PROC if(edfread_physical_samples(hdl, 1, 23, dbuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %f %i\n", i, dbuf[i], -30100 + (i * 909)); if(i == 0) { if(dblcmp_lim(dbuf[i], -30000, 0.00001)) JUMP_TO_EXIT_ERROR_PROC continue; } if(dblcmp(dbuf[i], -30100 + (i * 909))) JUMP_TO_EXIT_ERROR_PROC } edfrewind(hdl, 0); if(edfread_physical_samples(hdl, 0, 20, dbuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i: %f %i\n", i, dbuf[i], -5100 + (i * 800)); if(i == 0) { if(dblcmp_lim(dbuf[i], -5000, 0.00001)) JUMP_TO_EXIT_ERROR_PROC continue; } if(i == 19) { if(dblcmp_lim(dbuf[i], 10000, 0.00001)) JUMP_TO_EXIT_ERROR_PROC continue; } if(dblcmp_lim(dbuf[i], -5100 + (i * 800), 0.0075)) JUMP_TO_EXIT_ERROR_PROC } edfrewind(hdl, 1); if(edfread_physical_samples(hdl, 1, 23, dbuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %f %i\n", i, dbuf[i], -30100 + (i * 909)); if(i == 0) { if(dblcmp_lim(dbuf[i], -30000, 0.00001)) JUMP_TO_EXIT_ERROR_PROC continue; } if(dblcmp(dbuf[i], -30100 + (i * 909))) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 0, 40, EDFSEEK_SET) != 40) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 0, 20, ibuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i: %i %i\n", i, ibuf[i], -1010000 + (i * 105300)); if(i == 0) { if(ibuf[i] != -1000000) JUMP_TO_EXIT_ERROR_PROC } else { if(ibuf[i] != -1010000 + (i * 105300)) JUMP_TO_EXIT_ERROR_PROC } } if(edfseek(hdl, 1, 46, EDFSEEK_SET) != 46) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 1, 23, ibuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %i %i\n", i, ibuf[i], 990000 + (i * 105300)); if(i == 0) { if(ibuf[i] != 1000000) JUMP_TO_EXIT_ERROR_PROC } else if(i >= 20) { if(ibuf[i] != 3000000) JUMP_TO_EXIT_ERROR_PROC } else { if(ibuf[i] != 990000 + (i * 105300)) JUMP_TO_EXIT_ERROR_PROC } } if(edfseek(hdl, 0, 60, EDFSEEK_SET) != 60) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 0, 20, ibuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i: %i %i\n", i, ibuf[i], -1010000 + (i * 105300)); if(i == 0) { if(ibuf[i] != -1000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != -1010000 + (i * 105300)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 1, 69, EDFSEEK_SET) != 69) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 1, 23, ibuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %i %i\n", i, ibuf[i], 990000 + (i * 105300)); if(i == 0) { if(ibuf[i] != 1000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(i >= 20) { if(ibuf[i] != 3000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != 990000 + (i * 105300)) JUMP_TO_EXIT_ERROR_PROC } if(edfread_digital_samples(hdl, 0, 20, ibuf) != 20) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<20; i++) { // printf("%i: %i %i\n", i, ibuf[i], -1010000 + (i * 105300)); if(i == 0) { if(ibuf[i] != -1000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != -1010000 + (i * 105300)) JUMP_TO_EXIT_ERROR_PROC } if(edfread_digital_samples(hdl, 1, 23, ibuf) != 23) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<23; i++) { // printf("%i: %i %i\n", i, ibuf[i], 990000 + (i * 105300)); if(i == 0) { if(ibuf[i] != 1000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(i >= 20) { if(ibuf[i] != 3000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != 990000 + (i * 105300)) JUMP_TO_EXIT_ERROR_PROC } if(edfread_digital_samples(hdl, 0, 80, ibuf) != 80) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<80; i++) { // printf("%i: %i %i\n", i, ibuf[i], -1010000 + (i * 25300)); if(i == 0) { if(ibuf[i] != -1000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != -1010000 + (i * 25300)) JUMP_TO_EXIT_ERROR_PROC } if(edfread_digital_samples(hdl, 1, 92, ibuf) != 92) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<92; i++) { // printf("%i: %i %i\n", i, ibuf[i], 990000 + (i * 25300)); if(i == 0) { if(ibuf[i] != 1000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(i >= 80) { if(ibuf[i] != 3000000) JUMP_TO_EXIT_ERROR_PROC continue; } if(ibuf[i] != 990000 + (i * 25300)) JUMP_TO_EXIT_ERROR_PROC } if(edfseek(hdl, 0, 165, EDFSEEK_SET) != 165) JUMP_TO_EXIT_ERROR_PROC if(edfread_digital_samples(hdl, 0, 20, ibuf) != 15) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<15; i++) { // printf("%i %i\n", ibuf[i], -10100 + ((i + 65) * 253)); if(ibuf[i] != -1010000 + ((i + 65) * 25300)) JUMP_TO_EXIT_ERROR_PROC } if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } /****************************************/ fp = fopen("test.bdf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x600, SEEK_SET); if(fread(str, 60, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<20; i++) { var.four[0] = str[i * 3]; var.four[1] = str[i * 3 + 1]; var.four[2] = str[i * 3 + 2]; if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } // printf("buf[%i]: %i value: %f\n", i, var.one_signed, ((-5100 + (i * 800)) / 0.0075) - 333333.333333); if(i == 0) { if(var.one_signed != -1000000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(i >= 19) { if(var.one_signed != 1000000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(dblcmp_lim(var.one_signed, ((-5100 + (i * 800)) / 0.0075) - 333333.333333, 1.0001)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.bdf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x63c, SEEK_SET); if(fread(str, 69, 1, fp) != 1) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } for(i=0; i<23; i++) { var.four[0] = str[i * 3]; var.four[1] = str[i * 3 + 1]; var.four[2] = str[i * 3 + 2]; if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } // printf("buf[%i]: %i value: %f\n", i, var.one_signed, ((-30100 + (i * 909)) / 0.01) + 4000000.0); if(i == 0) { if(var.one_signed != 1000000) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } continue; } if(dblcmp_lim(var.one_signed, ((-30100 + (i * 909)) / 0.01) + 4000000.0, 1.0001)) { fclose(fp); JUMP_TO_EXIT_ERROR_PROC } } fclose(fp); /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x37f, SEEK_SET); fputc('7', fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x37f, SEEK_SET); fputc('8', fp); fseek(fp, 0x39e, SEEK_SET); fputc('6', fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x39e, SEEK_SET); fputc('7', fp); fseek(fp, 0x318, SEEK_SET); fwrite("1 ", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x318, SEEK_SET); fwrite("-1", 2, 1, fp); fseek(fp, 0x358, SEEK_SET); fwrite("2000000 ", 8, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x358, SEEK_SET); fwrite("1000000 ", 8, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x358, SEEK_SET); fwrite("-1000000", 8, 1, fp); fseek(fp, 0xec, SEEK_SET); fwrite("+9", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) != 0) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdr.handle)) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xec, SEEK_SET); fwrite("-9", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xec, SEEK_SET); fwrite("-1", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xec, SEEK_SET); fwrite("0 ", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xec, SEEK_SET); fwrite(" 9", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xec, SEEK_SET); fwrite("9 ", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) != 0) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdr.handle)) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x358, SEEK_SET); fwrite("-8388609", 8, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x358, SEEK_SET); fwrite("-1000000", 8, 1, fp); fseek(fp, 0x380, SEEK_SET); fwrite("8388608 ", 8, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.bdf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0x380, SEEK_SET); fwrite("1000000 ", 8, 1, fp); fclose(fp); if(edfopen_file_readonly("test.bdf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) != 0) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xae, SEEK_SET); fwrite("15", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) == 0) JUMP_TO_EXIT_ERROR_PROC if(hdr.filetype != EDFLIB_FILE_CONTAINS_FORMAT_ERRORS) JUMP_TO_EXIT_ERROR_PROC /****************************************/ fp = fopen("test.edf", "r+b"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC fseek(fp, 0xae, SEEK_SET); fwrite("17 ", 2, 1, fp); fclose(fp); if(edfopen_file_readonly("test.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS) != 0) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /********************************** EDF writing ******************************/ hdl = edfopen_file_writeonly("test2.edf", EDFLIB_FILETYPE_EDFPLUS, 1); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC if(edf_set_samplefrequency(hdl, 0, 100)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, 0, 1000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, 0, -1000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, 0, 32767)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, 0, -32768)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patient_additional(hdl, "Test")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_recording_additional(hdl, "tEST")) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<100; i++) { dbuf[i] = 0; } if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /********************************** EDF reading ******************************/ if(edfopen_file_readonly("test2.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS)) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(hdr.filetype != 1) JUMP_TO_EXIT_ERROR_PROC if(hdr.edfsignals != 1) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.patient_additional, "Test", 4)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.recording_additional, "tEST", 4)) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /********************************** EDF writing ******************************/ hdl = edfopen_file_writeonly("test3.edf", EDFLIB_FILETYPE_EDFPLUS, 1); if(hdl < 0) JUMP_TO_EXIT_ERROR_PROC if(edf_set_datarecord_duration(hdl, 77777)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_subsecond_starttime(hdl, 1234000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_number_of_annotation_signals(hdl, 3)) JUMP_TO_EXIT_ERROR_PROC char str_korea[]={0xeb,0x8c,0x80,0xed,0x95,0x9c,0xeb,0xaf,0xbc,0xea,0xb5,0xad,0x00}; char str_accented[]={0xc3,0xb1,0xe1,0xb8,0xb1,0xc3,0xb6,0xc3,0xa8,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x00}; for(i=0; i<60; i++) { l_tmp = 10000LL * (i + 1); snprintf(str, 4096, "test %i sec", (int)(l_tmp / 10000LL)); if(i != 0) { if(edfwrite_annotation_latin1(hdl, l_tmp, -1LL, str)) JUMP_TO_EXIT_ERROR_PROC } else { if(edfwrite_annotation_utf8(hdl, l_tmp, -1LL, str_accented)) JUMP_TO_EXIT_ERROR_PROC } l_tmp += 3333LL; snprintf(str, 4096, "test %i.%04i sec", (int)(l_tmp / 10000LL), (int)(l_tmp % 10000LL)); if(i != 0) { if(edfwrite_annotation_latin1(hdl, l_tmp, -1LL, str)) JUMP_TO_EXIT_ERROR_PROC } else { if(edfwrite_annotation_utf8_hr(hdl, l_tmp * 100LL, -1LL, str_korea)) JUMP_TO_EXIT_ERROR_PROC } } if(edf_set_samplefrequency(hdl, 0, 100)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_maximum(hdl, 0, 1000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_physical_minimum(hdl, 0, -1000)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_maximum(hdl, 0, 32767)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_digital_minimum(hdl, 0, -32768)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_startdatetime(hdl, 2008, 12, 31, 23, 59, 58)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patientname(hdl, "Ãlpha")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patientcode(hdl, "Bràvó")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_gender(hdl, 1)) JUMP_TO_EXIT_ERROR_PROC /* DEPRECATED */ if(edf_set_birthdate(hdl, 2005, 7, 4)) JUMP_TO_EXIT_ERROR_PROC if(edf_set_patient_additional(hdl, "Charlie")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_admincode(hdl, "Dëlta")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_technician(hdl, "Ëcho")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_equipment(hdl, "Foxtröt")) JUMP_TO_EXIT_ERROR_PROC if(edf_set_recording_additional(hdl, "Golf")) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<100; i++) { dbuf[i] = 0; } for(i=0; i<40; i++) { if(edfwrite_physical_samples(hdl, dbuf)) JUMP_TO_EXIT_ERROR_PROC } if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /********************************** EDF reading ******************************/ if(edfopen_file_readonly("test3.edf", &hdr, EDFLIB_READ_ALL_ANNOTATIONS)) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(hdr.filetype != 1) JUMP_TO_EXIT_ERROR_PROC if(hdr.edfsignals != 1) JUMP_TO_EXIT_ERROR_PROC for(i=0; i<60; i++) { if(edf_get_annotation(hdl, i * 2, &annot)) JUMP_TO_EXIT_ERROR_PROC // printf("i: %i onset: %lli\n", i, annot.onset); if(annot.onset != 10000000LL * (i + 1)) JUMP_TO_EXIT_ERROR_PROC if(edf_get_annotation(hdl, i * 2 + 1, &annot)) JUMP_TO_EXIT_ERROR_PROC if(annot.onset != 10000000LL * (i + 1) + 3333000LL) JUMP_TO_EXIT_ERROR_PROC // printf("i: %i onset: %lli\n", i * 2 + 1, annot.onset); } if(strncmp(hdr.patientcode, "Bravo", 5)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.sex, "Male", 4)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.gender, "Male", 4)) JUMP_TO_EXIT_ERROR_PROC /* DEPRECATED */ if(strncmp(hdr.birthdate, "04 jul 2005", 11)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.patient_additional, "Charlie", 7)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.admincode, "Delta", 5)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.technician, "Echo", 4)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.equipment, "Foxtrot", 7)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(hdr.recording_additional, "Golf", 4)) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /****************************************/ fp = fopen("test3.edf", "rb"); if(fp == NULL) JUMP_TO_EXIT_ERROR_PROC if(fread(str, 256, 1, fp) != 1) JUMP_TO_EXIT_ERROR_PROC fclose(fp); if(strncmp(str + 8, "Bravo M 04-JUL-2005 Alpha Charlie" " ", 80)) JUMP_TO_EXIT_ERROR_PROC if(strncmp(str + 88, "Startdate 31-DEC-2008 Delta Echo Foxtrot Golf" " ", 80)) JUMP_TO_EXIT_ERROR_PROC /********************************** EDF reading ******************************/ if(edfopen_file_readonly("test3.edf", &hdr, EDFLIB_DO_NOT_READ_ANNOTATIONS)) JUMP_TO_EXIT_ERROR_PROC hdl = hdr.handle; if(hdr.filetype != 1) JUMP_TO_EXIT_ERROR_PROC if(hdr.edfsignals != 1) JUMP_TO_EXIT_ERROR_PROC if(hdr.starttime_subsecond!=1234000LL) JUMP_TO_EXIT_ERROR_PROC if(edfclose_file(hdl)) { hdl = -1; JUMP_TO_EXIT_ERROR_PROC } hdl = -1; /****************************************/ free(ibuf); free(sbuf); free(dbuf); free(str); free(pbuf); return EXIT_SUCCESS; OUT_ERROR: if(hdl >= 0) { edfclose_file(hdl); } free(ibuf); free(sbuf); free(dbuf); free(str); free(pbuf); fprintf(stderr, "Error, line %i file %s\n", line, __FILE__); return EXIT_FAILURE; } int dblcmp(double val1, double val2) { long double diff = (long double)val1 - (long double)val2; if(diff > 1e-13) { return 1; } else if(-diff > 1e-13) { return -1; } else { return 0; } } int dblcmp_lim(double val1, double val2, double lim) { long double diff = (long double)val1 - (long double)val2; if(diff > lim) { return 1; } else if(-diff > lim) { return -1; } else { return 0; } } edflib_124/unittest/LICENSE000644 001750 000144 00000104513 12571340211 015555 0ustar00guvusers000000 000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . edflib_124/unittest/README000644 001750 000144 00000000460 13321166172 015432 0ustar00guvusers000000 000000 Run make to compile the unit test. Run ./edflib_test to run the test. If there are no errors, it doesn't output anything. In case there's an error, it exit with an error message telling in which line the problem is. Run make clean to cleanup the directory and remove all files generated by the test. edflib_124/README.md000644 001750 000144 00000012756 14420677405 014174 0ustar00guvusers000000 000000 # EDFlib EDFlib is a programming library for C/C++ for reading and writing EDF+ and BDF+ files. It also reads "old style" EDF and BDF files. EDF means European Data Format. BDF is the 24-bits version of EDF. ## Usage The library consists of only two files: `edflib.h` and `edflib.c`. In order to use EDFlib, copy these two files to your project. Include the file `edflib.h` in every source file from where you want to access the library. Don't forget to tell your compiler that it must compile and link `edflib.c` (add it to your makefile or build script). `edflib.c` needs to be compiled with the options `-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE`. For example: `gcc -Wall -Wextra -Wshadow -Wformat-nonliteral -Wformat-security -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE test_edflib.c edflib.c -lm -o test_edflib` Compilation has been tested using GCC on Linux, Mingw-w64 on Windows, and LLVM GCC on OS X (Yosemite). Big-endian systems are not supported. To understand how to use the library, read the comments in `edflib.h`. ## Examples To build the examples: `make` Each "generator" example creates an EDF+ or BDF+ file with sample signals. `test_generator` shows how to use most of the functions provided by the library and generates an EDF+ or BDF+ test file with several sample signals. `sine_generator` creates a BDF+ file containing the signal "sine", a 1 Hz sinusoidal waveform with a sample frequency of 2048 Hz. `sweep_generator` creates a linear or logarithmic sweep through a range of frequencies in EDF+ or BDF+ format. Use EDFbrowser to view these files: http://www.teuniz.net/edfbrowser/ `test_edflib ` will print the properties of the EDF/BDF header, the annotations, and the values of 200 samples of the chosen signal. For example, running `test_generator` will produce the file `test_generator.edf`. Running `test_edflib test_generator.edf 6` will show the header and first 200 samples of the "noise" signal: `75 6 27 77 37 30 35 96 62 69 34 15 51 56 69 68 80 45 ...` ## Background info 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): http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=sbaa042 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 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. ## License Copyright (c) 2009 - 2023 Teunis van Beelen All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. edflib_124/sweep_generator.c000644 001750 000144 00000016253 14416032226 016235 0ustar00guvusers000000 000000 /* ***************************************************************************** * * Copyright (c) 2009 - 2021 Teunis van Beelen * All rights reserved. * * Email: teuniz@protonmail.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY Teunis van Beelen ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Teunis van Beelen BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************** */ #define _GNU_SOURCE #include #include #include #include "edflib.h" #ifndef M_PI #define M_PI (3.14159265358979323846264338327) #endif #define SMP_FREQ (8192) // Uncomment the next line to create a BSF+ file instead of EDF+: //#define BDF_FORMAT void remove_trailing_zeros(char *); int main(void) { int i, j, hdl, chns=1, fileduration=300, linear=0; double buf[SMP_FREQ], q, sine_1, startfreq=10.0, stopfreq=4095.0, freqspan, freq; long long samples, sampleswritten; char str[256]; #ifdef BDF_FORMAT hdl = edfopen_file_writeonly("freq_sweep.bdf", EDFLIB_FILETYPE_BDFPLUS, chns); #else hdl = edfopen_file_writeonly("freq_sweep.edf", EDFLIB_FILETYPE_EDFPLUS, chns); #endif if(hdl<0) { printf("error: edfopen_file_writeonly()\n"); return(1); } for(i=0; i '9')) { if(decimalzerofound) { if(str[i-decimalzerofound-1] == '.') { decimalzerofound++; } for(j=i; j<(len+1); j++) { str[j-decimalzerofound] = str[j]; } trailingzerofound = 1; break; } if(str[i] != '.') { numberfound = 0; dotfound = 0; decimalzerofound = 0; } } else { numberfound = 1; if(str[i] > '0') { decimalzerofound = 0; } } if((str[i] == '.') && numberfound) { dotfound = 1; } if((str[i] == '0') && dotfound) { decimalzerofound++; } } } if(decimalzerofound) { if(str[i-decimalzerofound-1] == '.') { decimalzerofound++; } for(j=i; j<(len+1); j++) { str[j-decimalzerofound] = str[j]; } } } edflib_124/edflib.c000644 001750 000144 00000413651 14416032226 014274 0ustar00guvusers000000 000000 /* ***************************************************************************** * * Copyright (c) 2009 - 2023 Teunis van Beelen * All rights reserved. * * Email: teuniz@protonmail.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************** */ /* compile with options "-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE" */ #include "edflib.h" #define EDFLIB_VERSION (124) #define EDFLIB_MAXFILES (64) #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) || defined(__HAIKU__) || defined(__ANDROID__) #define fopeno fopen #else #define fseeko fseeko64 #define ftello ftello64 #define fopeno fopen64 #endif #ifdef _WIN32 #ifndef __MINGW32__ /* needed for visual c */ #undef fseeko #define fseeko _fseeki64 #undef ftello #define ftello _ftelli64 #undef fopeno #define fopeno fopen #endif #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 (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; static edf_write_annotationblock_t *write_annotationslist[EDFLIB_MAXFILES]; static int edf_files_open=0; static edfhdrblock_t *hdrlist[EDFLIB_MAXFILES]; static edfhdrblock_t * edflib_check_edf_file(FILE *, int *); 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(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(edfhdrblock_t *); static void edflib_latin1_to_ascii(char *, int); static void edflib_latin12utf8(char *, int); static void edflib_remove_padding_trailing_spaces(char *); static int edflib_atoi_nonlocalized(const char *); static double edflib_atof_nonlocalized(const char *); static int edflib_snprint_number_nonlocalized(char *, double, int); /* 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(edfhdrblock_t *, FILE *); static int edflib_strlcpy(char *, const char *, int); static int edflib_strlcat(char *, const char *, int); EDFLIB_API int edflib_is_file_used(const char *path) { int i; for(i=0; ipath))) return 1; } } return 0; } EDFLIB_API int edflib_get_number_of_open_files() { return edf_files_open; } EDFLIB_API int edflib_get_handle(int file_number) { int i, file_count=0; for(i=0; ifiletype = 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_mode<0)||(read_annotations_mode>2)) { edfhdr->filetype = EDFLIB_INVALID_READ_ANNOTS_VALUE; return -1; } if(edf_files_open>=EDFLIB_MAXFILES) { edfhdr->filetype = EDFLIB_MAXFILES_REACHED; return -1; } for(i=0; ipath))) { edfhdr->filetype = EDFLIB_FILE_ALREADY_OPENED; return -1; } } } file = fopeno(path, "rb"); if(file==NULL) { edfhdr->filetype = EDFLIB_NO_SUCH_FILE_OR_DIRECTORY; return -1; } hdr = edflib_check_edf_file(file, &edf_error); if(hdr==NULL) { edfhdr->filetype = edf_error; fclose(file); return -1; } if(hdr->discontinuous) { edfhdr->filetype = EDFLIB_FILE_IS_DISCONTINUOUS; free(hdr->edfparam); free(hdr); fclose(file); return -1; } for(i=0; ihandle = i; break; } } if((hdr->edf)&&(!(hdr->edfplus))) { edfhdr->filetype = EDFLIB_FILETYPE_EDF; } if(hdr->edfplus) { edfhdr->filetype = EDFLIB_FILETYPE_EDFPLUS; } if((hdr->bdf)&&(!(hdr->bdfplus))) { edfhdr->filetype = EDFLIB_FILETYPE_BDF; } if(hdr->bdfplus) { edfhdr->filetype = EDFLIB_FILETYPE_BDFPLUS; } edfhdr->edfsignals = hdr->edfsignals - hdr->nr_annot_chns; edfhdr->file_duration = hdr->long_data_record_duration * hdr->datarecords; edfhdr->startdate_day = hdr->startdate_day; edfhdr->startdate_month = hdr->startdate_month; edfhdr->startdate_year = hdr->startdate_year; edfhdr->starttime_hour = hdr->starttime_hour; edfhdr->starttime_second = hdr->starttime_second; edfhdr->starttime_minute = hdr->starttime_minute; edfhdr->starttime_subsecond = hdr->starttime_offset; edfhdr->datarecords_in_file = hdr->datarecords; edfhdr->datarecord_duration = hdr->long_data_record_duration; annotationslist[edfhdr->handle] = NULL; hdr->annotlist_sz = 0; hdr->annots_in_file = 0; edfhdr->annotations_in_file = 0LL; if((!(hdr->edfplus))&&(!(hdr->bdfplus))) { edflib_strlcpy(edfhdr->patient, hdr->patient, 81); edflib_strlcpy(edfhdr->recording, hdr->recording, 81); } else { edflib_strlcpy(edfhdr->patientcode, hdr->plus_patientcode, 81); 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); edflib_strlcpy(edfhdr->technician, hdr->plus_technician, 81); edflib_strlcpy(edfhdr->equipment, hdr->plus_equipment, 81); edflib_strlcpy(edfhdr->recording_additional, hdr->plus_recording_additional, 81); if(edflib_get_annotations(hdr, edfhdr->handle, read_annotations_mode)) { edfhdr->filetype = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; fclose(file); free(hdr->edfparam); hdr->edfparam = NULL; free(hdr); hdr = NULL; hdrlist[edfhdr->handle] = NULL; free(annotationslist[edfhdr->handle]); annotationslist[edfhdr->handle] = NULL; return -1; } edfhdr->starttime_subsecond = hdr->starttime_offset; edfhdr->annotations_in_file = hdr->annots_in_file; } edflib_strlcpy(hdr->path, path, 1024); edf_files_open++; j = 0; for(i=0; iedfsignals; i++) { if(!(hdr->edfparam[i].annotation)) { hdr->mapped_signals[j++] = i; } } for(i=0; iedfsignals; i++) { channel = hdr->mapped_signals[i]; edflib_strlcpy(edfhdr->signalparam[i].label, hdr->edfparam[channel].label, 17); edflib_strlcpy(edfhdr->signalparam[i].transducer, hdr->edfparam[channel].transducer, 81); edflib_strlcpy(edfhdr->signalparam[i].physdimension, hdr->edfparam[channel].physdimension, 9); edflib_strlcpy(edfhdr->signalparam[i].prefilter, hdr->edfparam[channel].prefilter, 81); edfhdr->signalparam[i].smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords; edfhdr->signalparam[i].phys_max = hdr->edfparam[channel].phys_max; edfhdr->signalparam[i].phys_min = hdr->edfparam[channel].phys_min; edfhdr->signalparam[i].dig_max = hdr->edfparam[channel].dig_max; edfhdr->signalparam[i].dig_min = hdr->edfparam[channel].dig_min; edfhdr->signalparam[i].smp_in_datarecord = hdr->edfparam[channel].smp_per_record; } return 0; } EDFLIB_API int edfclose_file(int handle) { edf_write_annotationblock_t *annot2; int i, j, k, n, p, err, datrecsize, nmemb; long long offset, datarecords; char str[EDFLIB_ANNOTATION_BYTES * 2]; edfhdrblock_t *hdr; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; hdr = hdrlist[handle]; if(hdr->writemode) { if(hdr->datarecords == 0LL) { err = edflib_write_edf_header(hdr); if(err) { fclose(hdr->file_hdl); free(hdr->edfparam); free(hdr->wrbuf); free(hdr); hdrlist[handle] = NULL; free(write_annotationslist[handle]); write_annotationslist[handle] = NULL; edf_files_open--; return err; } for(k=0; kannots_in_file; 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)) { fputc('.', hdr->file_hdl); p++; p += edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, hdr->file_hdl); fputc(20, hdr->file_hdl); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, hdr->file_hdl); } hdr->datarecords++; } } if(hdr->datarecords<100000000LL) { fseeko(hdr->file_hdl, 236LL, SEEK_SET); p = edflib_fprint_int_number_nonlocalized(hdr->file_hdl, (int)(hdr->datarecords), 0, 0); if(p < 2) { fputc(' ', hdr->file_hdl); } } datarecords = 0LL; offset = (long long)((hdr->edfsignals + hdr->nr_annot_chns + 1) * 256); datrecsize = hdr->total_annot_bytes; for(i=0; iedfsignals; i++) { if(hdr->edf) { offset += (long long)(hdr->edfparam[i].smp_per_record * 2); datrecsize += (hdr->edfparam[i].smp_per_record * 2); } else { offset += (long long)(hdr->edfparam[i].smp_per_record * 3); datrecsize += (hdr->edfparam[i].smp_per_record * 3); } } j = 0; for(k=0; kannots_in_file; k++) { annot2 = write_annotationslist[handle] + k; annot2->onset += hdr->starttime_offset / 10LL; p = 0; if(j==0) // first annotation signal { if(fseeko(hdr->file_hdl, offset, SEEK_SET)) { break; } p += edflib_snprint_ll_number_nonlocalized(str, (datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1, EDFLIB_ANNOTATION_BYTES * 2); if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset)) { str[p++] = '.'; n = edflib_snprint_ll_number_nonlocalized(str + p, (datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; } str[p++] = 20; str[p++] = 20; str[p++] = 0; } n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->onset / 1000000LL, 0, 1, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; if(annot2->onset % 1000000LL) { str[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 / 1000000LL, 0, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; if(annot2->duration % 1000000LL) { str[p++] = '.'; n = edflib_snprint_ll_number_nonlocalized(str + p, annot2->duration % 1000000LL, 6, 0, (EDFLIB_ANNOTATION_BYTES * 2) - p); p += n; } } str[p++] = 20; for(i=0; iannotation[i]==0) { break; } str[p++] = annot2->annotation[i]; } str[p++] = 20; for(; pfile_hdl); if(nmemb != 1) { break; } j++; if(j >= hdr->nr_annot_chns) { j = 0; offset += datrecsize; datarecords++; if(datarecords>=hdr->datarecords) { break; } } } free(write_annotationslist[handle]); } else { free(annotationslist[handle]); } fclose(hdr->file_hdl); free(hdr->edfparam); free(hdr->wrbuf); free(hdr); hdrlist[handle] = NULL; edf_files_open--; return 0; } 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(hdrlist[handle]==NULL) return -1; if(edfsignal<0) return -1; if(hdrlist[handle]->writemode) return -1; if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) return -1; channel = hdrlist[handle]->mapped_signals[edfsignal]; smp_in_file = hdrlist[handle]->edfparam[channel].smp_per_record * hdrlist[handle]->datarecords; if(whence==EDFSEEK_SET) { hdrlist[handle]->edfparam[channel].sample_pntr = offset; } if(whence==EDFSEEK_CUR) { hdrlist[handle]->edfparam[channel].sample_pntr += offset; } if(whence==EDFSEEK_END) { hdrlist[handle]->edfparam[channel].sample_pntr = (hdrlist[handle]->edfparam[channel].smp_per_record * hdrlist[handle]->datarecords) + offset; } if(hdrlist[handle]->edfparam[channel].sample_pntr > smp_in_file) { hdrlist[handle]->edfparam[channel].sample_pntr = smp_in_file; } if(hdrlist[handle]->edfparam[channel].sample_pntr < 0LL) { hdrlist[handle]->edfparam[channel].sample_pntr = 0LL; } return hdrlist[handle]->edfparam[channel].sample_pntr; } EDFLIB_API long long edftell(int handle, int edfsignal) { int channel; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(edfsignal<0) return -1; if(hdrlist[handle]->writemode) return -1; if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) return -1; channel = hdrlist[handle]->mapped_signals[edfsignal]; return hdrlist[handle]->edfparam[channel].sample_pntr; } EDFLIB_API void edfrewind(int handle, int edfsignal) { int channel; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return; if(hdrlist[handle]==NULL) return; if(edfsignal<0) return; if(hdrlist[handle]->writemode) return; if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) return; channel = hdrlist[handle]->mapped_signals[edfsignal]; hdrlist[handle]->edfparam[channel].sample_pntr = 0LL; } EDFLIB_API int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) { int bytes_per_smpl=2, tmp, i, channel; double phys_bitvalue, phys_offset; long long smp_in_file, offset, sample_pntr, smp_per_record, jump; edfhdrblock_t *hdr; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; FILE *file; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(edfsignal<0) return -1; if(hdrlist[handle]->writemode) 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 0LL; hdr = hdrlist[handle]; if(hdr->edf) { bytes_per_smpl = 2; } if(hdr->bdf) { bytes_per_smpl = 3; } smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords; if((hdr->edfparam[channel].sample_pntr + n) > smp_in_file) { n = smp_in_file - hdr->edfparam[channel].sample_pntr; if(n==0) return 0LL; if(n<0) return -1; } file = hdr->file_hdl; offset = hdr->hdrsize; offset += (hdr->edfparam[channel].sample_pntr / hdr->edfparam[channel].smp_per_record) * hdr->recordsize; offset += hdr->edfparam[channel].buf_offset; offset += ((hdr->edfparam[channel].sample_pntr % hdr->edfparam[channel].smp_per_record) * bytes_per_smpl); fseeko(file, offset, SEEK_SET); sample_pntr = hdr->edfparam[channel].sample_pntr; smp_per_record = hdr->edfparam[channel].smp_per_record; jump = hdr->recordsize - (smp_per_record * bytes_per_smpl); phys_bitvalue = hdr->edfparam[channel].bitvalue; phys_offset = hdr->edfparam[channel].offset; if(hdr->edf) { for(i=0; i 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++; } } if(hdr->bdf) { for(i=0; i 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++; } } hdr->edfparam[channel].sample_pntr = sample_pntr; return n; } EDFLIB_API int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) { int bytes_per_smpl=2, tmp, i, channel; long long smp_in_file, offset, sample_pntr, smp_per_record, jump; edfhdrblock_t *hdr; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; FILE *file; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(edfsignal<0) return -1; if(hdrlist[handle]->writemode) 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 0LL; hdr = hdrlist[handle]; if(hdr->edf) { bytes_per_smpl = 2; } if(hdr->bdf) { bytes_per_smpl = 3; } smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords; if((hdr->edfparam[channel].sample_pntr + n) > smp_in_file) { n = smp_in_file - hdr->edfparam[channel].sample_pntr; if(n==0) { return 0LL; } if(n<0) { return -1; } } file = hdr->file_hdl; offset = hdr->hdrsize; offset += (hdr->edfparam[channel].sample_pntr / hdr->edfparam[channel].smp_per_record) * hdr->recordsize; offset += hdr->edfparam[channel].buf_offset; offset += ((hdr->edfparam[channel].sample_pntr % hdr->edfparam[channel].smp_per_record) * bytes_per_smpl); fseeko(file, offset, SEEK_SET); sample_pntr = hdr->edfparam[channel].sample_pntr; smp_per_record = hdr->edfparam[channel].smp_per_record; jump = hdr->recordsize - (smp_per_record * bytes_per_smpl); if(hdr->edf) { for(i=0; i 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] = var.two_signed[0]; sample_pntr++; } } if(hdr->bdf) { for(i=0; i 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++; } } hdr->edfparam[channel].sample_pntr = sample_pntr; return n; } EDFLIB_API int edf_get_annotation(int handle, int n, edflib_annotation_t *annot) { memset(annot, 0, sizeof(edflib_annotation_t)); if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(hdrlist[handle]->writemode) return -1; if(n<0) return -1; if(n>=hdrlist[handle]->annots_in_file) return -1; annot->onset = (annotationslist[handle] + n)->onset; 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 edfhdrblock_t * edflib_check_edf_file(FILE *inputfile, int *edf_error) { int i, j, p, r=0, n, dotposition, error; char *edf_hdr, scratchpad[128], scratchpad2[64]; edfhdrblock_t *edfhdr; /***************** check header ******************************/ edf_hdr = (char *)calloc(1, 256); if(edf_hdr==NULL) { *edf_error = EDFLIB_MALLOC_ERROR; return NULL; } edfhdr = (edfhdrblock_t *)calloc(1, sizeof(edfhdrblock_t)); if(edfhdr==NULL) { free(edf_hdr); *edf_error = EDFLIB_MALLOC_ERROR; return NULL; } rewind(inputfile); if(fread(edf_hdr, 256, 1, inputfile)!=1) { *edf_error = EDFLIB_FILE_READ_ERROR; free(edf_hdr); free(edfhdr); return NULL; } /**************************** VERSION ***************************************/ strncpy(scratchpad, edf_hdr, 8); scratchpad[8] = 0; if(((signed char *)scratchpad)[0]==-1) /* BDF-file */ { for(i=1; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } if(strcmp(scratchpad + 1, "BIOSEMI")) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } edfhdr->bdf = 1; } else /* EDF-file */ { for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } if(strcmp(scratchpad, "0 ")) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } edfhdr->edf = 1; } strncpy(edfhdr->version, edf_hdr, 8); edfhdr->version[8] = 0; if(edfhdr->bdf) edfhdr->version[0] = '.'; /********************* PATIENTNAME *********************************************/ strncpy(scratchpad, edf_hdr + 8, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } strncpy(edfhdr->patient, edf_hdr + 8, 80); edfhdr->patient[80] = 0; /********************* RECORDING *********************************************/ strncpy(scratchpad, edf_hdr + 88, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } strncpy(edfhdr->recording, edf_hdr + 88, 80); edfhdr->recording[80] = 0; /********************* STARTDATE *********************************************/ strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } error = 0; if((edf_hdr[170]!='.')||(edf_hdr[173]!='.')) error = 1; if((edf_hdr[168]<48)||(edf_hdr[168]>57)) error = 1; if((edf_hdr[169]<48)||(edf_hdr[169]>57)) error = 1; if((edf_hdr[171]<48)||(edf_hdr[171]>57)) error = 1; if((edf_hdr[172]<48)||(edf_hdr[172]>57)) error = 1; if((edf_hdr[174]<48)||(edf_hdr[174]>57)) error = 1; if((edf_hdr[175]<48)||(edf_hdr[175]>57)) error = 1; strncpy(scratchpad, edf_hdr + 168, 8); if(error) { scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if((edflib_atoi_nonlocalized(scratchpad)<1)||(edflib_atoi_nonlocalized(scratchpad)>31)) { strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } if((edflib_atoi_nonlocalized(scratchpad+3)<1)||(edflib_atoi_nonlocalized(scratchpad+3)>12)) { strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } 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; } else { edfhdr->startdate_year += 2000; } /********************* STARTTIME *********************************************/ strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } error = 0; if((edf_hdr[178]!='.')||(edf_hdr[181]!='.')) error = 1; if((edf_hdr[176]<48)||(edf_hdr[176]>57)) error = 1; if((edf_hdr[177]<48)||(edf_hdr[177]>57)) error = 1; if((edf_hdr[179]<48)||(edf_hdr[179]>57)) error = 1; if((edf_hdr[180]<48)||(edf_hdr[180]>57)) error = 1; if((edf_hdr[182]<48)||(edf_hdr[182]>57)) error = 1; if((edf_hdr[183]<48)||(edf_hdr[183]>57)) error = 1; strncpy(scratchpad, edf_hdr + 176, 8); if(error) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if(edflib_atoi_nonlocalized(scratchpad)>23) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } if(edflib_atoi_nonlocalized(scratchpad+3)>59) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } if(edflib_atoi_nonlocalized(scratchpad+6)>59) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } 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_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; /***************** NUMBER OF SIGNALS IN HEADER *******************************/ strncpy(scratchpad, edf_hdr + 252, 4); scratchpad[4] = 0; for(i=0; i<4; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } edfhdr->edfsignals = edflib_atoi_nonlocalized(scratchpad); if(edfhdr->edfsignals<1) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } if(edfhdr->edfsignals>EDFLIB_MAXSIGNALS) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } /***************** NUMBER OF BYTES IN HEADER *******************************/ strncpy(scratchpad, edf_hdr + 184, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } n = edflib_atoi_nonlocalized(scratchpad); if((edfhdr->edfsignals * 256 + 256)!=n) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } /********************* RESERVED FIELD *************************************/ edfhdr->edfplus = 0; edfhdr->discontinuous = 0; strncpy(scratchpad, edf_hdr + 192, 44); scratchpad[44] = 0; for(i=0; i<44; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } if(edfhdr->edf) { if(!strncmp(scratchpad, "EDF+C ", 44)) { edfhdr->edfplus = 1; edfhdr->discontinuous = 0; } else if(!strncmp(scratchpad, "EDF+D ", 44)) { edfhdr->edfplus = 1; edfhdr->discontinuous = 1; } else if(strncmp(scratchpad, " ", 44)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } if(edfhdr->bdf) { if(!strncmp(scratchpad, "BDF+C ", 44)) { edfhdr->bdfplus = 1; edfhdr->discontinuous = 0; } if(!strncmp(scratchpad, "BDF+D ", 44)) { edfhdr->bdfplus = 1; edfhdr->discontinuous = 1; } } strncpy(edfhdr->reserved, edf_hdr + 192, 44); edfhdr->reserved[44] = 0; /********************* NUMBER OF DATARECORDS *************************************/ strncpy(scratchpad, edf_hdr + 236, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } edfhdr->datarecords = edflib_atoi_nonlocalized(scratchpad); if(edfhdr->datarecords<1) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } /********************* DATARECORD DURATION *************************************/ strncpy(scratchpad, edf_hdr + 244, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } } if(edflib_is_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } edfhdr->data_record_duration = edflib_atof_nonlocalized(scratchpad); if(edfhdr->data_record_duration < -0.000001) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return NULL; } edfhdr->long_data_record_duration = edflib_get_long_duration(scratchpad); free(edf_hdr); /********************* START WITH THE SIGNALS IN THE HEADER *********************/ edf_hdr = (char *)calloc(1, (edfhdr->edfsignals + 1) * 256); if(edf_hdr==NULL) { *edf_error = EDFLIB_MALLOC_ERROR; free(edfhdr); return NULL; } rewind(inputfile); if(fread(edf_hdr, (edfhdr->edfsignals + 1) * 256, 1, inputfile)!=1) { *edf_error = EDFLIB_FILE_READ_ERROR; free(edf_hdr); free(edfhdr); return NULL; } edfhdr->edfparam = (edfparamblock_t *)calloc(1, sizeof(edfparamblock_t) * edfhdr->edfsignals); if(edfhdr->edfparam==NULL) { *edf_error = EDFLIB_MALLOC_ERROR; free(edf_hdr); free(edfhdr); return NULL; } /**************************** LABELS *************************************/ edfhdr->nr_annot_chns = 0; for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (i * 16), 16); for(j=0; j<16; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } if(edfhdr->edfplus) { if(!strncmp(scratchpad, "EDF Annotations ", 16)) { edfhdr->annot_ch[edfhdr->nr_annot_chns] = i; edfhdr->nr_annot_chns++; edfhdr->edfparam[i].annotation = 1; } } if(edfhdr->bdfplus) { if(!strncmp(scratchpad, "BDF Annotations ", 16)) { edfhdr->annot_ch[edfhdr->nr_annot_chns] = i; edfhdr->nr_annot_chns++; edfhdr->edfparam[i].annotation = 1; } } strncpy(edfhdr->edfparam[i].label, edf_hdr + 256 + (i * 16), 16); edfhdr->edfparam[i].label[16] = 0; } if(edfhdr->edfplus&&(!edfhdr->nr_annot_chns)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } if(edfhdr->bdfplus&&(!edfhdr->nr_annot_chns)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } if((edfhdr->edfsignals!=edfhdr->nr_annot_chns)||((!edfhdr->edfplus)&&(!edfhdr->bdfplus))) { if(edfhdr->data_record_duration<0.0000001) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } /**************************** TRANSDUCER TYPES *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80); for(j=0; j<80; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } strncpy(edfhdr->edfparam[i].transducer, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80); edfhdr->edfparam[i].transducer[80] = 0; if((edfhdr->edfplus) || (edfhdr->bdfplus)) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { if(edfhdr->edfparam[i].transducer[j]!=' ') { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } } } } /**************************** PHYSICAL DIMENSIONS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 96) + (i * 8), 8); for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } strncpy(edfhdr->edfparam[i].physdimension, edf_hdr + 256 + (edfhdr->edfsignals * 96) + (i * 8), 8); edfhdr->edfparam[i].physdimension[8] = 0; } /**************************** PHYSICAL MINIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 104) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } if(edflib_is_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } edfhdr->edfparam[i].phys_min = edflib_atof_nonlocalized(scratchpad); } /**************************** PHYSICAL MAXIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 112) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } if(edflib_is_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } edfhdr->edfparam[i].phys_max = edflib_atof_nonlocalized(scratchpad); if(edfhdr->edfparam[i].phys_max==edfhdr->edfparam[i].phys_min) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } /**************************** DIGITAL MINIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 120) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } n = edflib_atoi_nonlocalized(scratchpad); if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=-0x8000) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } } if(edfhdr->bdfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=-0x800000) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } } if(edfhdr->edf) { if((n>0x7fff)||(n<-0x8000)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } if(edfhdr->bdf) { if((n>0x7fffff)||(n<-0x800000)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } edfhdr->edfparam[i].dig_min = n; } /**************************** DIGITAL MAXIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 128) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } n = edflib_atoi_nonlocalized(scratchpad); if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=0x7fff) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } } if(edfhdr->bdfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=0x7fffff) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } } if(edfhdr->edf) { if((n>0x7fff)||(n<-0x8000)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } else { if((n>0x7fffff)||(n<-0x800000)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } edfhdr->edfparam[i].dig_max = n; if(edfhdr->edfparam[i].dig_max<(edfhdr->edfparam[i].dig_min + 1)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } /**************************** PREFILTER FIELDS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80); for(j=0; j<80; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } strncpy(edfhdr->edfparam[i].prefilter, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80); edfhdr->edfparam[i].prefilter[80] = 0; if((edfhdr->edfplus) || (edfhdr->bdfplus)) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { if(edfhdr->edfparam[i].prefilter[j]!=' ') { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } } } } /*********************** NR OF SAMPLES IN EACH DATARECORD ********************/ edfhdr->recordsize = 0; for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 216) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } n = edflib_atoi_nonlocalized(scratchpad); if(n<1) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } edfhdr->edfparam[i].smp_per_record = n; edfhdr->recordsize += n; } if(edfhdr->bdf) { edfhdr->recordsize *= 3; if(edfhdr->recordsize > (15 * 1024 * 1024)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } else { edfhdr->recordsize *= 2; if(edfhdr->recordsize > (10 * 1024 * 1024)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } /**************************** RESERVED FIELDS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 224) + (i * 32), 32); for(j=0; j<32; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } strncpy(edfhdr->edfparam[i].reserved, edf_hdr + 256 + (edfhdr->edfsignals * 224) + (i * 32), 32); edfhdr->edfparam[i].reserved[32] = 0; } /********************* EDF+ PATIENTNAME *********************************************/ if(edfhdr->edfplus || edfhdr->bdfplus) { error = 0; dotposition = 0; strncpy(scratchpad, edf_hdr + 8, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if(scratchpad[i]==' ') { dotposition = i; break; } } dotposition++; if((dotposition>73)||(dotposition<2)) error = 1; if(scratchpad[dotposition + 2]!='X') { if(dotposition>65) error = 1; } if((scratchpad[dotposition]!='M')&&(scratchpad[dotposition]!='F')&&(scratchpad[dotposition]!='X')) error = 1; dotposition++; if(scratchpad[dotposition]!=' ') error = 1; if(scratchpad[dotposition + 1]=='X') { if(scratchpad[dotposition + 2]!=' ') error = 1; if(scratchpad[dotposition + 3]==' ') error = 1; } else { if(scratchpad[dotposition + 12]!=' ') error = 1; if(scratchpad[dotposition + 13]==' ') error = 1; dotposition++; strncpy(scratchpad2, scratchpad + dotposition, 11); scratchpad2[11] = 0; if((scratchpad2[2]!='-')||(scratchpad2[6]!='-')) error = 1; scratchpad2[2] = 0; scratchpad2[6] = 0; if((scratchpad2[0]<48)||(scratchpad2[0]>57)) error = 1; if((scratchpad2[1]<48)||(scratchpad2[1]>57)) error = 1; if((scratchpad2[7]<48)||(scratchpad2[7]>57)) error = 1; 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_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")) if(strcmp(scratchpad2 + 3, "APR")) if(strcmp(scratchpad2 + 3, "MAY")) if(strcmp(scratchpad2 + 3, "JUN")) if(strcmp(scratchpad2 + 3, "JUL")) if(strcmp(scratchpad2 + 3, "AUG")) if(strcmp(scratchpad2 + 3, "SEP")) if(strcmp(scratchpad2 + 3, "OCT")) if(strcmp(scratchpad2 + 3, "NOV")) if(strcmp(scratchpad2 + 3, "DEC")) error = 1; } if(error) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } p = 0; if((edfhdr->patient[p]=='X') && (edfhdr->patient[p+1]==' ')) { edfhdr->plus_patientcode[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->patient[i+p]==' ') { break; } edfhdr->plus_patientcode[i] = edfhdr->patient[i+p]; if(edfhdr->plus_patientcode[i]=='_') edfhdr->plus_patientcode[i] = ' '; } edfhdr->plus_patientcode[i] = 0; p += i + 1; } if(edfhdr->patient[p]=='M') { edflib_strlcpy(edfhdr->plus_sex, "Male", 16); } if(edfhdr->patient[p]=='F') { edflib_strlcpy(edfhdr->plus_sex, "Female", 16); } if(edfhdr->patient[p]=='X') { edfhdr->plus_sex[0] = 0; } for(i=0; i<(80-p);i++) { if(edfhdr->patient[i+p]==' ') { break; } } p += i + 1; if(edfhdr->patient[p]=='X') { edfhdr->plus_birthdate[0] = 0; edfhdr->plus_birthdate_day = 0; edfhdr->plus_birthdate_month = 0; edfhdr->plus_birthdate_year = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->patient[i+p]==' ') { break; } edfhdr->plus_birthdate[i] = edfhdr->patient[i+p]; } edfhdr->plus_birthdate[2] = ' '; edfhdr->plus_birthdate[3] += 32; edfhdr->plus_birthdate[4] += 32; edfhdr->plus_birthdate[5] += 32; edfhdr->plus_birthdate[6] = ' '; edfhdr->plus_birthdate[11] = 0; p += i + 1; edfhdr->plus_birthdate_day = edflib_atoi_nonlocalized(edfhdr->plus_birthdate); if(!strncmp(edfhdr->plus_birthdate + 3, "jan", 3)) { edfhdr->plus_birthdate_month = 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++) { edfhdr->plus_patient_additional[i] = edfhdr->patient[i+p]; } edfhdr->plus_patient_additional[i] = 0; p += i + 1; } /********************* EDF+ RECORDINGFIELD *********************************************/ if(edfhdr->edfplus || edfhdr->bdfplus) { error = 0; strncpy(scratchpad, edf_hdr + 88, 80); scratchpad[80] = 0; if(strncmp(scratchpad, "Startdate ", 10)) error = 1; if(scratchpad[10]=='X') { if(scratchpad[11]!=' ') error = 1; if(scratchpad[12]==' ') error = 1; p = 12; } else { if(scratchpad[21]!=' ') error = 1; if(scratchpad[22]==' ') error = 1; p = 22; strncpy(scratchpad2, scratchpad + 10, 11); scratchpad2[11] = 0; if((scratchpad2[2]!='-')||(scratchpad2[6]!='-')) error = 1; scratchpad2[2] = 0; scratchpad2[6] = 0; if((scratchpad2[0]<48)||(scratchpad2[0]>57)) error = 1; if((scratchpad2[1]<48)||(scratchpad2[1]>57)) error = 1; if((scratchpad2[7]<48)||(scratchpad2[7]>57)) error = 1; 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_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; else if(!strcmp(scratchpad2 + 3, "MAR")) r = 3; else if(!strcmp(scratchpad2 + 3, "APR")) r = 4; else if(!strcmp(scratchpad2 + 3, "MAY")) r = 5; else if(!strcmp(scratchpad2 + 3, "JUN")) r = 6; else if(!strcmp(scratchpad2 + 3, "JUL")) r = 7; else if(!strcmp(scratchpad2 + 3, "AUG")) r = 8; else if(!strcmp(scratchpad2 + 3, "SEP")) r = 9; else if(!strcmp(scratchpad2 + 3, "OCT")) r = 10; else if(!strcmp(scratchpad2 + 3, "NOV")) r = 11; else if(!strcmp(scratchpad2 + 3, "DEC")) r = 12; else error = 1; } n = 0; for(i=p; i<80; i++) { if(i>78) { error = 1; break; } if(scratchpad[i]==' ') { n++; if(scratchpad[i + 1]==' ') { error = 1; break; } } if(n>1) break; } if(error) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } if(edf_hdr[98]!='X') { error = 0; strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; 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_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } if(edfhdr->startdate_year != edflib_atoi_nonlocalized(scratchpad2 + 7)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } } p = 10; for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_startdate[i] = edfhdr->recording[i+p]; } edfhdr->plus_startdate[2] = ' '; edfhdr->plus_startdate[3] += 32; edfhdr->plus_startdate[4] += 32; edfhdr->plus_startdate[5] += 32; edfhdr->plus_startdate[6] = ' '; edfhdr->plus_startdate[11] = 0; p += i + 1; if((edfhdr->recording[p]=='X') && (edfhdr->recording[p+1]==' ')) { edfhdr->plus_admincode[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_admincode[i] = edfhdr->recording[i+p]; if(edfhdr->plus_admincode[i]=='_') edfhdr->plus_admincode[i] = ' '; } edfhdr->plus_admincode[i] = 0; p += i + 1; } if((edfhdr->recording[p]=='X') && (edfhdr->recording[p+1]==' ')) { edfhdr->plus_technician[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_technician[i] = edfhdr->recording[i+p]; if(edfhdr->plus_technician[i]=='_') edfhdr->plus_technician[i] = ' '; } edfhdr->plus_technician[i] = 0; p += i + 1; } if((edfhdr->recording[p]=='X') && (edfhdr->recording[p+1]==' ')) { edfhdr->plus_equipment[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_equipment[i] = edfhdr->recording[i+p]; if(edfhdr->plus_equipment[i]=='_') edfhdr->plus_equipment[i] = ' '; } edfhdr->plus_equipment[i] = 0; p += i + 1; } for(i=0; i<(80-p);i++) { edfhdr->plus_recording_additional[i] = edfhdr->recording[i+p]; } edfhdr->plus_recording_additional[i] = 0; p += i + 1; } /********************* FILESIZE *********************************************/ edfhdr->hdrsize = edfhdr->edfsignals * 256 + 256; fseeko(inputfile, 0LL, SEEK_END); if(ftello(inputfile)!=(edfhdr->recordsize * edfhdr->datarecords + edfhdr->hdrsize)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return NULL; } n = 0; for(i=0; iedfsignals; i++) { 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; 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; } edfhdr->file_hdl = inputfile; free(edf_hdr); return edfhdr; } static int edflib_is_integer_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0; l = strlen(str); if(!l) return 1; if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57)) { return 1; } else { if(hasspace) { return 1; } digit++; } } } if(digit) return 0; else return 1; } static int edflib_is_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0, hasdot=0, hasexp=0; l = strlen(str); if(!l) return 1; if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57))&&str[i]!='.') { return 1; } else { if(hasspace) { return 1; } if(str[i]=='.') { if(hasdot) return 1; hasdot++; } else { digit++; } } } } if(hasexp) { if(++i==l) { return 1; } if((str[i]=='+')||(str[i]=='-')) { hassign++; i++; } for(; i57)) { return 1; } else { if(hasspace) { return 1; } digit++; } } } } if(digit) return 0; else return 1; } 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] == '-')) { for(i=0; i<7; i++) { str[i] = str[i+1]; } str[7] = ' '; } for(i=0; i<8; i++) { if(str[i]==' ') { len = i; break; } } for(i=0; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = EDFLIB_TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } return value; } EDFLIB_API int edflib_version(void) { return EDFLIB_VERSION; } static int edflib_get_annotations(edfhdrblock_t *edfhdr, int hdl, int read_annotations_mode) { int i, j, k, p, r=0, n, edfsignals, datarecords, recordsize, discontinuous, *annot_ch, nr_annot_chns, max, onset, duration, duration_start, zero, max_tal_ln, error, annots_in_record, annots_in_tal, samplesize=2; 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=NULL; edfparamblock_t *edfparam=NULL; edf_read_annotationblock_t *new_annotation=NULL, *malloc_list=NULL; inputfile = edfhdr->file_hdl; edfsignals = edfhdr->edfsignals; recordsize = edfhdr->recordsize; edfparam = edfhdr->edfparam; nr_annot_chns = edfhdr->nr_annot_chns; datarecords = edfhdr->datarecords; data_record_duration = edfhdr->long_data_record_duration; discontinuous = edfhdr->discontinuous; annot_ch = edfhdr->annot_ch; if(edfhdr->edfplus) { samplesize = 2; } if(edfhdr->bdfplus) { samplesize = 3; } cnv_buf = (char *)calloc(1, recordsize); if(cnv_buf==NULL) { return 1; } max_tal_ln = 0; for(i=0; i=EDFLIB_TIME_DIMENSION) || (time_tmp<0LL)) { error = 2; goto END; } else { edfhdr->starttime_offset = time_tmp; if(read_annotations_mode==EDFLIB_DO_NOT_READ_ANNOTATIONS) { error = 0; goto END_OUT; } } } elapsedtime = time_tmp; error = 0; break; } } } } for(k=0; k1) { error = 34; goto END; } zero = 0; if((scratchpad[n]==20)||(scratchpad[n]==21)) { if(scratchpad[n]==21) { if(duration||duration_start||onset||annots_in_tal) { /* it's not allowed to have multiple duration fields */ error = 35; /* in one TAL or to have a duration field which is */ goto END; /* not immediately behind the onsetfield */ } duration_start = 1; } if((scratchpad[n]==20)&&onset&&(!duration_start)) { if(r||annots_in_record) { if(n >= 0) { if(edfhdr->annots_in_file >= edfhdr->annotlist_sz) { 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); free(scratchpad); free(time_in_txt); free(duration_in_txt); return -1; } annotationslist[hdl] = malloc_list; edfhdr->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ; } new_annotation = annotationslist[hdl] + edfhdr->annots_in_file; new_annotation->annotation[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; jannotation[j] = scratchpad[j]; } new_annotation->annotation[j] = 0; new_annotation->onset = edflib_get_long_time(time_in_txt); new_annotation->onset -= edfhdr->starttime_offset; edfhdr->annots_in_file++; if(read_annotations_mode==EDFLIB_READ_ANNOTATIONS) { if(!(strncmp(new_annotation->annotation, "Recording ends", 14))) { if(nr_annot_chns==1) { goto END; } } } } } annots_in_tal++; annots_in_record++; n = 0; continue; } if(!onset) { scratchpad[n] = 0; if(edflib_is_onset_number(scratchpad)) { error = 36; goto END; } onset = 1; n = 0; edflib_strlcpy(time_in_txt, scratchpad, max_tal_ln + 3); continue; } if(duration_start) { scratchpad[n] = 0; if(edflib_is_duration_number(scratchpad)) { error = 37; goto END; } for(j=0; j126)) { duration_in_txt[j] = '.'; } } duration_in_txt[j] = 0; duration = 1; duration_start = 0; n = 0; continue; } } n++; } END: /****************** end ************************/ if(error) { free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return 9; } } } END_OUT: free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return 0; } static int edflib_is_duration_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(!l) return 1; if((str[0] == '.')||(str[l-1] == '.')) return 1; for(i=0; i57)) return 1; } } return 0; } static int edflib_is_onset_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(l<2) return 1; if((str[0]!='+')&&(str[0]!='-')) return 1; if((str[1] == '.')||(str[l-1] == '.')) return 1; for(i=1; i57)) return 1; } } return 0; } static long long edflib_get_long_time(char *str) { int i, len, hasdot=0, dotposition=0, neg=0; long long value=0, radix; if(str[0] == '+') { str++; } else if(str[0] == '-') { neg = 1; str++; } len = strlen(str); for(i=0; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = EDFLIB_TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } if(neg) value = -value; return value; } 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; i31)&&(value<127)) { continue; } if(value < 32) { str[i] = '.'; continue; } str[i] = conv_table[value - 127]; } } static void edflib_latin12utf8(char *latin1_str, int len) { int i, j; unsigned char *str, tmp_str[512]; str = (unsigned char *)latin1_str; j = 0; for(i=0; i126)&&(str[i]<160)) tmp_str[j] = '.'; if(str[i]>159) { if((len-j)<2) { tmp_str[j] = ' '; } else { tmp_str[j] = 192 + (str[i]>>6); j++; tmp_str[j] = 128 + (str[i]&63); } } j++; if(j>=len) break; } for(i=0; i=EDFLIB_MAXFILES) { return EDFLIB_MAXFILES_REACHED; } for(i=0; ipath))) { return EDFLIB_FILE_ALREADY_OPENED; } } } if(number_of_signals<0) { return EDFLIB_NUMBER_OF_SIGNALS_INVALID; } if(number_of_signals>EDFLIB_MAXSIGNALS) { return EDFLIB_NUMBER_OF_SIGNALS_INVALID; } hdr = (edfhdrblock_t *)calloc(1, sizeof(edfhdrblock_t)); if(hdr==NULL) { return EDFLIB_MALLOC_ERROR; } hdr->edfparam = (edfparamblock_t *)calloc(1, sizeof(edfparamblock_t) * number_of_signals); if(hdr->edfparam==NULL) { free(hdr); return EDFLIB_MALLOC_ERROR; } hdr->writemode = 1; hdr->edfsignals = number_of_signals; handle = -1; for(i=0; iedfparam); free(hdr); return EDFLIB_MAXFILES_REACHED; } write_annotationslist[handle] = NULL; hdr->annotlist_sz = 0; hdr->annots_in_file = 0; file = fopeno(path, "wb"); if(file==NULL) { free(hdr->edfparam); hdr->edfparam = NULL; free(hdr); hdr = NULL; hdrlist[handle] = NULL; return EDFLIB_NO_SUCH_FILE_OR_DIRECTORY; } hdr->file_hdl = file; edflib_strlcpy(hdr->path, path, 1024); edf_files_open++; if(filetype==EDFLIB_FILETYPE_EDFPLUS) { hdr->edf = 1; hdr->edfplus = 1; } if(filetype==EDFLIB_FILETYPE_BDFPLUS) { hdr->bdf = 1; hdr->bdfplus = 1; } hdr->long_data_record_duration = EDFLIB_TIME_DIMENSION; hdr->data_record_duration = 1.0; hdr->nr_annot_chns = 1; return handle; } EDFLIB_API int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) 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(samplefrequency<1) return -1; if(hdrlist[handle]->datarecords) return -1; hdrlist[handle]->edfparam[edfsignal].smp_per_record = samplefrequency; return 0; } EDFLIB_API int edf_set_number_of_annotation_signals(int handle, int annot_signals) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((annot_signals < 1) || (annot_signals > EDFLIB_MAX_ANNOTATION_CHANNELS)) return -1; hdrlist[handle]->nr_annot_chns = annot_signals; return 0; } EDFLIB_API int edf_set_datarecord_duration(int handle, int duration) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((duration < 100) || (duration > 6000000)) return -1; hdrlist[handle]->long_data_record_duration = (long long)duration * 100LL; if(hdrlist[handle]->long_data_record_duration < (EDFLIB_TIME_DIMENSION * 10LL)) { hdrlist[handle]->long_data_record_duration /= 10LL; hdrlist[handle]->long_data_record_duration *= 10LL; } else { hdrlist[handle]->long_data_record_duration /= 100LL; hdrlist[handle]->long_data_record_duration *= 100LL; } hdrlist[handle]->data_record_duration = ((double)(hdrlist[handle]->long_data_record_duration)) / EDFLIB_TIME_DIMENSION; return 0; } EDFLIB_API int edf_set_micro_datarecord_duration(int handle, int duration) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((duration < 1) || (duration > 9999)) return -1; hdrlist[handle]->long_data_record_duration = (long long)duration * 10LL; hdrlist[handle]->data_record_duration = ((double)(hdrlist[handle]->long_data_record_duration)) / EDFLIB_TIME_DIMENSION; return 0; } EDFLIB_API int edf_set_subsecond_starttime(int handle, int subsecond) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((subsecond < 0) || (subsecond > 9999999)) return -1; hdrlist[handle]->starttime_offset = (long long)subsecond; return 0; } EDFLIB_API int edfwrite_digital_short_samples(int handle, short *buf) { int i, error, sf, digmax, digmin, edfsignal, value; FILE *file; edfhdrblock_t *hdr; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->edfsignals == 0) return -1; if(hdrlist[handle]->bdf == 1) return -1; hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignal = hdr->signal_write_sequence_pos; if(!hdr->datarecords) { if(!edfsignal) { error = edflib_write_edf_header(hdr); if(error) return error; } } sf = hdr->edfparam[edfsignal].smp_per_record; digmax = hdr->edfparam[edfsignal].dig_max; digmin = hdr->edfparam[edfsignal].dig_min; if(hdr->edf) { if((digmax != 0x7fff) || (digmin != -0x8000)) { for(i=0; idigmax) buf[i] = digmax; if(buf[i]wrbufsize < (sf * 3)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 3); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } for(i=0; idigmax) 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; } hdr->signal_write_sequence_pos++; if(hdr->signal_write_sequence_pos == hdr->edfsignals) { hdr->signal_write_sequence_pos = 0; if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; fflush(file); } return 0; } EDFLIB_API int edfwrite_digital_samples(int handle, int *buf) { int i, error, sf, digmax, digmin, edfsignal, value; FILE *file; edfhdrblock_t *hdr; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->edfsignals == 0) return -1; hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignal = hdr->signal_write_sequence_pos; if(!hdr->datarecords) { if(!edfsignal) { error = edflib_write_edf_header(hdr); if(error) return error; } } sf = hdr->edfparam[edfsignal].smp_per_record; digmax = hdr->edfparam[edfsignal].dig_max; digmin = hdr->edfparam[edfsignal].dig_min; if(hdr->edf) { if(hdr->wrbufsize < (sf * 2)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 2); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 2; } for(i=0; idigmax) 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; } else // BDF { if(hdr->wrbufsize < (sf * 3)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 3); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } for(i=0; idigmax) 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; } hdr->signal_write_sequence_pos++; if(hdr->signal_write_sequence_pos == hdr->edfsignals) { hdr->signal_write_sequence_pos = 0; if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; fflush(file); } return 0; } EDFLIB_API int edf_blockwrite_digital_samples(int handle, int *buf) { int i, j, error, sf, digmax, digmin, edfsignals, buf_offset, value; FILE *file; edfhdrblock_t *hdr; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->edfsignals == 0) return -1; if(hdrlist[handle]->signal_write_sequence_pos) return -1; hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(!hdr->datarecords) { error = edflib_write_edf_header(hdr); if(error) return error; } buf_offset = 0; for(j=0; jedfparam[j].smp_per_record; digmax = hdr->edfparam[j].dig_max; digmin = hdr->edfparam[j].dig_min; if(hdr->edf) { if(hdr->wrbufsize < (sf * 2)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 2); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 2; } for(i=0; idigmax) 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; } else // BDF { if(hdr->wrbufsize < (sf * 3)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 3); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } for(i=0; idigmax) 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; } buf_offset += sf; } if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; fflush(file); return 0; } EDFLIB_API int edf_blockwrite_digital_short_samples(int handle, short *buf) { int i, j, error, sf, digmax, digmin, edfsignals, buf_offset, value; FILE *file; edfhdrblock_t *hdr; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) 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]->bdf == 1) return -1; hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(!hdr->datarecords) { error = edflib_write_edf_header(hdr); if(error) { return error; } } buf_offset = 0; for(j=0; jedfparam[j].smp_per_record; digmax = hdr->edfparam[j].dig_max; digmin = hdr->edfparam[j].dig_min; if(hdr->edf) { if((digmax != 0x7fff) || (digmin != -0x8000)) { for(i=0; i digmax) { buf[i + buf_offset] = digmax; } if(buf[i + buf_offset] < digmin) { buf[i + buf_offset] = digmin; } } } if(fwrite(buf + buf_offset, sf * 2, 1, file) != 1) return -1; } else // BDF { if(hdr->wrbufsize < (sf * 3)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 3); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } for(i=0; idigmax) 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; } buf_offset += sf; } if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; fflush(file); return 0; } EDFLIB_API int edf_blockwrite_digital_3byte_samples(int handle, void *buf) { int j, error, edfsignals, total_samples=0; FILE *file; edfhdrblock_t *hdr; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) 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]->bdf != 1) return -1; hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(!hdr->datarecords) { error = edflib_write_edf_header(hdr); if(error) return error; } for(j=0; jedfparam[j].smp_per_record; } if(fwrite(buf, total_samples * 3, 1, file) != 1) return -1; if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; fflush(file); return 0; } EDFLIB_API int edfwrite_physical_samples(int handle, double *buf) { int i, error, sf, digmax, digmin, value, edfsignal; double bitvalue, phys_offset; FILE *file; edfhdrblock_t *hdr; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->edfsignals == 0) return -1; hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignal = hdr->signal_write_sequence_pos; if(!hdr->datarecords) { if(!edfsignal) { error = edflib_write_edf_header(hdr); if(error) return error; } } sf = hdr->edfparam[edfsignal].smp_per_record; digmax = hdr->edfparam[edfsignal].dig_max; digmin = hdr->edfparam[edfsignal].dig_min; bitvalue = hdr->edfparam[edfsignal].bitvalue; phys_offset = hdr->edfparam[edfsignal].offset; if(hdr->edf) { if(hdr->wrbufsize < (sf * 2)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 2); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 2; } for(i=0; idigmax) 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; } else // BDF { if(hdr->wrbufsize < (sf * 3)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 3); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } for(i=0; idigmax) 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; } hdr->signal_write_sequence_pos++; if(hdr->signal_write_sequence_pos == hdr->edfsignals) { hdr->signal_write_sequence_pos = 0; if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; fflush(file); } return 0; } EDFLIB_API int edf_blockwrite_physical_samples(int handle, double *buf) { int i, j, error, sf, digmax, digmin, edfsignals, buf_offset, value; double bitvalue, phys_offset; FILE *file; edfhdrblock_t *hdr; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->edfsignals == 0) return -1; if(hdrlist[handle]->signal_write_sequence_pos) return -1; hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(!hdr->datarecords) { error = edflib_write_edf_header(hdr); if(error) return error; } buf_offset = 0; for(j=0; jedfparam[j].smp_per_record; digmax = hdr->edfparam[j].dig_max; digmin = hdr->edfparam[j].dig_min; bitvalue = hdr->edfparam[j].bitvalue; phys_offset = hdr->edfparam[j].offset; if(hdr->edf) { if(hdr->wrbufsize < (sf * 2)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 2); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 2; } for(i=0; idigmax) 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; } else // BDF { if(hdr->wrbufsize < (sf * 3)) { free(hdr->wrbuf); hdr->wrbufsize = 0; hdr->wrbuf = (char *)malloc(sf * 3); if(hdr->wrbuf == NULL) return -1; hdr->wrbufsize = sf * 3; } for(i=0; idigmax) 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; } buf_offset += sf; } if(edflib_write_tal(hdr, file)) return -1; hdr->datarecords++; fflush(file); return 0; } static int edflib_write_edf_header(edfhdrblock_t *hdr) { int i, j, p, q, len, rest, edfsignals; char str[128]; struct tm *date_time; time_t elapsed_time; FILE *file; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(edfsignals<0) return EDFLIB_NO_SIGNALS; if(edfsignals>EDFLIB_MAXSIGNALS) return EDFLIB_TOO_MANY_SIGNALS; hdr->eq_sf = 1; hdr->recordsize = 0; hdr->total_annot_bytes = EDFLIB_ANNOTATION_BYTES * hdr->nr_annot_chns; for(i=0; iedfparam[i].smp_per_record<1) return EDFLIB_NO_SAMPLES_IN_RECORD; if(hdr->edfparam[i].dig_max==hdr->edfparam[i].dig_min) return EDFLIB_DIGMIN_IS_DIGMAX; if(hdr->edfparam[i].dig_maxedfparam[i].dig_min) return EDFLIB_DIGMAX_LOWER_THAN_DIGMIN; if(hdr->edfparam[i].phys_max==hdr->edfparam[i].phys_min) return EDFLIB_PHYSMIN_IS_PHYSMAX; 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) { hdr->eq_sf = 0; } } } if(hdr->edf) { hdr->recordsize *= 2; hdr->recordsize += hdr->total_annot_bytes; if(hdr->recordsize > (10 * 1024 * 1024)) /* datarecord size should not exceed 10MB for EDF */ { return EDFLIB_DATARECORD_SIZE_TOO_BIG; } /* if your application gets hit by this limitation, lower the value for the datarecord duration */ /* using the function edf_set_datarecord_duration() */ } else { hdr->recordsize *= 3; hdr->recordsize += hdr->total_annot_bytes; if(hdr->recordsize > (15 * 1024 * 1024)) /* datarecord size should not exceed 15MB for BDF */ { return EDFLIB_DATARECORD_SIZE_TOO_BIG; } /* if your application gets hit by this limitation, lower the value for the datarecord duration */ /* using the function edf_set_datarecord_duration() */ } for(i=0; iedfparam[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); if(hdr->edf) { fprintf(file, "0 "); } else { fprintf(file, "\xff" "BIOSEMI"); } p = 0; if(hdr->plus_birthdate[0]==0) { rest = 72; } else { rest = 62; } len = strlen(hdr->plus_patientcode); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } edflib_strlcpy(str, hdr->plus_patientcode, 128); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_sex[0]=='M') { fputc('M', file); } else { if(hdr->plus_sex[0]=='F') { fputc('F', file); } else { fputc('X', file); } } fputc(' ', file); p +=2; if(hdr->plus_birthdate[0]==0) { fputc('X', file); fputc(' ', file); p +=2; } else { fputc(hdr->plus_birthdate[0], file); fputc(hdr->plus_birthdate[1], file); fputc('-', file); q = edflib_atoi_nonlocalized(&(hdr->plus_birthdate[3])); switch(q) { case 1: fprintf(file, "JAN"); break; case 2: fprintf(file, "FEB"); break; case 3: fprintf(file, "MAR"); break; case 4: fprintf(file, "APR"); break; case 5: fprintf(file, "MAY"); break; case 6: fprintf(file, "JUN"); break; case 7: fprintf(file, "JUL"); break; case 8: fprintf(file, "AUG"); break; case 9: fprintf(file, "SEP"); break; case 10: fprintf(file, "OCT"); break; case 11: fprintf(file, "NOV"); break; case 12: fprintf(file, "DEC"); break; } fputc('-', file); fputc(hdr->plus_birthdate[6], file); fputc(hdr->plus_birthdate[7], file); fputc(hdr->plus_birthdate[8], file); fputc(hdr->plus_birthdate[9], file); fputc(' ', file); p += 12; } len = strlen(hdr->plus_patient_name); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } edflib_strlcpy(str, hdr->plus_patient_name, 128); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_patient_additional); if(len && rest) { if(len>rest) { len = rest; } edflib_strlcpy(str, hdr->plus_patient_additional, 128); edflib_latin1_to_ascii(str, len); str[len] = 0; p += fprintf(file, "%s", str); } for(; p<80; p++) { fputc(' ', file); } if(!hdr->startdate_year) { elapsed_time = time(NULL); date_time = localtime(&elapsed_time); hdr->startdate_year = date_time->tm_year + 1900; hdr->startdate_month = date_time->tm_mon + 1; hdr->startdate_day = date_time->tm_mday; hdr->starttime_hour = date_time->tm_hour; hdr->starttime_minute = date_time->tm_min; hdr->starttime_second = date_time->tm_sec % 60; } p = 0; p += fprintf(file, "Startdate %02u-", hdr->startdate_day); switch(hdr->startdate_month) { case 1 : fprintf(file, "JAN"); break; case 2 : fprintf(file, "FEB"); break; case 3 : fprintf(file, "MAR"); break; case 4 : fprintf(file, "APR"); break; case 5 : fprintf(file, "MAY"); break; case 6 : fprintf(file, "JUN"); break; case 7 : fprintf(file, "JUL"); break; case 8 : fprintf(file, "AUG"); break; case 9 : fprintf(file, "SEP"); break; case 10 : fprintf(file, "OCT"); break; case 11 : fprintf(file, "NOV"); break; case 12 : fprintf(file, "DEC"); break; } p += 3; fputc('-', file); p++; p += edflib_fprint_int_number_nonlocalized(file, hdr->startdate_year, 4, 0); fputc(' ', file); p++; rest = 42; len = strlen(hdr->plus_admincode); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } edflib_strlcpy(str, hdr->plus_admincode, 128); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_technician); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } edflib_strlcpy(str, hdr->plus_technician, 128); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_equipment); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } edflib_strlcpy(str, hdr->plus_equipment, 128); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_recording_additional); if(len && rest) { if(len>rest) { len = rest; } edflib_strlcpy(str, hdr->plus_recording_additional, 128); edflib_latin1_to_ascii(str, len); str[len] = 0; p += fprintf(file, "%s", str); } for(; p<80; p++) { fputc(' ', file); } fprintf(file, "%02u.%02u.%02u", hdr->startdate_day, hdr->startdate_month, (hdr->startdate_year % 100)); fprintf(file, "%02u.%02u.%02u", hdr->starttime_hour, hdr->starttime_minute, hdr->starttime_second); p = edflib_fprint_int_number_nonlocalized(file, (edfsignals + hdr->nr_annot_chns + 1) * 256, 0, 0); for(; p<8; p++) { fputc(' ', file); } if(hdr->edf) { fprintf(file, "EDF+C"); } else { fprintf(file, "BDF+C"); } for(i=0; i<39; i++) { fputc(' ', file); } fprintf(file, "-1 "); if(hdr->long_data_record_duration == EDFLIB_TIME_DIMENSION) { fprintf(file, "1 "); } else { edflib_snprint_number_nonlocalized(str, hdr->data_record_duration, 128); edflib_strlcat(str, " ", 128); str[8] = 0; fprintf(file, "%s", str); } p = edflib_fprint_int_number_nonlocalized(file, edfsignals + hdr->nr_annot_chns, 0, 0); for(; p<4; p++) { fputc(' ', file); } for(i=0; iedfparam[i].label); edflib_latin1_to_ascii(hdr->edfparam[i].label, len); for(j=0; jedfparam[i].label[j], file); } for(; j<16; j++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { if(hdr->edf) { fprintf(file, "EDF Annotations "); } else { fprintf(file, "BDF Annotations "); } } for(i=0; iedfparam[i].transducer); edflib_latin1_to_ascii(hdr->edfparam[i].transducer, len); for(j=0; jedfparam[i].transducer[j], file); } for(; j<80; j++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { for(i=0; i<80; i++) { fputc(' ', file); } } for(i=0; iedfparam[i].physdimension); edflib_latin1_to_ascii(hdr->edfparam[i].physdimension, len); for(j=0; jedfparam[i].physdimension[j], file); } for(; j<8; j++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { fprintf(file, " "); } for(i=0; iedfparam[i].phys_min, 128); for(; p<8; p++) { str[p] = ' '; } str[8] = 0; fprintf(file, "%s", str); } for(j=0; jnr_annot_chns; j++) { fprintf(file, "-1 "); } for(i=0; iedfparam[i].phys_max, 128); for(; p<8; p++) { str[p] = ' '; } str[8] = 0; fprintf(file, "%s", str); } for(j=0; jnr_annot_chns; j++) { fprintf(file, "1 "); } for(i=0; iedfparam[i].dig_min, 0, 0); for(; p<8; p++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { if(hdr->edf) { fprintf(file, "-32768 "); } else { fprintf(file, "-8388608"); } } for(i=0; iedfparam[i].dig_max, 0, 0); for(; p<8; p++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { if(hdr->edf) { fprintf(file, "32767 "); } else { fprintf(file, "8388607 "); } } for(i=0; iedfparam[i].prefilter); edflib_latin1_to_ascii(hdr->edfparam[i].prefilter, len); for(j=0; jedfparam[i].prefilter[j], file); } for(; j<80; j++) { fputc(' ', file); } } for(i=0; inr_annot_chns; i++) { for(j=0; j<80; j++) { fputc(' ', file); } } for(i=0; iedfparam[i].smp_per_record, 0, 0); for(; p<8; p++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { if(hdr->edf) { p = edflib_fprint_int_number_nonlocalized(file, EDFLIB_ANNOTATION_BYTES / 2, 0, 0); for(; p<8; p++) { fputc(' ', file); } } else { p = edflib_fprint_int_number_nonlocalized(file, EDFLIB_ANNOTATION_BYTES / 3, 0, 0); for(; p<8; p++) { fputc(' ', file); } } } for(i=0; i<(edfsignals * 32); i++) { fputc(' ', file); } for(i=0; i<(hdr->nr_annot_chns * 32); i++) { fputc(' ', file); } return 0; } EDFLIB_API int edf_set_label(int handle, int edfsignal, const char *label) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) 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); hdrlist[handle]->edfparam[edfsignal].label[16] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].label); return 0; } EDFLIB_API int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) 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); hdrlist[handle]->edfparam[edfsignal].physdimension[8] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].physdimension); return 0; } EDFLIB_API int edf_set_physical_maximum(int handle, int edfsignal, double phys_max) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) 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; return 0; } EDFLIB_API int edf_set_physical_minimum(int handle, int edfsignal, double phys_min) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) 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; return 0; } EDFLIB_API int edf_set_digital_maximum(int handle, int edfsignal, int dig_max) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; if(hdrlist[handle]->edf) { if(dig_max > 0x7fff) return -1; } else { if(dig_max > 0x7fffff) return -1; } hdrlist[handle]->edfparam[edfsignal].dig_max = dig_max; return 0; } EDFLIB_API int edf_set_digital_minimum(int handle, int edfsignal, int dig_min) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; if(hdrlist[handle]->edf) { if(dig_min < (-0x8000)) return -1; } else { if(dig_min < (-0x800000)) return -1; } hdrlist[handle]->edfparam[edfsignal].dig_min = dig_min; return 0; } EDFLIB_API int edf_set_patientname(int handle, const char *patientname) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_patient_name, patientname, 80); hdrlist[handle]->plus_patient_name[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patient_name); return 0; } EDFLIB_API int edf_set_patientcode(int handle, const char *patientcode) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_patientcode, patientcode, 80); hdrlist[handle]->plus_patientcode[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patientcode); return 0; } EDFLIB_API int edf_set_sex(int handle, int sex) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((sex<0)||(sex>1)) return -1; if(sex) { hdrlist[handle]->plus_sex[0] = 'M'; } else { hdrlist[handle]->plus_sex[0] = 'F'; } hdrlist[handle]->plus_sex[1] = 0; return 0; } EDFLIB_API int edf_set_gender(int handle, int sex) { return edf_set_sex(handle, sex); } 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]==NULL) 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) || (birthdate_day<1) || (birthdate_day>31)) { return -1; } sprintf(hdrlist[handle]->plus_birthdate, "%02i.%02i.%02i%02i", birthdate_day, birthdate_month, birthdate_year / 100, birthdate_year % 100); hdrlist[handle]->plus_birthdate[10] = 0; return 0; } EDFLIB_API int edf_set_patient_additional(int handle, const char *patient_additional) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_patient_additional, patient_additional, 80); hdrlist[handle]->plus_patient_additional[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patient_additional); return 0; } EDFLIB_API int edf_set_admincode(int handle, const char *admincode) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_admincode, admincode, 80); hdrlist[handle]->plus_admincode[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_admincode); return 0; } EDFLIB_API int edf_set_technician(int handle, const char *technician) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_technician, technician, 80); hdrlist[handle]->plus_technician[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_technician); return 0; } EDFLIB_API int edf_set_equipment(int handle, const char *equipment) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_equipment, equipment, 80); hdrlist[handle]->plus_equipment[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_equipment); return 0; } EDFLIB_API int edf_set_recording_additional(int handle, const char *recording_additional) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->plus_recording_additional, recording_additional, 80); hdrlist[handle]->plus_recording_additional[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_recording_additional); return 0; } 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)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; 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) || (starttime_minute<0) || (starttime_minute>59) || (starttime_second<0) || (starttime_second>59)) { return -1; } hdrlist[handle]->startdate_year = startdate_year; hdrlist[handle]->startdate_month = startdate_month; hdrlist[handle]->startdate_day = startdate_day; hdrlist[handle]->starttime_hour = starttime_hour; hdrlist[handle]->starttime_minute = starttime_minute; hdrlist[handle]->starttime_second = starttime_second; return 0; } EDFLIB_API int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description) { if(duration > 0LL) duration *= 100LL; return edfwrite_annotation_utf8_hr(handle, onset * 100LL, duration, description); } EDFLIB_API int edfwrite_annotation_utf8_hr(int handle, long long onset, long long duration, const char *description) { int i; edf_write_annotationblock_t *list_annot, *malloc_list; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) 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 = (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; } write_annotationslist[handle] = malloc_list; hdrlist[handle]->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ; } list_annot = write_annotationslist[handle] + hdrlist[handle]->annots_in_file; list_annot->onset = onset; list_annot->duration = duration; strncpy(list_annot->annotation, description, EDFLIB_WRITE_MAX_ANNOTATION_LEN); list_annot->annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0; for(i=0; ; i++) { if(list_annot->annotation[i] == 0) { break; } if(((unsigned char *)(list_annot->annotation))[i] < 32) { list_annot->annotation[i] = '.'; } } hdrlist[handle]->annots_in_file++; return 0; } EDFLIB_API int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description) { if(duration > 0LL) duration *= 100LL; return edfwrite_annotation_latin1_hr(handle, onset * 100LL, duration, description); } 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; char str[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1]; if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) 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 = (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; } write_annotationslist[handle] = malloc_list; hdrlist[handle]->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ; } list_annot = write_annotationslist[handle] + hdrlist[handle]->annots_in_file; list_annot->onset = onset; list_annot->duration = duration; strncpy(str, description, EDFLIB_WRITE_MAX_ANNOTATION_LEN); str[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0; edflib_latin12utf8(str, strlen(str)); strncpy(list_annot->annotation, str, EDFLIB_WRITE_MAX_ANNOTATION_LEN); list_annot->annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0; hdrlist[handle]->annots_in_file++; return 0; } static void edflib_remove_padding_trailing_spaces(char *str) { int i; while(str[0]==' ') { for(i=0; ; i++) { if(str[i]==0) { break; } str[i] = str[i+1]; } } for(i = strlen(str); i>0; i--) { if(str[i-1]==' ') { str[i-1] = 0; } else { break; } } } EDFLIB_API int edf_set_prefilter(int handle, int edfsignal, const char *prefilter) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->edfparam[edfsignal].prefilter, prefilter, 80); hdrlist[handle]->edfparam[edfsignal].prefilter[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].prefilter); return 0; } EDFLIB_API int edf_set_transducer(int handle, int edfsignal, const char *transducer) { if((handle<0)||(handle>=EDFLIB_MAXFILES)) return -1; if(hdrlist[handle]==NULL) return -1; if(!hdrlist[handle]->writemode) return -1; if(hdrlist[handle]->datarecords) return -1; if((edfsignal<0) || (edfsignal>=hdrlist[handle]->edfsignals)) return -1; if(hdrlist[handle]->datarecords) return -1; strncpy(hdrlist[handle]->edfparam[edfsignal].transducer, transducer, 80); hdrlist[handle]->edfparam[edfsignal].transducer[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].transducer); return 0; } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ static int edflib_fprint_int_number_nonlocalized(FILE *file, int q, int minimum, int sign) { int flag=0, z, i, j=0, base = 1000000000; if(minimum < 0) { minimum = 0; } if(minimum > 9) { flag = 1; } if(q < 0) { fputc('-', file); j++; base = -base; } else { if(sign) { fputc('+', file); j++; } } for(i=10; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { fputc('0' + z, file); j++; flag = 1; } base /= 10; } if(!flag) { fputc('0', file); j++; } return j; } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ static int edflib_fprint_ll_number_nonlocalized(FILE *file, long long q, int minimum, int sign) { int flag=0, z, i, j=0; long long base = 1000000000000000000LL; if(minimum < 0) { minimum = 0; } if(minimum > 18) { flag = 1; } if(q < 0LL) { fputc('-', file); j++; base = -base; } else { if(sign) { fputc('+', file); j++; } } for(i=19; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { fputc('0' + z, file); j++; flag = 1; } base /= 10LL; } if(!flag) { fputc('0', file); j++; } return j; } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ /* static int edflib_sprint_int_number_nonlocalized(char *str, int q, int minimum, int sign) { int flag=0, z, i, j=0, base = 1000000000; if(minimum < 0) { minimum = 0; } if(minimum > 9) { flag = 1; } if(q < 0) { str[j++] = '-'; q = -q; } else { if(sign) { str[j++] = '+'; } } for(i=10; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { str[j++] = '0' + z; flag = 1; } base /= 10; } if(!flag) { str[j++] = '0'; } str[j] = 0; return j; } */ /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ static int edflib_snprint_ll_number_nonlocalized(char *dest, long long q, int minimum, int sign, int sz) { int flag=0, z, i, j=0; long long base = 1000000000000000000LL; if(sz < 1) { return 0; } if(minimum < 0) { minimum = 0; } if(minimum > 18) { flag = 1; } if(q < 0LL) { dest[j++] = '-'; base = -base; } else { if(sign) { dest[j++] = '+'; } } if(j == sz) { dest[--j] = 0; return j; } for(i=19; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { dest[j++] = '0' + z; if(j == sz) { dest[--j] = 0; return j; } flag = 1; } base /= 10LL; } if(!flag) { dest[j++] = '0'; } if(j == sz) { dest[--j] = 0; return j; } dest[j] = 0; return j; } static int edflib_snprint_number_nonlocalized(char *dest, double val, int sz) { int flag=0, z, i, j=0, q, base = 1000000000; double var; if(sz < 1) return 0; q = (int)val; var = val - q; if(val < 0.0) { dest[j++] = '-'; if(q < 0) { base = -base; } } if(j == sz) { dest[--j] = 0; return j; } for(i=10; i; i--) { z = q / base; q %= base; if(z || flag) { dest[j++] = '0' + z; if(j == sz) { dest[--j] = 0; return j; } flag = 1; } base /= 10; } if(!flag) { dest[j++] = '0'; } if(j == sz) { dest[--j] = 0; return j; } base = 100000000; var *= (base * 10); q = (int)var; if(q < 0) { base = -base; } if(!q) { dest[j] = 0; return j; } dest[j++] = '.'; if(j == sz) { dest[--j] = 0; return j; } for(i=9; i; i--) { z = q / base; q %= base; dest[j++] = '0' + z; if(j == sz) { dest[--j] = 0; return j; } base /= 10; } dest[j] = 0; j--; for(; j>0; j--) { if(dest[j] == '0') { dest[j] = 0; } else { j++; break; } } return j; } static double edflib_atof_nonlocalized(const char *str) { int i=0, j, dot_pos=-1, decimals=0, sign=1, exp_pos=-1, exp_sign=1, exp_val=0; double value, value2=0.0; value = edflib_atoi_nonlocalized(str); while(str[i] == ' ') { i++; } if((str[i] == '+') || (str[i] == '-')) { if(str[i] == '-') { sign = -1; } i++; } for(; ; i++) { if(str[i] == 0) { break; } if((str[i] == 'e') || (str[i] == 'E')) { exp_pos = i; break; } if(((str[i] < '0') || (str[i] > '9')) && (str[i] != '.')) { break; } if(dot_pos >= 0) { if((str[i] >= '0') && (str[i] <= '9')) { decimals++; } else { break; } } if(str[i] == '.') { if(dot_pos < 0) { dot_pos = i; } } } if(decimals) { value2 = edflib_atoi_nonlocalized(str + dot_pos + 1) * sign; i = 1; while(decimals--) { i *= 10; } value2 /= i; value += value2; } if(exp_pos > 0) { i = exp_pos + 1; if(str[i]) { if(str[i] == '+') { i++; } else if(str[i] == '-') { exp_sign = -1; i++; } if(str[i]) { exp_val = edflib_atoi_nonlocalized(str + i); if(exp_val > 0) { for(j=0; j 0) { value *= 10; } else { value /= 10; } } } } } } return value; } static int edflib_atoi_nonlocalized(const char *str) { int i=0, value=0, sign=1; while(str[i] == ' ') { i++; } if((str[i] == '+') || (str[i] == '-')) { if(str[i] == '-') { sign = -1; } i++; } for( ; ; i++) { if(str[i] == 0) { break; } if((str[i] < '0') || (str[i] > '9')) { break; } value *= 10; value += ((str[i] - '0') * sign); } return value; } static int edflib_write_tal(edfhdrblock_t *hdr, FILE *file) { int p; char str[EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)]; p = edflib_snprint_ll_number_nonlocalized(str, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) / EDFLIB_TIME_DIMENSION, 0, 1, EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)); if((hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) || (hdr->starttime_offset)) { str[p++] = '.'; p += edflib_snprint_ll_number_nonlocalized(str + p, (hdr->datarecords * hdr->long_data_record_duration + hdr->starttime_offset) % EDFLIB_TIME_DIMENSION, 7, 0, (EDFLIB_ANNOTATION_BYTES * (EDFLIB_MAX_ANNOTATION_CHANNELS + 1)) - p); } str[p++] = 20; str[p++] = 20; for(; ptotal_annot_bytes; p++) { str[p] = 0; } if(fwrite(str, hdr->total_annot_bytes, 1, file) != 1) { return -1; } return 0; } static int edflib_strlcpy(char *dst, const char *src, int sz) { int srclen; sz--; srclen = strlen(src); if(srclen > sz) srclen = sz; memcpy(dst, src, srclen); dst[srclen] = 0; return srclen; } static int edflib_strlcat(char *dst, const char *src, int sz) { int srclen, dstlen; dstlen = strlen(dst); sz -= dstlen + 1; if(!sz) return dstlen; srclen = strlen(src); if(srclen > sz) srclen = sz; memcpy(dst + dstlen, src, srclen); dst[dstlen + srclen] = 0; return (dstlen + srclen); } edflib_124/test_edflib.c000644 001750 000144 00000017125 14415562626 015342 0ustar00guvusers000000 000000 /* ***************************************************************************** * * Copyright (c) 2009 - 2021 Teunis van Beelen * All rights reserved. * * Email: teuniz@protonmail.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY Teunis van Beelen ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Teunis van Beelen BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************** */ #include #include #include "edflib.h" #define SAMPLES_READ (200) int main(int argc, char *argv[]) { int i, hdl, channel, n; double *buf; edflib_hdr_t hdr; if(argc!=3) { printf("\nusage: test_edflib \n\n"); return(1); } channel = atoi(argv[2]); if(channel<1) { printf("\nsignalnumber must be > 0\n\n"); return(1); } if(edfopen_file_readonly(argv[1], &hdr, EDFLIB_READ_ALL_ANNOTATIONS)) { switch(hdr.filetype) { case EDFLIB_MALLOC_ERROR : printf("\nmalloc error\n\n"); break; case EDFLIB_NO_SUCH_FILE_OR_DIRECTORY : printf("\ncannot open file, no such file or directory\n\n"); break; case EDFLIB_FILE_CONTAINS_FORMAT_ERRORS : printf("\nthe file is not EDF(+) or BDF(+) compliant\n" "(it contains format errors)\n\n"); break; case EDFLIB_MAXFILES_REACHED : printf("\nto many files opened\n\n"); break; case EDFLIB_FILE_READ_ERROR : printf("\na read error occurred\n\n"); break; case EDFLIB_FILE_ALREADY_OPENED : printf("\nfile has already been opened\n\n"); break; default : printf("\nunknown error\n\n"); break; } return(1); } hdl = hdr.handle; if(channel>(hdr.edfsignals)) { printf("\nerror: file has %i signals and you selected signal %i\n\n", hdr.edfsignals, channel); edfclose_file(hdl); return(1); } channel--; printf("\nlibrary version: %i.%02i\n", edflib_version() / 100, edflib_version() % 100); printf("\ngeneral header:\n\n"); printf("filetype: %i\n", hdr.filetype); printf("edfsignals: %i\n", hdr.edfsignals); #ifdef WIN32 printf("file duration: %I64d seconds\n", hdr.file_duration / EDFLIB_TIME_DIMENSION); #else printf("file duration: %lli seconds\n", hdr.file_duration / EDFLIB_TIME_DIMENSION); #endif printf("startdate: %i-%i-%i\n", hdr.startdate_day, hdr.startdate_month, hdr.startdate_year); #ifdef WIN32 printf("starttime: %i:%02i:%02i.%07I64d\n", hdr.starttime_hour, hdr.starttime_minute, hdr.starttime_second, hdr.starttime_subsecond); #else printf("starttime: %i:%02i:%02i.%07lli\n", hdr.starttime_hour, hdr.starttime_minute, hdr.starttime_second, hdr.starttime_subsecond); #endif printf("patient: %s\n", hdr.patient); printf("recording: %s\n", hdr.recording); printf("patientcode: %s\n", hdr.patientcode); printf("sex: %s\n", hdr.sex); printf("birthdate: %s\n", hdr.birthdate); printf("patient_name: %s\n", hdr.patient_name); printf("patient_additional: %s\n", hdr.patient_additional); printf("admincode: %s\n", hdr.admincode); printf("technician: %s\n", hdr.technician); printf("equipment: %s\n", hdr.equipment); printf("recording_additional: %s\n", hdr.recording_additional); printf("datarecord duration: %f seconds\n", ((double)hdr.datarecord_duration) / EDFLIB_TIME_DIMENSION); #ifdef WIN32 printf("number of datarecords in the file: %I64d\n", hdr.datarecords_in_file); printf("number of annotations in the file: %I64d\n", hdr.annotations_in_file); #else printf("number of datarecords in the file: %lli\n", hdr.datarecords_in_file); printf("number of annotations in the file: %lli\n", hdr.annotations_in_file); #endif printf("\nsignal parameters:\n\n"); printf("label: %s\n", hdr.signalparam[channel].label); #ifdef WIN32 printf("samples in file: %I64d\n", hdr.signalparam[channel].smp_in_file); #else printf("samples in file: %lli\n", hdr.signalparam[channel].smp_in_file); #endif printf("samples in datarecord: %i\n", hdr.signalparam[channel].smp_in_datarecord); printf("physical maximum: %f\n", hdr.signalparam[channel].phys_max); printf("physical minimum: %f\n", hdr.signalparam[channel].phys_min); printf("digital maximum: %i\n", hdr.signalparam[channel].dig_max); printf("digital minimum: %i\n", hdr.signalparam[channel].dig_min); printf("physical dimension: %s\n", hdr.signalparam[channel].physdimension); printf("prefilter: %s\n", hdr.signalparam[channel].prefilter); printf("transducer: %s\n", hdr.signalparam[channel].transducer); printf("samplefrequency: %f\n", ((double)hdr.signalparam[channel].smp_in_datarecord / (double)hdr.datarecord_duration) * EDFLIB_TIME_DIMENSION); edflib_annotation_t annot; printf("\n"); for(i=0; i