kopia lustrzana https://gitlab.com/Teuniz/DSRemote
1264 wiersze
51 KiB
C
1264 wiersze
51 KiB
C
/*
|
|
*****************************************************************************
|
|
*
|
|
* Copyright (c) 2009 - 2025 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.
|
|
*
|
|
*****************************************************************************
|
|
*/
|
|
|
|
/**
|
|
* @file edflib.h
|
|
*
|
|
* In EDF, the resolution (or sensitivity) (e.g. uV/bit) and offset are stored using four parameters:<br>
|
|
* digital maximum and minimum, and physical maximum and minimum.<br>
|
|
* Here, digital means the raw data coming from a sensor or ADC. Physical means the units like uV.<br>
|
|
* The resolution in units per least significant bit is calculated as follows:<br>
|
|
*
|
|
* units per bit = (physical max - physical min) / (digital max - digital min)<br>
|
|
*
|
|
* The digital offset is calculated as follows:<br>
|
|
*
|
|
* offset = (physical max / units per bit) - digital max<br>
|
|
*
|
|
* For a better explanation about the relation between digital data and physical data,<br>
|
|
* read the document "Coding Schemes Used with Data Converters" (PDF):<br>
|
|
*
|
|
* https://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=sbaa042<br>
|
|
*
|
|
* An EDF file usually contains multiple so-called datarecords. One datarecord usually has a duration of one second (this is the default but it's not mandatory).<br>
|
|
* 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<br>
|
|
* 0.1 to 1 second for easier handling. Just make sure that the total size of one datarecord, expressed in bytes, does not exceed 10 MByte (15 MBytes for BDF(+)).<br>
|
|
*
|
|
* The <b>recommendation</b> of a maximum datarecord size of 61440 bytes in the EDF(+) specification was useful in the time people were still using DOS as their main operating system.<br>
|
|
* Using DOS and fast (near) pointers (16-bit pointers), the maximum allocatable block of memory was 64KByte.<br>
|
|
* This is not a concern anymore so the maximum datarecord size now is limited to 10 MByte for EDF(+) and 15 MByte for BDF(+). This helps to accommodate for higher sampling rates<br>
|
|
* used by modern Analog to Digital Converters.<br>
|
|
*
|
|
* EDF header character encoding: The EDF specification says that only (printable) ASCII characters are allowed.<br>
|
|
* When writing the header info, EDFlib will assume you are using Latin1 encoding and it will automatically convert<br>
|
|
* characters with accents, umlauts, tilde, etc. to their "normal" equivalent without the accent/umlaut/tilde/etc.<br>
|
|
* in order to create a valid EDF file.<br>
|
|
* The description of an EDF+ annotation/event/trigger on the other hand, is always encoded in UTF-8 (which is forward compatible with ASCII).<br>
|
|
*
|
|
* The sample frequency of a signal is calculated as follows: sf = (smp_in_datarecord * EDFLIB_TIME_DIMENSION) / datarecord_duration<br>
|
|
*
|
|
* Annotation signals<br>
|
|
* ==================<br>
|
|
*
|
|
* EDF+ and BDF+ store the annotations/events/triggers in one or more signals (in order to be backwards compatible with EDF and BDF)<br>
|
|
* and they can appear anywhere in the list of signals.<br>
|
|
* The numbering of the signals in the file is zero based (starts at 0). Signals used for annotations are skipped by EDFlib.<br>
|
|
* This means that the annotationsignal(s) in the file are hidden.<br>
|
|
* Use the function edf_get_annotation() to get the annotations.<br>
|
|
*
|
|
* So, when a file contains 7 signals and the third and fifth signal are annotation signals, the library will<br>
|
|
* report that there are only 5 signals in the file.<br>
|
|
* The library will "map" the (zero-based) signal numbers as follows: 0->0, 1->1, 2->3, 3->4, 4->6.<br>
|
|
* This way you don't need to worry about which signals are annotationsignals, the library will take care of it.<br>
|
|
*
|
|
* How the library stores time values<br>
|
|
* ==================================<br>
|
|
*
|
|
* To avoid rounding errors and to be able to compare values, the library stores some time values in variables of type long long int.<br>
|
|
* In order not to lose the sub-second precision, all time values are scaled with a scaling factor: 10000000.<br>
|
|
* This will limit the time resolution to 100 nanoseconds. To calculate the amount of seconds, divide<br>
|
|
* the timevalue by 10000000 or use the macro EDFLIB_TIME_DIMENSION which is declared in edflib.h.<br>
|
|
* The following variables use this scaling when you open a file in read mode: "file_duration", "starttime_subsecond" and "onset".<br>
|
|
*
|
|
* EDFlib and thread-safety<br>
|
|
* ========================<br>
|
|
* The following functions are always MT-unsafe:<br>
|
|
* edfopen_file_readonly() (race condition)<br>
|
|
* edfclose_file() (race condition)<br>
|
|
* edflib_get_handle() (race condition)<br>
|
|
*
|
|
* When writing to or reading from the same file, all EDFlib functions are MT-unsafe (race condition).<br>
|
|
*
|
|
* When accessing EDFlib from different threads, use a mutex.<br>
|
|
*
|
|
* For more info about the EDF and EDF+ format, visit: https://edfplus.info/specs/<br>
|
|
*
|
|
* For more info about the BDF and BDF+ format, visit: https://www.teuniz.net/edfbrowser/bdfplus%20format%20description.html<br>
|
|
*
|
|
*/
|
|
|
|
|
|
/* compile with options "-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE" */
|
|
|
|
|
|
#ifndef EDFLIB_INCLUDED
|
|
#define EDFLIB_INCLUDED
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
|
|
/*
|
|
* 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 (4096)
|
|
#define EDFLIB_MAX_ANNOTATION_LEN (512)
|
|
|
|
#define EDFSEEK_SET (0)
|
|
#define EDFSEEK_CUR (1)
|
|
#define EDFSEEK_END (2)
|
|
|
|
#define EDF_ANNOT_IDX_POS_END (0)
|
|
#define EDF_ANNOT_IDX_POS_MIDDLE (1)
|
|
#define EDF_ANNOT_IDX_POS_START (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 (https://www.teuniz.net/edfbrowser/),
|
|
it will give you full details about the cause of the error. It can also fix most errors. */
|
|
#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
|
|
|
|
/**
|
|
* This structure contains the signal parameters.
|
|
*/
|
|
typedef struct edf_param_struct
|
|
{
|
|
char label[17]; /*!< Label (name) of the signal, null-terminated string. */
|
|
long long smp_in_file; /*!< Number of samples 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 samplesin a datarecord, if the datarecord has a duration of one second (default), then it equals the sample rate. */
|
|
char physdimension[9]; /*!< Physical dimension (unit, e.g. uV, bpm, mA, etc.), null-terminated string. */
|
|
char prefilter[81]; /*!< Prefilter settings, null-terminated string. */
|
|
char transducer[81]; /*!< Transducer (sensor), null-terminated string. */
|
|
} edflib_param_t;
|
|
|
|
/**
|
|
* This structure is used for annotations/events/triggers.
|
|
*/
|
|
typedef struct edf_annotation_struct
|
|
{
|
|
long long onset; /*!< Onset time of the event, expressed in units of 100 nanoseconds and relative to the start of the recording. */
|
|
long long duration_l; /*!< Duration, expressed in units of 100 nanoseconds, if less than zero: unused or not applicable. */
|
|
char duration[20]; /*!< Duration, expressed in seconds, this is a null-terminated ASCII string. */
|
|
char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; /*!< Description of the annotation/event/trigger, this is a null-terminated UTF8 string. */
|
|
} edflib_annotation_t;
|
|
|
|
/**
|
|
* This structure contains the general header info and parameters. It will be filled when calling the function edfopen_file_readonly().
|
|
*/
|
|
typedef struct edf_hdr_struct
|
|
{
|
|
int handle; /*!< A handle (identifier) used to distinguish the different files or -1 in case of an error. */
|
|
int filetype; /*!< 0: EDF, 1: EDF+, 2: BDF, 3: BDF+, a negative number indicates an error code. */
|
|
int edfsignals; /*!< Number of 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; /*!< Startdate: day: 1 - 31 */
|
|
int startdate_month; /*!< Startdate: month: 1 - 12 */
|
|
int startdate_year; /*!< Startdate: year: 1985 - 2084 */
|
|
long long starttime_subsecond; /*!< Starttime subsecond expressed in units of 100 nanoseconds. Is always less than 10000000 (one second). Only used by EDF+ and BDF+. */
|
|
int starttime_second; /*!< Starttime: second: 0 - 59 */
|
|
int starttime_minute; /*!< Starttime: minute: 0 - 59 */
|
|
int starttime_hour; /*!< Starttime: hour: 0 - 23 */
|
|
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 \p sex. */
|
|
#else
|
|
char gender[16]; /*!< Deprecated, use \p sex. */
|
|
#endif
|
|
char birthdate[16]; /*!< Null-terminated string, is always empty when filetype is EDF or BDF. */
|
|
int birthdate_day; /*!< Birthdate: day: 1 - 31 (zero in case of EDF or BDF). */
|
|
int birthdate_month; /*!< Birthdate: month: 1 - 12 (zero in case of EDF or BDF). */
|
|
int birthdate_year; /*!< Birthdate: year: 1800 - 3000 (zero in case of EDF or BDF). */
|
|
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/events/triggers in the file. */
|
|
edflib_param_t signalparam[EDFLIB_MAXSIGNALS]; /*!< array of structs containing the signal parameters. */
|
|
} edflib_hdr_t;
|
|
|
|
/***************** the following functions are used to read files **************************/
|
|
|
|
/**
|
|
* Opens an existing file for reading.
|
|
*
|
|
* @param[in] path
|
|
* null-terminated string containing the \p path to the file
|
|
*
|
|
* @param[out] edfhdr
|
|
* pointer to an \p edflib_hdr_t struct, all fields in this struct will be overwritten,
|
|
* it will be filled with all the relevant header- and signalinfo/parameters
|
|
*
|
|
* @param[in] read_annotations
|
|
* Must have one of the following values:
|
|
* - EDFLIB_DO_NOT_READ_ANNOTATIONS annotations will not be read (this can save 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
|
|
*
|
|
* @return
|
|
* 0 on success, in case of an error it returns -1 and an error code will be set in the member "filetype" of edfhdr.
|
|
* This function is required if you want to read a file
|
|
*
|
|
* In case of a file format error (-3), try to open the file with EDFbrowser: https://www.teuniz.net/edfbrowser/
|
|
* It will give you full details about the cause of the error and it can also fix most errors.
|
|
*/
|
|
EDFLIB_API int edfopen_file_readonly(const char *path, edflib_hdr_t *edfhdr, int read_annotations);
|
|
|
|
/**
|
|
* Reads \p n samples from \p edfsignal, starting from the current sample position indicator, into \p buf (edfsignal starts at 0).
|
|
* The values are converted to their physical values e.g. microVolts, beats per minute, etc.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
* @param[in] n
|
|
* Number of samples to read. The sample position indicator will be increased with the same amount.
|
|
* @param[out] buf
|
|
* Pointer to a buffer, size must be equal to, or bigger than, sizeof(double[n])
|
|
*
|
|
* @return
|
|
* The number of samples read (this can be less than \p n or zero!) or -1 in case of an error
|
|
*/
|
|
EDFLIB_API int edfread_physical_samples(int handle, int edfsignal, int n, double *buf);
|
|
|
|
/**
|
|
* Reads \p n samples from \p edfsignal, starting from the current sample position indicator, into \p buf (edfsignal starts at 0).
|
|
* The values are the "raw" digital values (e.g. from an ADC).
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
* @param[in] n
|
|
* Number of samples to read. The sample position indicator will be increased with the same amount.
|
|
* @param[out] buf
|
|
* Pointer to a buffer, size must be equal to, or bigger than, sizeof(double[n])
|
|
*
|
|
* @return
|
|
* The number of samples read (this can be less than \p n or zero!) or -1 in case of an error
|
|
*/
|
|
EDFLIB_API int edfread_digital_samples(int handle, int edfsignal, int n, int *buf);
|
|
|
|
/**
|
|
* Sets the sample position indicator for the edfsignal pointed to by \p edfsignal.
|
|
* The new position, measured in samples, is obtained by adding offset samples to the position specified by \p whence.
|
|
* If \p 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.
|
|
* Note that every signal has it's own independent sample position indicator and \p edfseek() affects only one of them.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
* @param[in] offset
|
|
* Offset measured in samples.
|
|
* @param[in] whence
|
|
* Reference for \p offset:
|
|
* - EDFSEEK_SET start of the file
|
|
* - EDFSEEK_CUR current position
|
|
* - EDFSEEK_END end of the file
|
|
*
|
|
* @return
|
|
* The current offset or -1 in case of an error.
|
|
*/
|
|
EDFLIB_API long long edfseek(int handle, int edfsignal, long long offset, int whence);
|
|
|
|
/**
|
|
* Obtains the current value of the sample position indicator for the edfsignal pointed to by \p edfsignal.
|
|
* Note that every signal has it's own independent sample position indicator and \p edftell() affects only one of them.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @return
|
|
* The current offset or -1 in case of an error.
|
|
*/
|
|
EDFLIB_API long long edftell(int handle, int edfsignal);
|
|
|
|
/**
|
|
* Sets the sample position indicator for the edfsignal pointed to by \p edfsignal to the beginning of the file.
|
|
* It is equivalent to: \p edfseek(handle, edfsignal, 0LL, EDFSEEK_SET).
|
|
* Note that every signal has it's own independent sample position indicator and \p edfrewind() affects only one of them.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @return
|
|
* 0 on success or -1 in case of an error.
|
|
*/
|
|
EDFLIB_API int edfrewind(int handle, int edfsignal);
|
|
|
|
/**
|
|
* Fills the edflib_annotation_t structure with the annotation \p n.
|
|
* 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.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
* @param[in] n
|
|
* The zero-based index number of the list of annotations.
|
|
* @param[out] annot
|
|
* Pointer to a struct that will be filled with the annotation.
|
|
*
|
|
* @return
|
|
* 0 on success or -1 in case of an error.
|
|
*/
|
|
EDFLIB_API int edf_get_annotation(int handle, int n, edflib_annotation_t *annot);
|
|
|
|
/***************** the following functions are used in read and write mode **************************/
|
|
|
|
/**
|
|
* Closes (and in case of writing, finalizes) the file.
|
|
*
|
|
* This function MUST be called when you have 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 or incomplete file.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @return
|
|
* 0 on success or -1 in case of an error.
|
|
*/
|
|
EDFLIB_API int edfclose_file(int handle);
|
|
|
|
/**
|
|
* Returns the version number of this library, multiplied by hundred. if version is "1.00" then it will return 100.
|
|
*
|
|
* @return
|
|
* The version number.
|
|
*/
|
|
EDFLIB_API int edflib_version(void);
|
|
|
|
/**
|
|
* Returns 1 if the file is in use, either for reading or writing, otherwise returns 0.
|
|
*
|
|
* @param[in] path
|
|
* Pointer to a null-terminated string that contains the path to the file.
|
|
*
|
|
* @return
|
|
* 1 if the file is in use (either for reading or writing), otherwise 0.
|
|
*/
|
|
EDFLIB_API int edflib_is_file_used(const char *path);
|
|
|
|
/**
|
|
* Returns the number of open files.
|
|
*
|
|
* @return
|
|
* The number of open files, either for reading or writing.
|
|
*/
|
|
EDFLIB_API int edflib_get_number_of_open_files(void);
|
|
|
|
/**
|
|
* Returns the handle of an open file, either for reading or writing.
|
|
*
|
|
* @param[in] file_number
|
|
* A zero based index number of the list of open files.
|
|
*
|
|
* @return
|
|
* The file handle or -1 if the file_number >= number of open files.
|
|
*/
|
|
EDFLIB_API int edflib_get_handle(int file_number);
|
|
|
|
/***************** the following functions are used to write files **************************/
|
|
|
|
/**
|
|
* Opens an new file for writing. Warning: an already existing file with the same name will be silently overwritten without advance warning!<br>
|
|
* This function is required if you want to write a file (or use edfopen_file_writeonly_with_params())
|
|
*
|
|
* @param[in] path
|
|
* A null-terminated string containing the path and name of the file
|
|
*
|
|
* @param[in] filetype
|
|
* Must be EDFLIB_FILETYPE_EDFPLUS or EDFLIB_FILETYPE_BDFPLUS.
|
|
*
|
|
* @param[in] number_of_signals
|
|
* The number of signals you want to store into the file<br>
|
|
* (excluding annotation signals, the library will take care of that).
|
|
*
|
|
* @return
|
|
* A file handle on success or a negative number in case of an error:
|
|
* - EDFLIB_MALLOC_ERROR
|
|
* - EDFLIB_NO_SUCH_FILE_OR_DIRECTORY
|
|
* - EDFLIB_MAXFILES_REACHED
|
|
* - EDFLIB_FILE_ALREADY_OPENED
|
|
* - EDFLIB_NUMBER_OF_SIGNALS_INVALID
|
|
* - EDFLIB_ARCH_ERROR
|
|
*/
|
|
EDFLIB_API int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals);
|
|
|
|
/**
|
|
* This is a convenience function that can create a new EDF file and initializes the most important parameters.<br>
|
|
* It assumes that all signals are sharing the same parameters (you can still change them though).<br>
|
|
* Warning: an already existing file with the same name will be silently overwritten without advance warning!<br>
|
|
*
|
|
* @param[in] path
|
|
* A null-terminated string containing the path and name of the file.
|
|
*
|
|
* @param[in] filetype
|
|
* Must be EDFLIB_FILETYPE_EDFPLUS or EDFLIB_FILETYPE_BDFPLUS.
|
|
*
|
|
* @param[in] number_of_signals
|
|
* The number of signals you want to store into the file<br>
|
|
* (excluding annotation signals, the library will take care of that).
|
|
*
|
|
* @param[in] samplefrequency
|
|
* Sample frequency for all signals. (In reality, it sets the number of samples per datarecord which equals the sample frequency only when<br>
|
|
* the datarecords have a duration of one second which is the default here.)
|
|
*
|
|
* @param[in] phys_max_min
|
|
* Physical maximum and minimum for all signals.
|
|
*
|
|
* @param[in] phys_dim
|
|
* Pointer to a NULL-terminated ASCII-string containing the physical dimension (unit) for all signals ("uV", "BPM", "mA", "Degr.", etc.).
|
|
*
|
|
* @return
|
|
* A file handle on success or a negative number in case of an error:
|
|
* - EDFLIB_MALLOC_ERROR
|
|
* - EDFLIB_NO_SUCH_FILE_OR_DIRECTORY
|
|
* - EDFLIB_MAXFILES_REACHED
|
|
* - EDFLIB_FILE_ALREADY_OPENED
|
|
* - EDFLIB_NUMBER_OF_SIGNALS_INVALID
|
|
* - EDFLIB_ARCH_ERROR
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* Sets the sample frequency of signal edfsignal. In reality, it sets the number of samples in a datarecord<br>
|
|
* which equals the sample frequency only when the datarecords have a duration of one second.<br>
|
|
* The effective sample frequency is: samplefrequency / datarecord duration<br>
|
|
* This function is required for every signal (except when using edfopen_file_writeonly_with_params()) and can be called<br>
|
|
* only after opening a file in write mode and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] samplefrequency
|
|
* Sample frequency, must be > 0;
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency);
|
|
|
|
/**
|
|
* 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")<br>
|
|
* It is the highest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level.<br>
|
|
* In other words, it is the highest value that CAN occur in the recording.<br>
|
|
* Must be un-equal to physical minimum.<br>
|
|
* This function is required for every signal (except when using edfopen_file_writeonly_with_params()) and can be called<br>
|
|
* only after opening a file in write mode and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] phys_max
|
|
* Physical maximum, must be != physical minimum;
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_physical_maximum(int handle, int edfsignal, double phys_max);
|
|
|
|
/**
|
|
* 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")<br>
|
|
* It is the lowest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level.<br>
|
|
* In other words, it is the lowest value that CAN occur in the recording.<br>
|
|
* Must be un-equal to physical maximum.<br>
|
|
* This function is required for every signal (except when using edfopen_file_writeonly_with_params()) and can be called<br>
|
|
* only after opening a file in write mode and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] phys_min
|
|
* Physical minimum, must be != physical maximum;
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_physical_minimum(int handle, int edfsignal, double phys_min);
|
|
|
|
/**
|
|
* Sets the maximum digital value of signal edfsignal. The maximum value is 32767 for EDF+ and 8388607 for BDF+.<br>
|
|
* It is the highest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level.<br>
|
|
* In other words, it is the highest value that CAN occur in the recording.<br>
|
|
* Must be higher than digital minimum.<br>
|
|
* This function is required for every signal (except when using edfopen_file_writeonly_with_params()) and can be called<br>
|
|
* only after opening a file in write mode and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] dig_max
|
|
* Digital maximum, must be > digital minimum;
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_digital_maximum(int handle, int edfsignal, int dig_max);
|
|
|
|
/**
|
|
* Sets the minimum digital value of signal edfsignal. The minimum value is -32768 for EDF+ and -8388608 for BDF+.<br>
|
|
* It is the lowest value that the equipment is able to record. It does not necessarily mean the signal recorded reaches this level.<br>
|
|
* In other words, it is the lowest value that CAN occur in the recording.<br>
|
|
* Must be lower than digital maximum.<br>
|
|
* This function is required for every signal (except when using edfopen_file_writeonly_with_params()) and can be called<br>
|
|
* only after opening a file in write mode and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] dig_min
|
|
* Digital minimum, must be < digital maximum;
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_digital_minimum(int handle, int edfsignal, int dig_min);
|
|
|
|
/**
|
|
* Sets the label (name) of signal \p edfsignal. ("EEG FP1", "SaO2", etc.).<br>
|
|
* This function is recommended for every signal when you want to write a file<br>
|
|
* and can be called only after opening a file in write mode and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] label
|
|
* A pointer to a NULL-terminated ASCII-string containing the label (name) of the signal \p edfsignal.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_label(int handle, int edfsignal, const char *label);
|
|
|
|
/**
|
|
* Sets the prefilter of signal \p edfsignal e.g. "HP:0.1Hz", "LP:75Hz N:50Hz", etc.<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] prefilter
|
|
* A pointer to a NULL-terminated ASCII-string containing the prefilter text of the signal \p edfsignal.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_prefilter(int handle, int edfsignal, const char *prefilter);
|
|
|
|
/**
|
|
* Sets the transducer of signal \p edfsignal e.g. "AgAgCl cup electrodes", etc.<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] transducer
|
|
* A pointer to a NULL-terminated ASCII-string containing the transducer text of the signal \p edfsignal.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_transducer(int handle, int edfsignal, const char *transducer);
|
|
|
|
/**
|
|
* Sets the physical dimension (unit) of signal \p edfsignal. ("uV", "BPM", "mA", "Degr.", etc.).<br>
|
|
* This function is recommended for every signal when you want to write a file<br>
|
|
* and can be called only after opening a file in write mode and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] edfsignal
|
|
* The zero-based index of the signal.
|
|
*
|
|
* @param[in] phys_dim
|
|
* A pointer to a NULL-terminated ASCII-string containing the physical dimension (unit) of the signal \p edfsignal.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim);
|
|
|
|
/**
|
|
* Sets the startdate and starttime.<br>
|
|
* If not called, the library will use the system date and time at runtime.<br>
|
|
* This function is optional and can be called only after opening a file in write mode<br>
|
|
* and before the first sample write action.<br>
|
|
* Note: for anonymization purposes, the consensus is to use 1985-01-01 00:00:00 for the startdate and starttime.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] startdate_year
|
|
* 1985 - 2084 inclusive
|
|
*
|
|
* @param[in] startdate_month
|
|
* 1 - 12 inclusive
|
|
*
|
|
* @param[in] startdate_day
|
|
* 1 - 31 inclusive
|
|
*
|
|
* @param[in] starttime_hour
|
|
* 0 - 23 inclusive
|
|
*
|
|
* @param[in] starttime_minute
|
|
* 0 - 59 inclusive
|
|
*
|
|
* @param[in] starttime_second
|
|
* 0 - 59 inclusive
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
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 subject name<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] patientname
|
|
* A pointer to a NULL-terminated ASCII-string containing the subject name.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_patientname(int handle, const char *patientname);
|
|
|
|
/**
|
|
* Sets the subject code<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] patientcode
|
|
* A pointer to a NULL-terminated ASCII-string containing the subject code.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_patientcode(int handle, const char *patientcode);
|
|
|
|
/**
|
|
* Sets the sex of the subject. 1 is male, 0 is female.<br>
|
|
* This function is optional and can be called only after opening a file in writemode<br>
|
|
* and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] sex
|
|
* 1: male, 0: female.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_sex(int handle, int sex);
|
|
|
|
#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
|
|
*/
|
|
|
|
/**
|
|
* Sets the subject birthdate.<br>
|
|
* This function is optional and can be called only after opening a file in write mode<br>
|
|
* and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] birthdate_year
|
|
* 1800 - 3000 inclusive
|
|
*
|
|
* @param[in] birthdate_month
|
|
* 1 - 12 inclusive
|
|
*
|
|
* @param[in] birthdate_day
|
|
* 1 - 31 inclusive
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day);
|
|
|
|
/**
|
|
* Sets the additional subject info<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] patient_additional
|
|
* A pointer to a NULL-terminated ASCII-string containing the additional subject info.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_patient_additional(int handle, const char *patient_additional);
|
|
|
|
/**
|
|
* Sets the administration code<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] admincode
|
|
* A pointer to a NULL-terminated ASCII-string containing the administration code.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_admincode(int handle, const char *admincode);
|
|
|
|
/**
|
|
* Sets the technicians name or code<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] technician
|
|
* A pointer to a NULL-terminated ASCII-string containing the technicians name or code.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_technician(int handle, const char *technician);
|
|
|
|
/**
|
|
* Sets the equipment brand and/or model<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] equipment
|
|
* A pointer to a NULL-terminated ASCII-string containing the equipment brand and/or model<br>
|
|
* used for the recording.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_equipment(int handle, const char *equipment);
|
|
|
|
/**
|
|
* Sets the additional info about the recording.<br>
|
|
* This function is optional and can be called only after opening a file in writemode and<br>
|
|
* before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] recording_additional
|
|
* A pointer to a NULL-terminated ASCII-string containing the additional info about the recording.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_recording_additional(int handle, const char *recording_additional);
|
|
|
|
/**
|
|
* Writes n physical samples (uV, mA, Ohm) from \p buf belonging to one signal<br>
|
|
* where n is the samplefrequency of that signal.<br>
|
|
* Actually, n equals the number of samples per datarecord which equals the samplefrequency only<br>
|
|
* when the datarecord duration has the default value of one second!<br>
|
|
* The physical samples will be converted to digital samples using the<br>
|
|
* values of physical maximum, physical minimum, digital maximum and digital minimum.<br>
|
|
* Size of \p buf must be equal to or bigger than sizeof(double[samples per datarecord]).<br>
|
|
* Call this function for every signal in the file. The order is important:<br>
|
|
* When there are 4 signals in the file, the order of calling this function<br>
|
|
* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] buf
|
|
* A pointer to a buffer containing the samples.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edfwrite_physical_samples(int handle, double *buf);
|
|
|
|
/**
|
|
* Writes physical samples (uV, mA, Ohm) from \p buf <br>
|
|
* \p 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.<br>
|
|
* where n is the samplefrequency of that signal.<br>
|
|
* Actually, n equals the number of samples per datarecord which equals the samplefrequency only<br>
|
|
* when the datarecord duration has the default value of one second!<br>
|
|
* The physical samples will be converted to digital samples using the<br>
|
|
* values of physical maximum, physical minimum, digital maximum and digital minimum.<br>
|
|
* The number of samples written equals the sum of the samples per datarecord of all signals.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] buf
|
|
* A pointer to a buffer containing the samples.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_blockwrite_physical_samples(int handle, double *buf);
|
|
|
|
/**
|
|
* Writes n "raw" digital samples from \p buf belonging to one signal<br>
|
|
* where n is the samplefrequency of that signal.<br>
|
|
* Actually, n equals the number of samples per datarecord which equals the samplefrequency only<br>
|
|
* when the datarecord duration has the default value of one second!<br>
|
|
* Size of \p buf should be equal to or bigger than sizeof(short[samples per datarecord]).<br>
|
|
* Call this function for every signal in the file. The order is important:<br>
|
|
* When there are 4 signals in the file, the order of calling this function<br>
|
|
* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] buf
|
|
* A pointer to a buffer containing the samples.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edfwrite_digital_short_samples(int handle, short *buf);
|
|
|
|
/**
|
|
* Writes n "raw" digital samples from \p buf belonging to one signal<br>
|
|
* where n is the samplefrequency of that signal.<br>
|
|
* Actually, n equals the number of samples per datarecord which equals the samplefrequency only<br>
|
|
* when the datarecord duration has the default value of one second!<br>
|
|
* The 16 (or 24 in case of BDF+) least significant bits of the samples will be written to the<br>
|
|
* file without any conversion.<br>
|
|
* Size of \p buf should be equal to or bigger than sizeof(int[samples per datarecord]).<br>
|
|
* Call this function for every signal in the file. The order is important:<br>
|
|
* When there are 4 signals in the file, the order of calling this function<br>
|
|
* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] buf
|
|
* A pointer to a buffer containing the samples.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edfwrite_digital_samples(int handle, int *buf);
|
|
|
|
/**
|
|
* Writes "raw" digital samples from \p buf <br>
|
|
* \p 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.<br>
|
|
* where n is the samplefrequency of that signal.<br>
|
|
* Actually, n equals the number of samples per datarecord which equals the samplefrequency only<br>
|
|
* when the datarecord duration has the default value of one second!<br>
|
|
* One sample equals 3 bytes, order is little endian (least significant byte first).<br>
|
|
* Encoding is second's complement, most significant bit of most significant byte is the sign-bit.<br>
|
|
* Because the size of a 3-byte sample is 24-bit, this function can only be used when writing a BDF+ file.<br>
|
|
* The number of samples written equals the sum of the samples per datarecord of all signals.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] buf
|
|
* A pointer to a buffer containing the samples.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_blockwrite_digital_3byte_samples(int handle, void *buf);
|
|
|
|
/**
|
|
* Writes "raw" digital samples from \p buf <br>
|
|
* \p 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.<br>
|
|
* where n is the samplefrequency of that signal.<br>
|
|
* Actually, n equals the number of samples per datarecord which equals the samplefrequency only<br>
|
|
* when the datarecord duration has the default value of one second!<br>
|
|
* One sample equals 2 bytes, order is little endian (least significant byte first).<br>
|
|
* Encoding is second's complement, most significant bit of most significant byte is the sign-bit.<br>
|
|
* Because the size of a 2-byte sample is 16-bit, this function can only be used when writing an EDF+ file.<br>
|
|
* The number of samples written equals the sum of the samples per datarecord of all signals.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] buf
|
|
* A pointer to a buffer containing the samples.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_blockwrite_digital_short_samples(int handle, short *buf);
|
|
|
|
/**
|
|
* Writes "raw" digital samples from \p buf <br>
|
|
* \p 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.<br>
|
|
* where n is the samplefrequency of that signal.<br>
|
|
* Actually, n equals the number of samples per datarecord which equals the samplefrequency only<br>
|
|
* when the datarecord duration has the default value of one second!<br>
|
|
* The 16 (or 24 in case of BDF+) least significant bits of the samples will be written to the<br>
|
|
* file without any conversion.<br>
|
|
* The number of samples written equals the sum of the samples per datarecord of all signals.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] buf
|
|
* A pointer to a buffer containing the samples.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_blockwrite_digital_samples(int handle, int *buf);
|
|
|
|
/**
|
|
* Writes an annotation/event to the file.<br>
|
|
* This function is optional and can be called only after opening a file in writemode<br>
|
|
* and before closing the file.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] onset
|
|
* microseconds since start of recording.
|
|
*
|
|
* @param[in] duration
|
|
* microseconds, > 0 or -1 if not used.
|
|
*
|
|
* @param[in] description
|
|
* A null-terminated UTF8-string containing the text that describes the event.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edfwrite_annotation_utf8_hr(int handle, long long onset, long long duration, const char *description);
|
|
|
|
#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
|
|
*/
|
|
|
|
/**
|
|
* Writes an annotation/event to the file.<br>
|
|
* This function is optional and can be called only after opening a file in writemode<br>
|
|
* and before closing the file.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] onset
|
|
* microseconds since start of recording.
|
|
*
|
|
* @param[in] duration
|
|
* microseconds, > 0 or -1 if not used.
|
|
*
|
|
* @param[in] description
|
|
* A null-terminated Latin1-string containing the text that describes the event.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edfwrite_annotation_latin1_hr(int handle, long long onset, long long duration, const char *description);
|
|
|
|
#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
|
|
*/
|
|
|
|
/**
|
|
* Sets the datarecord duration. The default value is 1 second.<br>
|
|
* ATTENTION: the argument \p duration is expressed in units of 10 microseconds.<br>
|
|
* So, if you want to set the datarecord duration to 0.1 second, you must write a value of 10000.<br>
|
|
* The datarecord duration must be in the range 0.001 to 60 seconds.<br>
|
|
* This function can be used when you want to use a samplerate<br>
|
|
* which is not an integer. For example, if you want to use a samplerate of 0.5 Hz,<br>
|
|
* set the samplefrequency to 5 Hz and the datarecord duration to 10 seconds,<br>
|
|
* or set the samplefrequency to 1 Hz and the datarecord duration to 2 seconds.<br>
|
|
* This function is optional and can be called after opening a<br>
|
|
* file in writemode and before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] duration
|
|
* Datarecord duration expressed in units of 10 microSecond.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_datarecord_duration(int handle, int duration);
|
|
|
|
/**
|
|
* Sets the datarecord duration to a very small value.<br>
|
|
* ATTENTION: the argument \p duration is expressed in units of 1 microSecond.<br>
|
|
* The datarecord duration must be in the range 1 to 9999 microseconds.<br>
|
|
* This function can be used when you want to use a very high samplerate.<br>
|
|
* For example, if you want to use a samplerate of 5 GHz,<br>
|
|
* set the samplefrequency to 5000 Hz and the datarecord duration to 1 micro-second.<br>
|
|
* Do not use this function if not necessary.<br>
|
|
* This function was added to accommodate for high speed ADC's e.g. Digital Sampling Oscilloscopes<br>
|
|
* This function is optional and can be called after opening a<br>
|
|
* file in writemode and before the first sample write action.
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] duration
|
|
* Datarecord duration expressed in units of 10 microSecond.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_micro_datarecord_duration(int handle, int duration);
|
|
|
|
/**
|
|
* Sets the number of annotation signals. The default value is 1.<br>
|
|
* This function is optional and can be called only after opening a file in writemode<br>
|
|
* and before the first sample write action.<br>
|
|
* Normally you don't need to change the default value. Only when the number of annotations<br>
|
|
* you expect to write is more than the number of datarecords in the recording, you can use<br>
|
|
* this function to increase the storage space for annotations.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] annot_signals
|
|
* Number of annotation signals, must be in the range 1 - 64 inclusive.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_number_of_annotation_signals(int handle, int annot_signals);
|
|
|
|
/**
|
|
* Sets the subsecond starttime expressed in units of 100 nanoseconds.<br>
|
|
* Valid range is 0 to 9999999 inclusive. Default is 0.<br>
|
|
* This function is optional and can be called only after opening a file in writemode<br>
|
|
* and before the first sample write action.<br>
|
|
* It is recommended to use a maximum resolution of not more than 100 microseconds.<br>
|
|
* E.g. use 1234000 to set a starttime offset of 0.1234 seconds (instead of for example 1234217).<br>
|
|
* In other words, leave the last 3 digits at zero.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] subsecond
|
|
* Subsecond starttime expressed in units of 100 nanoseconds.
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_subsecond_starttime(int handle, int subsecond);
|
|
|
|
/**
|
|
* Sets the preferred position of the annotation channels(s) before, after or in the middle of the list<br>
|
|
* of regular signals. The default is to put them at the end (after the regular signals).<br>
|
|
* This function is optional and can be called only after opening a file in writemode<br>
|
|
* and before the first sample write action.<br>
|
|
*
|
|
* @param[in] handle
|
|
* File handle.
|
|
*
|
|
* @param[in] pos
|
|
* Preferred position of the annotation channel(s):<br>
|
|
* EDF_ANNOT_IDX_POS_START<br>
|
|
* EDF_ANNOT_IDX_POS_MIDDLE<br>
|
|
* EDF_ANNOT_IDX_POS_END<br>
|
|
*
|
|
* @return
|
|
* 0 on success, otherwise -1.<br>
|
|
*/
|
|
EDFLIB_API int edf_set_annot_chan_idx_pos(int handle, int pos);
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|