/* ***************************************************************************** * * 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 choosen but, if possible, use values from * 0.1 to 1 second for easier handling. Just make sure that the total size of one datarecord, expressed in bytes, does not exceed 10MByte (15MBytes for BDF(+)). * * The RECOMMENDATION of a maximum datarecordsize of 61440 bytes in the EDF and EDF+ specification was 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 samplingrates * 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 foreward compatible with ASCII). * * The samplefrequency 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 compatibel 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 hided. * 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 timevalues in variables of type long long int. * In order not to lose the subsecond precision, all timevalues are scaled with a scaling factor: 10000000. * This will limit the timeresolution to 100 nanoSeconds. To calculate the amount of seconds, divide * the timevalue by 10000000 or use the macro EDFLIB_TIME_DIMENSION which is declared in edflib.h. * The following variables 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 #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 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 samplerate */ char physdimension[9]; /* physical dimension (uV, bpm, mA, etc.), null-terminated string */ char prefilter[81]; /* null-terminated string */ char transducer[81]; /* null-terminated string */ }; 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, a value of -10000000 means unused (duration not present) */ char duration[16]; /* duration time, this is a null-terminated ASCII text-string */ char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; /* description of the event in UTF-8, this is a null terminated string */ }; struct edf_hdr_struct{ /* this structure contains all the relevant EDF header info and will be filled when calling the function edf_open_file_readonly() */ int handle; /* a handle (identifier) used to distinguish the different files */ int filetype; /* 0: EDF, 1: 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 patientfield of header, is always empty when filetype is EDFPLUS or BDFPLUS */ char recording[81]; /* null-terminated string, contains recordingfield of header, is always empty when filetype is EDFPLUS or BDFPLUS */ char patientcode[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char gender[16]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char 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 */ struct edf_param_struct signalparam[EDFLIB_MAXSIGNALS]; /* array of structs which contain the relevant signal parameters */ }; /***************** the following functions are used to read files **************************/ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *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 errorcode will be set in the member "filetype" of struct edf_hdr_struct * This function is required if you want to read a file */ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf); /* reads n samples from edfsignal, starting from the current sample position indicator, into buf (edfsignal starts at 0) * the values are converted to their physical values e.g. microVolts, beats per minute, etc. * bufsize should be equal to or bigger than sizeof(double[n]) * the sample position indicator will be increased with the amount of samples read * returns the amount of samples read (this can be less than n or zero!) * or -1 in case of an error */ int edfread_digital_samples(int handle, int edfsignal, int n, int *buf); /* reads n samples from edfsignal, starting from the current sample position indicator, into buf (edfsignal starts at 0) * the values are the "raw" digital values * bufsize should be equal to or bigger than sizeof(int[n]) * the sample position indicator will be increased with the amount of samples read * returns the amount of samples read (this can be less than n or zero!) * or -1 in case of an error */ long long edfseek(int handle, int edfsignal, long long offset, int whence); /* The edfseek() function sets the sample position indicator for the edfsignal pointed to by edfsignal. * The new position, measured in samples, is obtained by adding offset samples to the position specified by whence. * If whence is set to EDFSEEK_SET, EDFSEEK_CUR, or EDFSEEK_END, the offset is relative to the start of the file, * the current position indicator, or end-of-file, respectively. * Returns the current offset. Otherwise, -1 is returned. * note that every signal has it's own independent sample position indicator and edfseek() affects only one of them */ long long edftell(int handle, int edfsignal); /* The edftell() function obtains the current value of the sample position indicator for the edfsignal pointed to by edfsignal. * Returns the current offset. Otherwise, -1 is returned * note that every signal has it's own independent sample position indicator and edftell() affects only one of them */ void edfrewind(int handle, int edfsignal); /* The edfrewind() function sets the sample position indicator for the edfsignal pointed to by edfsignal to the beginning of the file. * It is equivalent to: (void) edfseek(int handle, int edfsignal, 0LL, EDFSEEK_SET) * note that every signal has it's own independent sample position indicator and edfrewind() affects only one of them */ int edf_get_annotation(int handle, int n, struct edf_annotation_struct *annot); /* Fills the edf_annotation_struct with the annotation n, returns 0 on success, otherwise -1 * The string that describes the annotation/event is encoded in UTF-8 * To obtain the number of annotations in a file, check edf_hdr_struct -> annotations_in_file. * returns 0 on success or -1 in case of an error */ /***************** the following functions are used in read and write mode **************************/ int edfclose_file(int handle); /* closes (and in case of writing, finalizes) the file * returns -1 in case of an error, 0 on success * this function MUST be called when you are finished reading or writing * This function is required after reading or writing. Failing to do so will cause * unnessecary memory usage and in case of writing it will cause a corrupted and incomplete file */ int edflib_version(void); /* Returns the version number of this library, multiplied by hundred. if version is "1.00" than it will return 100 */ int edflib_is_file_used(const char *path); /* returns 1 if the file is used, either for reading or writing, otherwise returns 0 */ int edflib_get_number_of_open_files(void); /* returns the number of open files, either for reading or writing */ 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 **************************/ int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals); /* opens an new file for writing. warning, an already existing file with the same name will be silently overwritten without advance warning! * path is a null-terminated string containing the path and name of the file * filetype must be EDFLIB_FILETYPE_EDFPLUS or EDFLIB_FILETYPE_BDFPLUS * returns a handle on success, you need this handle for the other functions * in case of an error it returns a negative number corresponding to one of the following values: * EDFLIB_MALLOC_ERROR * EDFLIB_NO_SUCH_FILE_OR_DIRECTORY * EDFLIB_MAXFILES_REACHED * EDFLIB_FILE_ALREADY_OPENED * EDFLIB_NUMBER_OF_SIGNALS_INVALID * EDFLIB_ARCH_ERROR * This function is required if you want to write a file (or use edfopen_file_writeonly_with_params()) */ int edfopen_file_writeonly_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 samplefrequency of all signals. (In reality, it sets the number of samples per datarecord which equals the samplefrequency 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()) */ int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency); /* Sets the samplefrequency of signal edfsignal. In reality, it sets the number of samples in a datarecord * which equals the samplefrequency only when the datarecords have a duration of 1 second. * The effective samplefrequency 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 writemode and before the first sample write action */ int edf_set_physical_maximum(int handle, int edfsignal, double phys_max); /* Sets the maximum physical value of signal edfsignal. (the value of the input of the ADC when the output equals the value of "digital maximum") * 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 writemode and before the first sample write action */ int edf_set_physical_minimum(int handle, int edfsignal, double phys_min); /* Sets the minimum physical value of signal edfsignal. (the value of the input of the ADC when the output equals the value of "digital minimum") * 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 writemode and before the first sample write action */ int edf_set_digital_maximum(int handle, int edfsignal, int dig_max); /* Sets the maximum digital value of signal edfsignal. The maximum value is 32767 for EDF+ and 8388607 for BDF+ * 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 writemode * and before the first sample write action */ int edf_set_digital_minimum(int handle, int edfsignal, int dig_min); /* Sets the minimum digital value of signal edfsignal. The minimum value is -32768 for EDF+ and -8388608 for BDF+ * 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 writemode * and before the first sample write action */ int edf_set_label(int handle, int edfsignal, const char *label); /* Sets the label (name) of signal edfsignal. ("FP1", "SaO2", etc.) * label is a pointer to a NULL-terminated ASCII-string containing the label (name) of the signal edfsignal * Returns 0 on success, otherwise -1 * This function is recommended for every signal when you want to write a file * and can be called only after opening a file in writemode and before the first sample write action */ int edf_set_prefilter(int handle, int edfsignal, const char *prefilter); /* Sets the prefilter of signal edfsignal ("HP:0.1Hz", "LP:75Hz N:50Hz", etc.). * prefilter is a pointer to a NULL-terminated ASCII-string containing the prefilter text of the signal edfsignal * Returns 0 on success, otherwise -1 * This function is optional and can be called only after opening a file in writemode and before * the first sample write action */ int edf_set_transducer(int handle, int edfsignal, const char *transducer); /* Sets the transducer of signal edfsignal ("AgAgCl cup electrodes", etc.). * transducer is a pointer to a NULL-terminated ASCII-string containing the transducer text of the signal edfsignal * Returns 0 on success, otherwise -1 * This function is optional and can be called only after opening a file in writemode and before * the first sample write action */ int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim); /* Sets the physical dimension (unit) of signal edfsignal. ("uV", "BPM", "mA", "Degr.", etc.) * phys_dim is a pointer to a NULL-terminated ASCII-string containing the physical dimension of the signal edfsignal * Returns 0 on success, otherwise -1 * This function is recommended for every signal when you want to write a file * and can be called only after opening a file in writemode and before the first sample write action */ int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day, int starttime_hour, int starttime_minute, int starttime_second); /* Sets the startdate and starttime. * year: 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 writemode * 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. */ 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 */ int edf_set_patientcode(int handle, const char *patientcode); /* Sets the patientcode. patientcode is a pointer to a null-terminated ASCII-string. * Returns 0 on success, otherwise -1 * This function is optional and can be called only after opening a file in writemode * and before the first sample write action */ int edf_set_gender(int handle, int gender); /* Sets the gender. 1 is male, 0 is female. * Returns 0 on success, otherwise -1 * This function is optional and can be called only after opening a file in writemode * and before the first sample write action */ int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day); /* Sets the birthdate. * year: 1800 - 3000, month: 1 - 12, day: 1 - 31 * This function is optional * Returns 0 on success, otherwise -1 * This function is optional and can be called only after opening a file in writemode * and before the first sample write action */ int edf_set_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 */ 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 */ int edf_set_technician(int handle, const char *technician); /* Sets the technicians name. technician is a pointer to a null-terminated ASCII-string. * Returns 0 on success, otherwise -1 * This function is optional and can be called only after opening a file in writemode * and before the first sample write action */ int edf_set_equipment(int handle, const char *equipment); /* Sets the name of the equipment used during the aquisition. equipment is a pointer to a null-terminated ASCII-string. * Returns 0 on success, otherwise -1 * This function is optional and can be called only after opening a file in writemode * and before the first sample write action */ 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 */ int edfwrite_physical_samples(int handle, double *buf); /* Writes n physical samples (uV, mA, Ohm) from *buf belonging to one signal * where n is the samplefrequency of that signal. * The physical samples will be converted to digital samples using the * values of physical maximum, physical minimum, digital maximum and digital minimum * The number of samples written is equal to the samplefrequency of the signal * Size of buf should be equal to or bigger than sizeof(double[samplefrequency]) * Call this function for every signal in the file. The order is important! * When there are 4 signals in the file, the order of calling this function * must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. * Returns 0 on success, otherwise -1 */ int edf_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 */ 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 */ int edfwrite_digital_samples(int handle, int *buf); /* Writes n "raw" digital samples from *buf belonging to one signal * where n is the samplefrequency of that signal. * The 16 (or 24 in case of BDF) least significant bits of the sample will be written to the * file without any conversion. * The number of samples written is equal to the samplefrequency of the signal * Size of buf should be equal to or bigger than sizeof(int[samplefrequency]) * Call this function for every signal in the file. The order is important! * When there are 4 signals in the file, the order of calling this function * must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. * Returns 0 on success, otherwise -1 */ int edf_blockwrite_digital_3byte_samples(int handle, void *buf); /* Writes "raw" digital samples from *buf. * buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. * where n is the samplefrequency of that signal. * One block equals one second. One sample equals 3 bytes, order is little endian (least significant byte first) * Encoding is second's complement, most significant bit of most significant byte is the sign-bit * The samples will be written to the file without any conversion. * Because the size of a 3-byte sample is 24-bit, this function can only be used when writing a BDF file * The number of samples written is equal to the sum of the samplefrequencies of all signals. * Size of buf should be equal to or bigger than: the sum of the samplefrequencies of all signals x 3 bytes * Returns 0 on success, otherwise -1 */ int edf_blockwrite_digital_short_samples(int handle, short *buf); /* Writes "raw" digital samples from *buf. * buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. * where n is the samplefrequency of that signal. * One block equals one second. * The samples will be written to the file without any conversion. * Because the size of a short is 16-bit, do not use this function with BDF (24-bit) * The number of samples written is equal to the sum of the samplefrequencies of all signals. * Size of buf should be equal to or bigger than sizeof(short) multiplied by the sum of the samplefrequencies of all signals * Returns 0 on success, otherwise -1 */ int edf_blockwrite_digital_samples(int handle, int *buf); /* Writes "raw" digital samples from *buf. * buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. * where n is the samplefrequency of that signal. * One block equals one second. * The 16 (or 24 in case of BDF) least significant bits of the sample will be written to the * file without any conversion. * The number of samples written is equal to the sum of the samplefrequencies of all signals. * Size of buf should be equal to or bigger than sizeof(int) multiplied by the sum of the samplefrequencies of all signals * Returns 0 on success, otherwise -1 */ int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description); /* writes an annotation/event to the file * onset is relative to the start of the file * onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! * for example: 34.071 seconds must be written as 340710 * if duration is unknown or not applicable: set a negative number (-1) * description is a null-terminated UTF8-string containing the text that describes the event * This function is optional and can be called only after opening a file in writemode * and before closing the file */ int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description); /* writes an annotation/event to the file * onset is relative to the start of the file * onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! * for example: 34.071 seconds must be written as 340710 * if duration is unknown or not applicable: set a negative number (-1) * description is a null-terminated Latin1-string containing the text that describes the event * This function is optional and can be called only after opening a file in writemode * and before closing the file */ int edf_set_datarecord_duration(int handle, int duration); /* Sets the datarecord duration. The default value is 1 second. * ATTENTION: the argument "duration" is expressed in units of 10 microSeconds! * So, if you want to set the datarecord duration to 0.1 second, you must give * the argument "duration" a value of "10000". * This function is optional, normally you don't need to change the default value. * The datarecord duration must be in the range 0.001 to 60 seconds. * Returns 0 on success, otherwise -1 * This function is NOT REQUIRED but can be called after opening a * file in writemode and before the first sample write action. * This function can be used when you want to use a samplerate * which is not an integer. For example, if you want to use a samplerate of 0.5 Hz, * set the samplefrequency to 5 Hz and the datarecord duration to 10 seconds, * or set the samplefrequency to 1 Hz and the datarecord duration to 2 seconds. * Do not use this function if not necessary. */ int edf_set_micro_datarecord_duration(int handle, int duration); /* Sets the datarecord duration to a very small value. * ATTENTION: the argument "duration" is expressed in units of 1 microSecond! * This function is optional, normally you don't need to change the default value. * The datarecord duration must be in the range 1 to 9999 micro-seconds. * Returns 0 on success, otherwise -1 * This function is NOT REQUIRED but can be called after opening a * file in writemode and before the first sample write action. * This function can be used when you want to use a very high samplerate. * For example, if you want to use a samplerate of 5 GHz, * set the samplefrequency to 5000 Hz and the datarecord duration to 1 micro-second. * Do not use this function if not necessary. * This function was added to accommodate for high speed ADC's e.g. Digital Sampling Oscilloscopes */ int edf_set_number_of_annotation_signals(int handle, int annot_signals); /* Sets the number of annotation signals. The default value is 1 * This function is optional and can be called only after opening a file in writemode * and before the first sample write action * Normally you don't need to change the default value. Only when the number of annotations * you want to write is higher than the number of datarecords in the recording, you can use * this function to increase the storage space for annotations * Minimum is 1, maximum is 64 * Returns 0 on success, otherwise -1 */ int edf_set_subsecond_starttime(int handle, int subsecond); /* Sets the subsecond starttime expressed in units of 100 nanoSeconds * Valid range is 0 to 9999999 inclusive. Default is 0 * This function is optional and can be called only after opening a file in writemode * and before the first sample write action * Returns 0 on success, otherwise -1 * It is strongly recommended to use a maximum resolution of no more than 100 micro-Seconds. * e.g. use 1234000 to set a starttime offset of 0.1234 seconds (instead of 1234567) * in other words, leave the last 3 digits at zero */ #ifdef __cplusplus } /* extern "C" */ #endif #endif