diff --git a/CMakeLists.txt b/CMakeLists.txt index d02f0f5..6cd54a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,28 @@ project(DbCoreLib) +find_package(Qt5Core CONFIG REQUIRED) +find_package(Qt5Test CONFIG REQUIRED) +find_package(Qt5LinguistTools CONFIG REQUIRED) + enable_testing() set(HEADERS cpp14polyfills.h dbcorelib_global.h + fifostream.h fixedsizematrix.h randomdevice.h + waverecorder.h + utils/datastreamutils.h utils/fileutils.h utils/jsonutils.h utils/timeutils.h ) set(SOURCES + fifostream.cpp randomdevice.cpp + waverecorder.cpp utils/fileutils.cpp utils/jsonutils.cpp utils/timeutils.cpp diff --git a/fifostream.cpp b/fifostream.cpp new file mode 100644 index 0000000..eab8123 --- /dev/null +++ b/fifostream.cpp @@ -0,0 +1,30 @@ +#include "fifostream.h" + +// system includes +#include +#include + +FifoStream::FifoStream(QObject *parent) : + QIODevice(parent) +{ + setOpenMode(QIODevice::ReadWrite); +} + +qint64 FifoStream::bytesAvailable() const +{ + return m_buffer.size(); +} + +qint64 FifoStream::readData(char *data, qint64 maxlen) +{ + const int len = std::min(int(maxlen), int(m_buffer.size())); + std::memcpy(data, m_buffer.data(), len); + m_buffer.remove(0, len); + return len; +} + +qint64 FifoStream::writeData(const char *data, qint64 len) +{ + m_buffer.append(data, len); + return len; +} diff --git a/fifostream.h b/fifostream.h new file mode 100644 index 0000000..acad1e3 --- /dev/null +++ b/fifostream.h @@ -0,0 +1,23 @@ +#pragma once + +#include "dbcorelib_global.h" +#include + +#include + +class DBCORELIB_EXPORT FifoStream : public QIODevice +{ + Q_OBJECT + +public: + FifoStream(QObject *parent = Q_NULLPTR); + + qint64 bytesAvailable() const Q_DECL_OVERRIDE; + +protected: + qint64 readData(char *data, qint64 maxlen) Q_DECL_OVERRIDE; + qint64 writeData(const char *data, qint64 len) Q_DECL_OVERRIDE; + +private: + QByteArray m_buffer; +}; diff --git a/randomdevice.h b/randomdevice.h index 8d7cf13..be7c76b 100644 --- a/randomdevice.h +++ b/randomdevice.h @@ -1,8 +1,9 @@ #pragma once +#include "dbcorelib_global.h" #include -class RandomDevice : public QIODevice +class DBCORELIB_EXPORT RandomDevice : public QIODevice { Q_OBJECT diff --git a/utils/datastreamutils.h b/utils/datastreamutils.h new file mode 100644 index 0000000..4fd8f0a --- /dev/null +++ b/utils/datastreamutils.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include + +template +inline QDataStream &operator>>(QDataStream &s, std::array &l) +{ + for(auto iter = std::begin(l); iter != std::end(l); iter++) + s >> *iter; + return s; +} + +template +inline QDataStream &operator<<(QDataStream &s, const std::array &l) +{ + for(auto iter = std::begin(l); iter != std::end(l); iter++) + s << *iter; + return s; +} diff --git a/waverecorder.cpp b/waverecorder.cpp new file mode 100644 index 0000000..46ccae3 --- /dev/null +++ b/waverecorder.cpp @@ -0,0 +1,41 @@ +#include "waverecorder.h" + +// Qt includes +#include + +// system includes +#include + +WaveRecorder::WaveRecorder(const quint16 channels, const quint32 frequency, const QString &filename) : + m_file(filename), + m_dataStream(&m_file) +{ + m_dataStream.setByteOrder(QDataStream::LittleEndian); + + if(!m_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) + throw std::runtime_error(QString("Could open file %0 because %1").arg(m_file.fileName(), m_file.errorString()).toStdString()); + + m_dataStream << quint8('R') << quint8('I') << quint8('F') << quint8('F'); + m_dataStream << quint32(0); + + m_dataStream << quint8('W') << quint8('A') << quint8('V') << quint8('E'); + + m_dataStream << quint8('f') << quint8('m') << quint8('t') << quint8(' '); + m_dataStream << quint32(16); + m_dataStream << quint16(1); // audio format (pcm) + m_dataStream << channels; + m_dataStream << frequency; + m_dataStream << quint32(frequency * channels * sizeof(qint32)); // byte rate + m_dataStream << quint16(sizeof(qint32) * channels); // block align + m_dataStream << quint16(sizeof(qint32) * 8); // bits per sample + + m_dataStream << quint8('d') << quint8('a') << quint8('t') << quint8('a'); + m_dataStream << quint32(0); + + m_dataStream.setByteOrder(QDataStream::BigEndian); +} + +void WaveRecorder::addSample(const qint32 sample) +{ + m_dataStream << sample; +} diff --git a/waverecorder.h b/waverecorder.h new file mode 100644 index 0000000..6592157 --- /dev/null +++ b/waverecorder.h @@ -0,0 +1,31 @@ +#pragma once + +#include "dbcorelib_global.h" +#include + +// Qt includes +#include +#include + +// forward declarations +template class QVector; + +class DBCORELIB_EXPORT WaveRecorder : public QObject +{ + Q_OBJECT + +public: + explicit WaveRecorder(const quint16 channels, const quint32 frequency, const QString &filename); + +public Q_SLOTS: + void addSample(const qint32 sample); + +private: + quint32 m_size = 0; + quint32 m_samplesCount = 0; + quint32 m_time = 0; + quint32 m_timeSamples = 0; + + QFile m_file; + QDataStream m_dataStream; +};