mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-04 02:00:43 +00:00
337 lines
7.9 KiB
C++
337 lines
7.9 KiB
C++
/* SleepLib Event Class Implementation
|
|
*
|
|
* Copyright (c) 2019-2024 The OSCAR Team
|
|
* 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 source code
|
|
* for more details. */
|
|
|
|
#include <QDebug>
|
|
#include "event.h"
|
|
|
|
EventList::EventList(EventListType et, EventDataType gain, EventDataType offset, EventDataType min,
|
|
EventDataType max, double rate, bool second_field)
|
|
: m_type(et), m_gain(gain), m_offset(offset), m_min(min), m_max(max), m_rate(rate),
|
|
m_second_field(second_field)
|
|
{
|
|
m_first = m_last = 0;
|
|
m_count = 0;
|
|
|
|
if (min == max) { // Update Min & Max unless forceably set here..
|
|
m_update_minmax = true;
|
|
m_min2 = m_min = 999999999.0F;
|
|
m_max2 = m_max = -999999999.0F;
|
|
} else {
|
|
m_update_minmax = false;
|
|
}
|
|
|
|
m_data.reserve(2048);
|
|
|
|
// Reserve a few to increase performace??
|
|
}
|
|
|
|
void EventList::clear()
|
|
{
|
|
m_min2 = m_min = 999999999.0F;
|
|
m_max2 = m_max = -999999999.0F;
|
|
m_update_minmax = true;
|
|
m_first = m_last = 0;
|
|
m_count = 0;
|
|
|
|
m_data.clear();
|
|
m_data2.clear();
|
|
m_time.clear();
|
|
|
|
}
|
|
|
|
qint64 EventList::time(quint32 i) const
|
|
{
|
|
if (m_type == EVL_Event) {
|
|
return m_first + qint64(m_time[i]);
|
|
}
|
|
|
|
return m_first + qint64((EventDataType(i) * m_rate));
|
|
}
|
|
|
|
EventDataType EventList::data(quint32 i)
|
|
{
|
|
return EventDataType(m_data[i]) * m_gain;
|
|
}
|
|
|
|
EventDataType EventList::data2(quint32 i)
|
|
{
|
|
return EventDataType(m_data2[i]);
|
|
}
|
|
|
|
static QString ts(qint64 msecs)
|
|
{
|
|
// TODO: make this UTC so that tests don't vary by where they're run
|
|
return QDateTime::fromMSecsSinceEpoch(msecs).toString(Qt::ISODate); //FIXME? LocalTime?
|
|
}
|
|
|
|
void EventList::AddEvent(qint64 time, EventStoreType data)
|
|
{
|
|
// Apply gain & offset
|
|
EventDataType val = EventDataType(data) * m_gain; // ignoring m_offset
|
|
|
|
if (m_update_minmax) {
|
|
if (m_count == 0) {
|
|
m_max = m_min = val;
|
|
} else {
|
|
m_min = (val < m_min) ? val : m_min;
|
|
m_max = (val > m_max) ? val : m_max;
|
|
}
|
|
}
|
|
|
|
if (!m_first) {
|
|
m_first = time;
|
|
m_last = time;
|
|
}
|
|
|
|
if (m_first > time) {
|
|
// Crud.. Update all the previous records
|
|
// This really shouldn't happen.
|
|
qDebug() << "Unordered time detected in AddEvent()" << m_count << ts(m_first) << ts(time) << data;
|
|
|
|
qint32 delta = (m_first - time);
|
|
|
|
for (quint32 i = 0; i < m_count; ++i) {
|
|
m_time[i] += delta;
|
|
}
|
|
|
|
m_first = time;
|
|
}
|
|
|
|
if (m_last < time) {
|
|
m_last = time;
|
|
}
|
|
|
|
quint32 delta = (time - m_first);
|
|
|
|
m_data.push_back(data);
|
|
m_time.push_back(delta);
|
|
m_count++;
|
|
}
|
|
|
|
void EventList::AddEvent(qint64 time, EventStoreType data, EventStoreType data2)
|
|
{
|
|
AddEvent(time, data);
|
|
|
|
if (!m_second_field)
|
|
return;
|
|
|
|
m_min2 = (data2 < m_min2) ? data2 : m_min2;
|
|
m_max2 = (data2 > m_max2) ? data2 : m_max2;
|
|
|
|
m_data2.push_back(data2);
|
|
}
|
|
|
|
// Adds a consecutive waveform chunk
|
|
void EventList::AddWaveform(qint64 start, qint16 *data, int recs, qint64 duration)
|
|
{
|
|
if (m_type != EVL_Waveform) {
|
|
qWarning() << "Attempted to add waveform data to non-waveform object";
|
|
return;
|
|
}
|
|
|
|
if (!m_rate) {
|
|
qWarning() << "Attempted to add waveform without setting sample rate";
|
|
return;
|
|
}
|
|
|
|
qint64 last = start + duration;
|
|
|
|
if (!m_first) {
|
|
m_first = start;
|
|
m_last = last;
|
|
}
|
|
|
|
if (m_last > start) {
|
|
//qWarning() << "Attempted to add waveform with previous timestamp";
|
|
// return;
|
|
|
|
// technically start should equal m_last+1 sample.. check this too.
|
|
}
|
|
|
|
if (m_last < last) {
|
|
m_last = last;
|
|
}
|
|
|
|
// TODO: Check waveform chunk really is contiguous
|
|
//double rate=duration/recs;
|
|
|
|
//realloc buffers.
|
|
int r = m_count;
|
|
m_count += recs;
|
|
m_data.resize(m_count);
|
|
|
|
// EventStoreType *edata = m_data.data();
|
|
|
|
//EventStoreType raw;
|
|
const qint16 *sp = data;
|
|
const qint16 *ep = data + recs;
|
|
EventStoreType *dp = (EventStoreType *)m_data.data()+r;
|
|
// EventStoreType *dp = &edata[r];
|
|
|
|
if (m_update_minmax) {
|
|
EventDataType min = m_min, max = m_max, val, gain = m_gain;
|
|
|
|
memcpy(dp, sp, recs*2);
|
|
|
|
for (sp = data; sp < ep; ++sp) {
|
|
// *dp++ = raw = *sp;
|
|
val = EventDataType(*sp) * gain + m_offset;
|
|
|
|
if (min > val) { min = val; }
|
|
|
|
if (max < val) { max = val; }
|
|
}
|
|
|
|
m_min = min;
|
|
m_max = max;
|
|
} else {
|
|
//register EventDataType val,gain=m_gain;
|
|
for (int i=0; i < recs; ++i) {
|
|
m_data[i] = *sp++;
|
|
}
|
|
// for (sp = data; sp < ep; ++sp) {
|
|
// *dp++ = *sp;
|
|
// //val=EventDataType(raw)*gain;
|
|
// }
|
|
}
|
|
|
|
}
|
|
void EventList::AddWaveform(qint64 start, unsigned char *data, int recs, qint64 duration)
|
|
{
|
|
if (m_type != EVL_Waveform) {
|
|
qWarning() << "Attempted to add waveform data to non-waveform object";
|
|
return;
|
|
}
|
|
|
|
if (!m_rate) {
|
|
qWarning() << "Attempted to add waveform without setting sample rate";
|
|
return;
|
|
}
|
|
|
|
// duration=recs*rate;
|
|
qint64 last = start + duration;
|
|
|
|
if (!m_first) {
|
|
m_first = start;
|
|
m_last = last;
|
|
}
|
|
|
|
if (m_last > start) {
|
|
//qWarning() << "Attempted to add waveform with previous timestamp";
|
|
// return;
|
|
|
|
// technically start should equal m_last+1 sample.. check this too.
|
|
}
|
|
|
|
if (m_last < last) {
|
|
m_last = last;
|
|
}
|
|
|
|
// TODO: Check waveform chunk really is contiguos
|
|
|
|
//realloc buffers.
|
|
int r = m_count;
|
|
m_count += recs;
|
|
m_data.resize(m_count);
|
|
|
|
EventStoreType *edata = m_data.data();
|
|
EventStoreType raw;
|
|
EventDataType val;
|
|
|
|
unsigned char *sp;
|
|
unsigned char *ep = data + recs;
|
|
EventStoreType *dp = &edata[r];
|
|
|
|
if (m_update_minmax) {
|
|
// ignoring m_offset
|
|
for (sp = data; sp < ep; ++sp) {
|
|
raw = *sp;
|
|
val = EventDataType(raw) * m_gain;
|
|
|
|
if (m_min > val) { m_min = val; }
|
|
|
|
if (m_max < val) { m_max = val; }
|
|
|
|
*dp++ = raw;
|
|
}
|
|
} else {
|
|
for (sp = data; sp < ep; ++sp) {
|
|
raw = *sp;
|
|
//val = EventDataType(raw) * m_gain;
|
|
*dp++ = raw;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EventList::AddWaveform(qint64 start, char *data, int recs, qint64 duration)
|
|
{
|
|
if (m_type != EVL_Waveform) {
|
|
qWarning() << "Attempted to add waveform data to non-waveform object";
|
|
return;
|
|
}
|
|
|
|
if (!m_rate) {
|
|
qWarning() << "Attempted to add waveform without setting sample rate";
|
|
return;
|
|
}
|
|
|
|
// duration=recs*rate;
|
|
qint64 last = start + duration;
|
|
|
|
if (!m_first) {
|
|
m_first = start;
|
|
m_last = last;
|
|
} else {
|
|
if (m_last > start) {
|
|
//qWarning() << "Attempted to add waveform with previous timestamp";
|
|
//return;
|
|
|
|
// technically start should equal m_last+1 sample.. check this too.
|
|
}
|
|
|
|
if (m_last < last) {
|
|
m_last = last;
|
|
}
|
|
}
|
|
|
|
// TODO: Check waveform chunk really is contiguos
|
|
|
|
//realloc buffers.
|
|
|
|
int r = m_count;
|
|
m_count += recs;
|
|
m_data.resize(m_count);
|
|
|
|
EventStoreType *edata = m_data.data();
|
|
EventStoreType raw;
|
|
EventDataType val; // FIXME: sstangl: accesses random memory
|
|
|
|
char *sp;
|
|
char *ep = data + recs;
|
|
EventStoreType *dp = &edata[r];
|
|
|
|
if (m_update_minmax) {
|
|
for (sp = data; sp < ep; ++sp) {
|
|
raw = *sp;
|
|
val = EventDataType(raw) * m_gain + m_offset;
|
|
|
|
if (m_min > val) { m_min = val; }
|
|
if (m_max < val) { m_max = val; }
|
|
|
|
*dp++ = raw;
|
|
}
|
|
} else {
|
|
for (sp = data; sp < ep; ++sp) {
|
|
raw = *sp;
|
|
// val = EventDataType(raw) * m_gain + m_offset;
|
|
*dp++ = raw;
|
|
}
|
|
}
|
|
}
|