Re-arrange edf-parser code - and fix it

This commit is contained in:
Phil Olynyk 2019-07-18 19:36:35 -04:00
parent 4ad282768c
commit 8c11751b2b
4 changed files with 391 additions and 395 deletions

View File

@ -1,5 +1,6 @@
/* EDF Parser Implementation
*
* Copyright (c) 2019 The OSCAR Team
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
*
* This file is subject to the terms and conditions of the GNU General Public
@ -20,16 +21,226 @@
EDFParser::EDFParser(QString name)
{
buffer = nullptr;
filesize = 0;
datasize = 0;
signalPtr = nullptr;
hdrPtr = nullptr;
fileData.clear();
if (!name.isEmpty())
Open(name);
}
EDFParser::~EDFParser()
{
for (auto & s : edfsignals) {
if (s.data) { delete [] s.data; }
if (s.value)
delete [] s.value;
}
}
bool EDFParser::Open(const QString & name)
{
if (hdrPtr != nullptr) {
qWarning() << "EDFParser::Open() called with file already open" << name;
return false;
}
QFile fi(name);
if (!fi.open(QFile::ReadOnly)) {
qDebug() << "EDFParser::Open() Couldn't open file" << name;
return false;
}
if (name.endsWith(STR_ext_gz)) {
fileData = gUncompress(fi.readAll()); // Open and decompress file
} else {
fileData = fi.readAll(); // Open and read uncompressed file
}
fi.close();
if (fileData.size() <= EDFHeaderSize) {
qDebug() << "EDFParser::Open() File too short" << name;
return false;
}
hdrPtr = (EDFHeaderRaw *)fileData.constData();
signalPtr = (char *)fileData.constData() + EDFHeaderSize;
filename = name;
filesize = fileData.size();
datasize = filesize - EDFHeaderSize;
pos = 0;
return true;
}
bool EDFParser::Parse()
{
bool ok;
if (hdrPtr == nullptr) {
qWarning() << "EDFParser::Parse() called without valid EDF data" << filename;
return false;
}
eof = false;
edfHdr.version = QString::fromLatin1(hdrPtr->version, 8).toLong(&ok);
if (!ok) {
return false;
}
//patientident=QString::fromLatin1(header.patientident,80);
edfHdr.recordingident = QString::fromLatin1(hdrPtr->recordingident, 80); // Serial number is in here..
int snp = edfHdr.recordingident.indexOf("SRN=");
serialnumber.clear();
for (int i = snp + 4; i < edfHdr.recordingident.length(); i++) {
if (edfHdr.recordingident[i] == ' ') {
break;
}
serialnumber += edfHdr.recordingident[i];
}
edfHdr.startdate_orig = QDateTime::fromString(QString::fromLatin1(hdrPtr->datetime, 16), "dd.MM.yyHH.mm.ss");
QDate d2 = edfHdr.startdate_orig.date();
if (d2.year() < 2000) {
d2.setDate(d2.year() + 100, d2.month(), d2.day());
edfHdr.startdate_orig.setDate(d2);
}
if (!edfHdr.startdate_orig.isValid()) {
qDebug() << "Invalid date time retreieved parsing EDF File" << filename;
return false;
}
startdate = qint64(edfHdr.startdate_orig.toTime_t()) * 1000L;
//startdate-=timezoneOffset();
if (startdate == 0) {
qDebug() << "Invalid startdate = 0 in EDF File" << filename;
return false;
}
qDebug() << edfHdr.startdate_orig.toString("yyyy-MMM-dd HH:mm:ss") << "in" << filename;
edfHdr.num_header_bytes = QString::fromLatin1(hdrPtr->num_header_bytes, 8).toLong(&ok);
if (!ok) {
return false;
}
edfHdr.reserved44=QString::fromLatin1(hdrPtr->reserved, 44);
edfHdr.num_data_records = QString::fromLatin1(hdrPtr->num_data_records, 8).toLong(&ok);
if (!ok) {
return false;
}
edfHdr.duration_Seconds = QString::fromLatin1(hdrPtr->dur_data_records, 8).toLong(&ok);
if (!ok) {
return false;
}
dur_data_record = (edfHdr.duration_Seconds * 1000.0L);
edfHdr.num_signals = QString::fromLatin1(hdrPtr->num_signals, 4).toLong(&ok);
if (!ok) {
return false;
}
enddate = startdate + dur_data_record * qint64(edfHdr.num_data_records);
// if (dur_data_record==0)
// return false;
// this could be loaded quicker by transducer_type[signal] etc..
// Initialize fixed-size signal list.
edfsignals.resize(edfHdr.num_signals);
for (auto & sig : edfsignals) {
sig.value = nullptr;
sig.label = Read(16);
signal_labels.push_back(sig.label);
signalList[sig.label].push_back(&sig);
if (eof)
return false;
}
for (auto & sig : edfsignals) {
sig.transducer_type = Read(80);
}
for (auto & sig : edfsignals) {
sig.physical_dimension = Read(8);
}
for (auto & sig : edfsignals) {
sig.physical_minimum = Read(8).toDouble(&ok);
}
for (auto & sig : edfsignals) {
sig.physical_maximum = Read(8).toDouble(&ok);
}
for (auto & sig : edfsignals) {
sig.digital_minimum = Read(8).toDouble(&ok);
}
for (auto & sig : edfsignals) {
sig.digital_maximum = Read(8).toDouble(&ok);
sig.gain = (sig.physical_maximum - sig.physical_minimum) / (sig.digital_maximum - sig.digital_minimum);
sig.offset = 0;
}
for (auto & sig : edfsignals) {
sig.prefiltering = Read(80);
}
for (auto & sig : edfsignals) {
sig.nr = Read(8).toLong(&ok);
}
for (auto & sig : edfsignals) {
sig.reserved = Read(32);
}
// could do it earlier, but it won't crash from > EOF Reads
if (eof)
return false;
// Now check the file isn't truncated before allocating all the memory
long allocsize = 0;
for (auto & sig : edfsignals) {
if (edfHdr.num_data_records > 0) {
allocsize += sig.nr * edfHdr.num_data_records * 2;
}
}
if (allocsize > (datasize - pos)) {
// Space required more than the remainder left to read,
// so abort and let the user clean up the corrupted file themselves
qWarning() << "EDFParser::Parse():" << filename << " is too short!";
return false;
}
// allocate the buffers for the signal values
for (auto & sig : edfsignals) {
long recs = sig.nr * edfHdr.num_data_records;
if (edfHdr.num_data_records <= 0) {
sig.value = nullptr;
continue;
}
sig.value = new qint16 [recs];
sig.pos = 0;
}
for (int x = 0; x < edfHdr.num_data_records; x++) {
for (auto & sig : edfsignals) {
#ifdef Q_LITTLE_ENDIAN
// Intel x86, etc..
memcpy((char *)&sig.value[sig.pos], (char *)&signalPtr[pos], sig.nr * 2);
sig.pos += sig.nr;
pos += sig.nr * 2;
#else
// Big endian safe
for (int j=0;j<sig.nr;j++) {
qint16 t=Read16();
sig.value[sig.pos++]=t;
}
#endif
}
}
return true;
}
// Read a 16 bits integer
qint16 EDFParser::Read16()
{
@ -37,15 +248,11 @@ qint16 EDFParser::Read16()
eof = true;
return 0;
}
#ifdef Q_LITTLE_ENDIAN
// Intel, etc...
qint16 res = *(qint16 *)&buffer[pos];
#else
// ARM, PPC, etc..
qint16 res = quint8(buffer[pos]) | (qint8(buffer[pos+1]) << 8);
#ifdef Q_LITTLE_ENDIAN // Intel, etc...
qint16 res = *(qint16 *)&signalPtr[pos];
#else // ARM, PPC, etc..
qint16 res = quint8(signalPtr[pos]) | (qint8(signalPtr[pos+1]) << 8);
#endif
pos += 2;
return res;
}
@ -56,225 +263,20 @@ QString EDFParser::Read(unsigned n)
eof = true;
return QString();
}
QByteArray buf(&buffer[pos], n);
QByteArray buf(&signalPtr[pos], n);
pos+=n;
return buf.trimmed();
}
bool EDFParser::Parse()
{
bool ok;
if (header == nullptr) {
qWarning() << "EDFParser::Parse() called without valid EDF data" << filename;
return false;
}
eof = false;
version = QString::fromLatin1(header->version, 8).toLong(&ok);
if (!ok) {
return false;
}
//patientident=QString::fromLatin1(header.patientident,80);
recordingident = QString::fromLatin1(header->recordingident, 80); // Serial number is in here..
int snp = recordingident.indexOf("SRN=");
serialnumber.clear();
for (int i = snp + 4; i < recordingident.length(); i++) {
if (recordingident[i] == ' ') {
break;
}
serialnumber += recordingident[i];
}
startdate_orig = QDateTime::fromString(QString::fromLatin1(header->datetime, 16), "dd.MM.yyHH.mm.ss");
QDate d2 = startdate_orig.date();
if (d2.year() < 2000) {
d2.setDate(d2.year() + 100, d2.month(), d2.day());
startdate_orig.setDate(d2);
}
if (!startdate_orig.isValid()) {
qDebug() << "Invalid date time retreieved parsing EDF File" << filename;
return false;
}
startdate = qint64(startdate_orig.toTime_t()) * 1000L;
//startdate-=timezoneOffset();
if (startdate == 0) {
qDebug() << "Invalid startdate = 0 in EDF File" << filename;
return false;
}
//qDebug() << startDate.toString("yyyy-MM-dd HH:mm:ss");
num_header_bytes = QString::fromLatin1(header->num_header_bytes, 8).toLong(&ok);
if (!ok) {
return false;
}
//reserved44=QString::fromLatin1(header.reserved,44);
num_data_records = QString::fromLatin1(header->num_data_records, 8).toLong(&ok);
if (!ok) {
return false;
}
dur_data_record = (QString::fromLatin1(header->dur_data_records, 8).toDouble(&ok) * 1000.0L);
if (!ok) {
return false;
}
num_signals = QString::fromLatin1(header->num_signals, 4).toLong(&ok);
if (!ok) {
return false;
}
enddate = startdate + dur_data_record * qint64(num_data_records);
// if (dur_data_record==0)
// return false;
// this could be loaded quicker by transducer_type[signal] etc..
// Initialize fixed-size signal list.
edfsignals.resize(num_signals);
for (auto & sig : edfsignals) {
sig.data = nullptr;
sig.label = Read(16);
signal_labels.push_back(sig.label);
signalList[sig.label].push_back(&sig);
if (eof) return false;
}
for (auto & sig : edfsignals) { sig.transducer_type = Read(80); }
for (auto & sig : edfsignals) { sig.physical_dimension = Read(8); }
for (auto & sig : edfsignals) { sig.physical_minimum = Read(8).toDouble(&ok); }
for (auto & sig : edfsignals) { sig.physical_maximum = Read(8).toDouble(&ok); }
for (auto & sig : edfsignals) { sig.digital_minimum = Read(8).toDouble(&ok); }
for (auto & sig : edfsignals) { sig.digital_maximum = Read(8).toDouble(&ok);
sig.gain = (sig.physical_maximum - sig.physical_minimum) / (sig.digital_maximum - sig.digital_minimum);
sig.offset = 0;
}
for (auto & sig : edfsignals) { sig.prefiltering = Read(80); }
for (auto & sig : edfsignals) { sig.nr = Read(8).toLong(&ok); }
for (auto & sig : edfsignals) { sig.reserved = Read(32); }
// could do it earlier, but it won't crash from > EOF Reads
if (eof) return false;
// Now check the file isn't truncated before allocating all the memory
long allocsize = 0;
for (auto & sig : edfsignals) {
if (num_data_records > 0) {
allocsize += sig.nr * num_data_records * 2;
}
}
if (allocsize > (datasize - pos)) {
// Space required more than the remainder left to read,
// so abort and let the user clean up the corrupted file themselves
qWarning() << "EDFParser::Parse():" << filename << " is truncated!";
return false;
}
// allocate the buffers
for (auto & sig : edfsignals) {
long recs = sig.nr * num_data_records;
if (num_data_records <= 0) {
sig.data = nullptr;
continue;
}
sig.data = new qint16 [recs];
sig.pos = 0;
}
for (int x = 0; x < num_data_records; x++) {
for (auto & sig : edfsignals) {
#ifdef Q_LITTLE_ENDIAN
// Intel x86, etc..
memcpy((char *)&sig.data[sig.pos], (char *)&buffer[pos], sig.nr * 2);
sig.pos += sig.nr;
pos += sig.nr * 2;
#else
// Big endian safe
for (int j=0;j<sig.nr;j++) {
qint16 t=Read16();
sig.data[sig.pos++]=t;
}
#endif
}
}
return true;
}
QByteArray gUncompress(const QByteArray &data);
bool EDFParser::Open(const QString & name)
{
if (buffer != nullptr) {
qWarning() << "EDFParser::Open() called with file already open" << name;
return false;
}
QFile fi(name);
if (!fi.open(QFile::ReadOnly)) {
goto badfile;
}
if (name.endsWith(STR_ext_gz)) {
filename = name; //name.mid(0, -3); // DoubleCheck: why am I cropping the extension? this is used for debugging
// Open and decempress file
data = gUncompress(fi.readAll());
} else {
// Open and read uncompressed file
filename = name;
data = fi.readAll();
}
fi.close();
filesize = data.size();
if (filesize > EDFHeaderSize) {
header = (EDFHeader *)data.constData();
buffer = (char *)data.constData() + EDFHeaderSize;
datasize = filesize - EDFHeaderSize;
} else goto badfile;
pos = 0;
return true;
badfile:
filesize = 0;
datasize = 0;
buffer = nullptr;
header = nullptr;
data.clear();
qDebug() << "EDFParser::Open() Couldn't open file" << name;
return false;
}
EDFSignal *EDFParser::lookupLabel(const QString & name, int index)
{
auto it = signalList.find(name);
if (it == signalList.end()) return nullptr;
if (it == signalList.end())
return nullptr;
if (index >= it.value().size()) return nullptr;
if (index >= it.value().size())
return nullptr;
return it.value()[index];
}
//QMutex EDFParser::EDFMutex;

View File

@ -1,5 +1,6 @@
/* EDF Parser Header
*
* Copyright (c) 2019 The OSCAR Team
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
*
* This file is subject to the terms and conditions of the GNU General Public
@ -13,7 +14,6 @@
#include <QVector>
#include <QHash>
#include <QList>
#include <QMutex>
#include "SleepLib/common.h"
@ -24,7 +24,7 @@ const QString STR_ext_gz = ".gz";
\brief Represents the EDF+ header structure, used as a place holder while processing the text data.
\note More information on the EDF+ file format can be obtained from http://edfplus.info
*/
struct EDFHeader {
struct EDFHeaderRaw {
char version[8];
char patientident[80];
char recordingident[80];
@ -39,8 +39,23 @@ struct EDFHeader {
__attribute__((packed))
#endif
;
const int EDFHeaderSize = sizeof(EDFHeaderRaw);
const int EDFHeaderSize = sizeof(EDFHeader);
/*! \struct EDFHeaderQT
\brief Contains the QT version of the EDF header information
*/
struct EDFHeaderQT {
public:
long version;
QString patientident;
QString recordingident;
QDateTime startdate_orig;
long num_header_bytes;
QString reserved44;
long num_data_records;
long duration_Seconds;
long num_signals;
};
/*! \struct EDFSignal
\brief Contains information about a single EDF+ Signal
@ -48,47 +63,20 @@ const int EDFHeaderSize = sizeof(EDFHeader);
*/
struct EDFSignal {
public:
//! \brief Name of this Signal
QString label;
//! \brief Tranducer Type (source of the data, usually blank)
QString transducer_type;
//! \brief The units of measurements represented by this signal
QString physical_dimension;
//! \brief The minimum limits of the ungained data
EventDataType physical_minimum;
//! \brief The maximum limits of the ungained data
EventDataType physical_maximum;
//! \brief The minimum limits of the data with gain and offset applied
EventDataType digital_minimum;
//! \brief The maximum limits of the data with gain and offset applied
EventDataType digital_maximum;
//! \brief Raw integer data is multiplied by this value
EventDataType gain;
//! \brief This value is added to the raw data
EventDataType offset;
//! \brief Any prefiltering methods used (usually blank)
QString prefiltering;
//! \brief Number of records
long nr;
//! \brief Reserved (usually blank)
QString reserved;
//! \brief Pointer to the signals sample data
qint16 *data;
//! \brief a non-EDF extra used internally to count the signal data
int pos;
QString label; //! \brief Name of this Signal
QString transducer_type; //! \brief Tranducer Type (source of the data, usually blank)
QString physical_dimension; //! \brief The units of measurements represented by this signal
EventDataType physical_minimum; //! \brief The minimum limits of the ungained data
EventDataType physical_maximum; //! \brief The maximum limits of the ungained data
EventDataType digital_minimum; //! \brief The minimum limits of the data with gain and offset applied
EventDataType digital_maximum; //! \brief The maximum limits of the data with gain and offset applied
EventDataType gain; //! \brief Raw integer data is multiplied by this value
EventDataType offset; //! \brief This value is added to the raw data
QString prefiltering; //! \brief Any prefiltering methods used (usually blank)
long nr; //! \brief Number of records
QString reserved; //! \brief Reserved (usually blank)
qint16 *value; //! \brief Pointer to the signals sample data
int pos; //! \brief a non-EDF extra used internally to count the signal data
};
@ -108,62 +96,62 @@ class EDFParser
//! \brief Open the EDF+ file, and read it's header
bool Open(const QString & name);
//! \brief Parse the EDF+ file into the list of EDFSignals.. Must be call Open(..) first.
bool Parse();
//! \brief Read n bytes of 8 bit data from the EDF+ data stream
QString Read(unsigned n);
//! \brief Read 16 bit word of data from the EDF+ data stream
qint16 Read16();
//! \brief Return a ptr to the i'th signal with the given name (if multiple signal with the same name(?!))
EDFSignal *lookupLabel(const QString & name, int index=0);
//! \brief Returns the number of signals contained in this EDF file
long GetNumSignals() { return edfHdr.num_signals; }
//! \brief Returns the number of data records contained per signal.
long GetNumDataRecords() { return edfHdr.num_data_records; }
//! \brief Returns the duration represented by this EDF file (in milliseconds)
qint64 GetDuration() { return dur_data_record; }
//! \brief Returns the patientid field from the EDF header
QString GetPatient() { return edfHdr.patientident; }
// The data members follow
//! \brief The header in a QT friendly form
EDFHeaderQT edfHdr;
//! \brief Vector containing the list of EDFSignals contained in this edf file
QVector<EDFSignal> edfsignals;
//! \brief An by-name indexed into the EDFSignal data
QStringList signal_labels;
//! \brief ResMed likes to use the SAME signal name
//! \brief ResMed sometimes re-uses the SAME signal name
QHash<QString, QList<EDFSignal *> > signalList;
EDFSignal *lookupLabel(const QString & name, int index=0);
//! \brief Returns the number of signals contained in this EDF file
long GetNumSignals() { return num_signals; }
//! \brief Returns the number of data records contained per signal.
long GetNumDataRecords() { return num_data_records; }
//! \brief Returns the duration represented by this EDF file (in milliseconds)
qint64 GetDuration() { return dur_data_record; }
//! \brief Returns the patientid field from the EDF header
QString GetPatient() { return patientident; }
//! \brief Parse the EDF+ file into the list of EDFSignals.. Must be call Open(..) first.
bool Parse();
char *buffer;
//! \brief The following are computed from the edfHdr data
QString serialnumber;
qint64 dur_data_record;
qint64 startdate;
qint64 enddate;
// the following could be private
//! \brief This is the array holding the EDF file data
QByteArray fileData;
//! \brief The EDF+ files header structure, used as a place holder while processing the text data.
EDFHeader *header;
QByteArray data;
EDFHeaderRaw *hdrPtr;
//! \brief This is the array of signal descriptors and values
char *signalPtr;
QString filename;
long filesize;
long datasize;
long pos;
long version;
long num_header_bytes;
long num_data_records;
qint64 dur_data_record;
long num_signals;
QString patientident;
QString recordingident;
QString serialnumber;
QDateTime startdate_orig;
qint64 startdate;
qint64 enddate;
QString reserved44;
// static QMutex EDFMutex;
bool eof;
};

View File

@ -132,7 +132,7 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
QString & strfile = file.filename;
ResMedEDFParser & str = *file.edf;
QDate date = str.startdate_orig.date(); // each STR.edf record starts at 12 noon
QDate date = str.edfHdr.startdate_orig.date(); // each STR.edf record starts at 12 noon
qDebug() << "Parsing" << strfile << date << str.GetNumDataRecords() << str.GetNumSignals();
@ -171,8 +171,8 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
bool validday = false;
for (int s = 0; s < maskon->nr; ++s) {
qint32 on = maskon->data[recstart + s];
qint32 off = maskoff->data[recstart + s];
qint32 on = maskon->value[recstart + s];
qint32 off = maskoff->value[recstart + s];
if ((on >= 0) && (off >= 0)) validday=true;
}
@ -196,8 +196,8 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
R.maskon.resize(maskon->nr);
R.maskoff.resize(maskoff->nr);
for (int s = 0; s < maskon->nr; ++s) {
qint32 on = maskon->data[recstart + s];
qint32 off = maskoff->data[recstart + s];
qint32 on = maskon->value[recstart + s];
qint32 off = maskoff->value[recstart + s];
R.maskon[s] = (on>0) ? (timestamp + (on * 60)) : 0;
R.maskoff[s] = (off>0) ? (timestamp + (off * 60)) : 0;
@ -216,7 +216,7 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
CPAPMode mode = MODE_UNKNOWN;
if ((sig = str.lookupSignal(CPAP_Mode))) {
int mod = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
int mod = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
R.rms9_mode = mod;
if (mod == 11) {
@ -241,184 +241,184 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
// Settings.CPAP.Starting Pressure
if ((mod == 0) && (sig = str.lookupLabel("S.C.StartPress"))) {
R.ramp_pressure = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.ramp_pressure = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
// Settings.Adaptive Starting Pressure? // mode 11 = APAP for her?
if (((mod == 1) || (mod == 11)) && (sig = str.lookupLabel("S.AS.StartPress"))) {
R.ramp_pressure = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.ramp_pressure = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((R.mode == MODE_BILEVEL_FIXED) && (sig = str.lookupLabel("S.BL.StartPress"))) {
// Bilevel Starting Pressure
R.ramp_pressure = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.ramp_pressure = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if (((R.mode == MODE_ASV) || (R.mode == MODE_ASV_VARIABLE_EPAP)) && (sig = str.lookupLabel("S.VA.StartPress"))) {
// Bilevel Starting Pressure
R.ramp_pressure = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.ramp_pressure = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
}
if ((sig = str.lookupLabel("Mask Dur"))) {
R.maskdur = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.maskdur = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("Leak Med")) || (sig = str.lookupLabel("Leak.50"))) {
float gain = sig->gain * 60.0;
R.leak50 = EventDataType(sig->data[rec]) * gain;
R.leak50 = EventDataType(sig->value[rec]) * gain;
}
if ((sig = str.lookupLabel("Leak Max"))|| (sig = str.lookupLabel("Leak.Max"))) {
float gain = sig->gain * 60.0;
R.leakmax = EventDataType(sig->data[rec]) * gain;
R.leakmax = EventDataType(sig->value[rec]) * gain;
}
if ((sig = str.lookupLabel("Leak 95")) || (sig = str.lookupLabel("Leak.95"))) {
float gain = sig->gain * 60.0;
R.leak95 = EventDataType(sig->data[rec]) * gain;
R.leak95 = EventDataType(sig->value[rec]) * gain;
}
if ((sig = str.lookupLabel("RespRate.50")) || (sig = str.lookupLabel("RR Med"))) {
R.rr50 = EventDataType(sig->data[rec]) * sig->gain;
R.rr50 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("RespRate.Max")) || (sig = str.lookupLabel("RR Max"))) {
R.rrmax = EventDataType(sig->data[rec]) * sig->gain;
R.rrmax = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("RespRate.95")) || (sig = str.lookupLabel("RR 95"))) {
R.rr95 = EventDataType(sig->data[rec]) * sig->gain;
R.rr95 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("MinVent.50")) || (sig = str.lookupLabel("Min Vent Med"))) {
R.mv50 = EventDataType(sig->data[rec]) * sig->gain;
R.mv50 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("MinVent.Max")) || (sig = str.lookupLabel("Min Vent Max"))) {
R.mvmax = EventDataType(sig->data[rec]) * sig->gain;
R.mvmax = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("MinVent.95")) || (sig = str.lookupLabel("Min Vent 95"))) {
R.mv95 = EventDataType(sig->data[rec]) * sig->gain;
R.mv95 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("TidVol.50")) || (sig = str.lookupLabel("Tid Vol Med"))) {
R.tv50 = EventDataType(sig->data[rec]) * (sig->gain*1000.0);
R.tv50 = EventDataType(sig->value[rec]) * (sig->gain*1000.0);
}
if ((sig = str.lookupLabel("TidVol.Max")) || (sig = str.lookupLabel("Tid Vol Max"))) {
R.tvmax = EventDataType(sig->data[rec]) * (sig->gain*1000.0);
R.tvmax = EventDataType(sig->value[rec]) * (sig->gain*1000.0);
}
if ((sig = str.lookupLabel("TidVol.95")) || (sig = str.lookupLabel("Tid Vol 95"))) {
R.tv95 = EventDataType(sig->data[rec]) * (sig->gain*1000.0);
R.tv95 = EventDataType(sig->value[rec]) * (sig->gain*1000.0);
}
if ((sig = str.lookupLabel("MaskPress.50")) || (sig = str.lookupLabel("Mask Pres Med"))) {
R.mp50 = EventDataType(sig->data[rec]) * sig->gain;
R.mp50 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("MaskPress.Max")) || (sig = str.lookupLabel("Mask Pres Max"))) {
R.mpmax = EventDataType(sig->data[rec]) * sig->gain ;
R.mpmax = EventDataType(sig->value[rec]) * sig->gain ;
}
if ((sig = str.lookupLabel("MaskPress.95")) || (sig = str.lookupLabel("Mask Pres 95"))) {
R.mp95 = EventDataType(sig->data[rec]) * sig->gain ;
R.mp95 = EventDataType(sig->value[rec]) * sig->gain ;
}
if ((sig = str.lookupLabel("TgtEPAP.50")) || (sig = str.lookupLabel("Exp Pres Med"))) {
R.tgtepap50 = EventDataType(sig->data[rec]) * sig->gain;
R.tgtepap50 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("TgtEPAP.Max")) || (sig = str.lookupLabel("Exp Pres Max"))) {
R.tgtepapmax = EventDataType(sig->data[rec]) * sig->gain;
R.tgtepapmax = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("TgtEPAP.95")) || (sig = str.lookupLabel("Exp Pres 95"))) {
R.tgtepap95 = EventDataType(sig->data[rec]) * sig->gain;
R.tgtepap95 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("TgtIPAP.50")) || (sig = str.lookupLabel("Insp Pres Med"))) {
R.tgtipap50 = EventDataType(sig->data[rec]) * sig->gain;
R.tgtipap50 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("TgtIPAP.Max")) || (sig = str.lookupLabel("Insp Pres Max"))) {
R.tgtipapmax = EventDataType(sig->data[rec]) * sig->gain;
R.tgtipapmax = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("TgtIPAP.95")) || (sig = str.lookupLabel("Insp Pres 95"))) {
R.tgtipap95 = EventDataType(sig->data[rec]) * sig->gain;
R.tgtipap95 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("I:E Med"))) {
R.ie50 = EventDataType(sig->data[rec]) * sig->gain;
R.ie50 = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("I:E Max"))) {
R.iemax = EventDataType(sig->data[rec]) * sig->gain;
R.iemax = EventDataType(sig->value[rec]) * sig->gain;
}
if ((sig = str.lookupLabel("I:E 95"))) {
R.ie95 = EventDataType(sig->data[rec]) * sig->gain;
R.ie95 = EventDataType(sig->value[rec]) * sig->gain;
}
bool haveipap = false;
// if (R.mode == MODE_BILEVEL_FIXED) {
if ((sig = str.lookupSignal(CPAP_IPAP))) {
R.ipap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.ipap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
haveipap = true;
}
if ((sig = str.lookupSignal(CPAP_EPAP))) {
R.epap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.epap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if (R.mode == MODE_ASV) {
if ((sig = str.lookupLabel("S.AV.StartPress"))) {
EventDataType sp = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
EventDataType sp = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
R.ramp_pressure = sp;
}
if ((sig = str.lookupLabel("S.AV.EPAP"))) {
R.min_epap = R.max_epap = R.epap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.min_epap = R.max_epap = R.epap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.AV.MinPS"))) {
R.min_ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.min_ps = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.AV.MaxPS"))) {
R.max_ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.max_ps = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
R.max_ipap = R.epap + R.max_ps;
R.min_ipap = R.epap + R.min_ps;
}
}
if (R.mode == MODE_ASV_VARIABLE_EPAP) {
if ((sig = str.lookupLabel("S.AA.StartPress"))) {
EventDataType sp = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
EventDataType sp = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
R.ramp_pressure = sp;
}
if ((sig = str.lookupLabel("S.AA.MinEPAP"))) {
R.min_epap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.min_epap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.AA.MaxEPAP"))) {
R.max_epap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.max_epap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.AA.MinPS"))) {
R.min_ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.min_ps = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.AA.MaxPS"))) {
R.max_ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.max_ps = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
R.max_ipap = R.max_epap + R.max_ps;
R.min_ipap = R.min_epap + R.min_ps;
}
}
if ((sig = str.lookupSignal(CPAP_PressureMax))) {
R.max_pressure = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.max_pressure = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupSignal(CPAP_PressureMin))) {
R.min_pressure = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.min_pressure = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupSignal(RMS9_SetPressure))) {
R.set_pressure = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.set_pressure = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupSignal(CPAP_EPAPHi))) {
R.max_epap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.max_epap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupSignal(CPAP_EPAPLo))) {
R.min_epap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.min_epap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupSignal(CPAP_IPAPHi))) {
R.max_ipap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.max_ipap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
haveipap = true;
}
if ((sig = str.lookupSignal(CPAP_IPAPLo))) {
R.min_ipap = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.min_ipap = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
haveipap = true;
}
if ((sig = str.lookupSignal(CPAP_PS))) {
R.ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.ps = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
// }
@ -428,10 +428,10 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
int psvar = (mode == MODE_ASV_VARIABLE_EPAP) ? 1 : 0;
if ((sig = str.lookupLabel("Max PS", psvar))) {
R.max_ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.max_ps = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("Min PS", psvar))) {
R.min_ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.min_ps = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if (!haveipap) {
@ -449,25 +449,25 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
bool a10 = false;
if ((mode == MODE_CPAP) || (mode == MODE_APAP)) {
if ((sig = str.lookupSignal(RMS9_EPR))) {
epr= EventDataType(sig->data[rec]) * sig->gain + sig->offset;
epr= EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupSignal(RMS9_EPRLevel))) {
epr_level= EventDataType(sig->data[rec]) * sig->gain + sig->offset;
epr_level= EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.EPR.EPRType"))) {
a10 = true;
epr = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
epr = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
epr += 1;
}
int epr_on=0, clin_epr_on=0;
if ((sig = str.lookupLabel("S.EPR.EPREnable"))) { // first check machines opinion
a10 = true;
epr_on = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
epr_on = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if (epr_on && (sig = str.lookupLabel("S.EPR.ClinEnable"))) {
a10 = true;
clin_epr_on = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
clin_epr_on = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if (a10 && !(epr_on && clin_epr_on)) {
epr = 0;
@ -495,71 +495,71 @@ void ResmedLoader::ParseSTR(Machine *mach, QMap<QDate, STRFile> & STRmap)
}
if ((sig = str.lookupLabel("AHI"))) {
R.ahi = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.ahi = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("AI"))) {
R.ai = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.ai = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("HI"))) {
R.hi = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.hi = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("UAI"))) {
R.uai = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.uai = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("CAI"))) {
R.cai = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.cai = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("OAI"))) {
R.oai = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.oai = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("CSR"))) {
R.csr = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.csr = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.RampTime"))) {
R.s_RampTime = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_RampTime = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.RampEnable"))) {
R.s_RampEnable = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_RampEnable = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.EPR.ClinEnable"))) {
R.s_EPR_ClinEnable = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_EPR_ClinEnable = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.EPR.EPREnable"))) {
R.s_EPREnable = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_EPREnable = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.ABFilter"))) {
R.s_ABFilter = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_ABFilter = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.ClimateControl"))) {
R.s_ClimateControl = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_ClimateControl = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.Mask"))) {
R.s_Mask = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_Mask = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.PtAccess"))) {
R.s_PtAccess = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_PtAccess = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.SmartStart"))) {
R.s_SmartStart = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_SmartStart = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.HumEnable"))) {
R.s_HumEnable = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_HumEnable = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.HumLevel"))) {
R.s_HumLevel = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_HumLevel = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.TempEnable"))) {
R.s_TempEnable = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_TempEnable = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.Temp"))) {
R.s_Temp = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_Temp = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
if ((sig = str.lookupLabel("S.Tube"))) {
R.s_Tube = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
R.s_Tube = EventDataType(sig->value[rec]) * sig->gain + sig->offset;
}
}
}
@ -715,7 +715,7 @@ int PeekAnnotations(const QString & path, quint32 &start, quint32 &end)
for (int s = 0; s < edf.GetNumSignals(); s++) {
recs = edf.edfsignals[s].nr * edf.GetNumDataRecords() * 2;
data = (char *)edf.edfsignals[s].data;
data = (char *)edf.edfsignals[s].value;
pos = 0;
tt = edf.startdate;
//duration = 0;
@ -1791,7 +1791,7 @@ int ResmedLoader::Open(const QString & dirpath)
continue;
}
QDate date = stredf->startdate_orig.date();
QDate date = stredf->edfHdr.startdate_orig.date();
date = QDate(date.year(), date.month(), 1);
if (STRmap.contains(date)) {
delete stredf;
@ -1869,7 +1869,7 @@ int ResmedLoader::Open(const QString & dirpath)
}
// Don't trust the filename date, pick the one inside the STR...
date = stredf->startdate_orig.date();
date = stredf->edfHdr.startdate_orig.date();
date = QDate(date.year(), date.month(), 1);
STRmap[date] = STRFile(fi.canonicalFilePath(), stredf);
@ -2145,7 +2145,7 @@ bool ResmedLoader::LoadCSL(Session *sess, const QString & path)
for (int s = 0; s < edf.GetNumSignals(); s++) {
recs = edf.edfsignals[s].nr * edf.GetNumDataRecords() * 2;
data = (char *)edf.edfsignals[s].data;
data = (char *)edf.edfsignals[s].value;
pos = 0;
tt = edf.startdate;
// sess->updateFirst(tt);
@ -2312,7 +2312,7 @@ bool ResmedLoader::LoadEVE(Session *sess, const QString & path)
for (int s = 0; s < edf.GetNumSignals(); s++) {
recs = edf.edfsignals[s].nr * edf.GetNumDataRecords() * 2;
data = (char *)edf.edfsignals[s].data;
data = (char *)edf.edfsignals[s].value;
pos = 0;
tt = edf.startdate;
@ -2495,7 +2495,7 @@ bool ResmedLoader::LoadBRP(Session *sess, const QString & path)
#ifdef DEBUG_EFFICIENCY
time2.start();
#endif
a->AddWaveform(edf.startdate, es.data, recs, duration);
a->AddWaveform(edf.startdate, es.value, recs, duration);
#ifdef DEBUG_EFFICIENCY
AddWavetime+= time2.elapsed();
#endif
@ -2552,7 +2552,7 @@ void ResmedLoader::ToTimeDelta(Session *sess, ResMedEDFParser &edf, EDFSignal &e
tt += rate * startpos;
}
qint16 *sptr = es.data;
qint16 *sptr = es.value;
qint16 *eptr = sptr + recs;
sptr += startpos;
@ -2709,7 +2709,7 @@ bool ResmedLoader::LoadSAD(Session *sess, const QString & path)
bool hasdata = false;
for (int i = 0; i < recs; ++i) {
if (es.data[i] != -1) {
if (es.value[i] != -1) {
hasdata = true;
break;
}
@ -2810,7 +2810,7 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
} else if (matchSignal(CPAP_RespRate, es.label)) {
code = CPAP_RespRate;
a = sess->AddEventList(code, EVL_Waveform, es.gain, es.offset, 0, 0, rate);
a->AddWaveform(edf.startdate, es.data, recs, duration);
a->AddWaveform(edf.startdate, es.value, recs, duration);
} else if (matchSignal(CPAP_TidalVolume, es.label)) {
code = CPAP_TidalVolume;
es.gain *= 1000.0;
@ -2845,9 +2845,9 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
// es.physical_maximum /= 100.0;
// es.physical_minimum /= 100.0;
// qDebug() << "IE Gain, Max, Min" << es.gain << es.physical_maximum << es.physical_minimum;
// qDebug() << "IE count, data..." << es.nr << es.data[0] << es.data[1] << es.data[2] << es.data[3] << es.data[4];
// qDebug() << "IE count, data..." << es.nr << es.value[0] << es.value[1] << es.value[2] << es.value[3] << es.value[4];
a = sess->AddEventList(code, EVL_Waveform, es.gain, es.offset, 0, 0, rate);
a->AddWaveform(edf.startdate, es.data, recs, duration);
a->AddWaveform(edf.startdate, es.value, recs, duration);
//a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0);
} else if (matchSignal(CPAP_Ti, es.label)) {
code = CPAP_Ti;
@ -2857,7 +2857,7 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
continue;
}
a = sess->AddEventList(code, EVL_Waveform, es.gain, es.offset, 0, 0, rate);
a->AddWaveform(edf.startdate, es.data, recs, duration);
a->AddWaveform(edf.startdate, es.value, recs, duration);
//a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0);
} else if (matchSignal(CPAP_Te, es.label)) {
code = CPAP_Te;
@ -2866,12 +2866,12 @@ bool ResmedLoader::LoadPLD(Session *sess, const QString & path)
continue;
}
a = sess->AddEventList(code, EVL_Waveform, es.gain, es.offset, 0, 0, rate);
a->AddWaveform(edf.startdate, es.data, recs, duration);
a->AddWaveform(edf.startdate, es.value, recs, duration);
//a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0);
} else if (matchSignal(CPAP_TgMV, es.label)) {
code = CPAP_TgMV;
a = sess->AddEventList(code, EVL_Waveform, es.gain, es.offset, 0, 0, rate);
a->AddWaveform(edf.startdate, es.data, recs, duration);
a->AddWaveform(edf.startdate, es.value, recs, duration);
//a=ToTimeDelta(sess,edf,es, code,recs,duration,0,0);
} else if (es.label == "") { // What the hell resmed??
if (emptycnt == 0) {

View File

@ -459,7 +459,13 @@ test {
CONFIG -= app_bundle
!win32 { # add memory checking on Linux and macOS test builds
QMAKE_CFLAGS += -Werror -fsanitize=address -fno-omit-frame-pointer -fno-common -fsanitize-address-use-after-scope
lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,9) {
QMAKE_CFLAGS -= -fsanitize-address-use-after-scope
}
QMAKE_CXXFLAGS += -Werror -fsanitize=address -fno-omit-frame-pointer -fno-common -fsanitize-address-use-after-scope
lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,9) {
QMAKE_CXXFLAGS -= -fsanitize-address-use-after-scope
}
QMAKE_LFLAGS += -fsanitize=address
}