/* EDF Parser Implementation * * Copyright (c) 2011-2018 Mark Watkins * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the Linux * distribution for more details. */ #include #include #include #include "zlib.h" #include "edfparser.h" EDFParser::EDFParser(QString name) { buffer = nullptr; if (!name.isEmpty()) Open(name); } EDFParser::~EDFParser() { for (QVector::iterator s = edfsignals.begin(); s != edfsignals.end(); s++) { if ((*s).data) { delete [](*s).data; } } if (buffer) { delete [] buffer; } } // Read a 16 bits integer qint16 EDFParser::Read16() { if ((pos + 2) > filesize) { 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); #endif pos += 2; return res; } QString EDFParser::Read(unsigned n) { if ((pos + long(n)) > filesize) { return ""; } QByteArray buf(&buffer[pos], n); pos+=n; return buf.trimmed(); } bool EDFParser::Parse() { bool ok; QString temp, temp2; 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(); /*char * idx=index(header.recordingident,'='); idx++; for (int i=0;i<16;++i) { if (*idx==0x20) break; serialnumber+=*idx; ++idx; } */ 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(); //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 (int i = 0; i < num_signals; i++) { EDFSignal &sig = edfsignals[i]; sig.data = nullptr; sig.label = Read(16); signal_labels.push_back(sig.label); signalList[sig.label].push_back(&sig); signal.push_back(&sig); } for (int i = 0; i < num_signals; i++) { edfsignals[i].transducer_type = Read(80); } for (int i = 0; i < num_signals; i++) { edfsignals[i].physical_dimension = Read(8); } for (int i = 0; i < num_signals; i++) { edfsignals[i].physical_minimum = Read(8).toDouble(&ok); } for (int i = 0; i < num_signals; i++) { edfsignals[i].physical_maximum = Read(8).toDouble(&ok); } for (int i = 0; i < num_signals; i++) { edfsignals[i].digital_minimum = Read(8).toDouble(&ok); } for (int i = 0; i < num_signals; i++) { EDFSignal &e = edfsignals[i]; e.digital_maximum = Read(8).toDouble(&ok); e.gain = (e.physical_maximum - e.physical_minimum) / (e.digital_maximum - e.digital_minimum); e.offset = 0; } for (int i = 0; i < num_signals; i++) { edfsignals[i].prefiltering = Read(80); } for (int i = 0; i < num_signals; i++) { edfsignals[i].nr = Read(8).toLong(&ok); } for (int i = 0; i < num_signals; i++) { edfsignals[i].reserved = Read(32); } // allocate the buffers for (int i = 0; i < num_signals; i++) { //qDebug//cout << "Reading signal " << signals[i]->label << endl; EDFSignal &sig = edfsignals[i]; 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 (int i = 0; i < num_signals; i++) { EDFSignal &sig = edfsignals[i]; #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 >::iterator it = signalList.find(name); if (it == signalList.end()) return nullptr; if (index >= it.value().size()) return nullptr; return it.value()[index]; }