summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorChristian Daniel <cd@maintech.de>2013-03-22 11:18:30 +0100
committerChristian Daniel <cd@maintech.de>2013-03-22 11:18:30 +0100
commiteca56e35be841396f6c57bab540a3e1503253d56 (patch)
tree4a0a29cd53a84339e56754c32bf67391c83494fe /include
parent2c8c930b39fe069b36d81caa00401d9ac182a9d8 (diff)
monster rework
- pluginify whole project - reorganize directory structure - fix PortAudio detection script - implement generic channelizer - fix several OpenGL problems - rework presets - add audio mixing - too many more
Diffstat (limited to 'include')
-rw-r--r--include/dsp/channelmarker.h39
-rw-r--r--include/dsp/dsptypes.h54
-rw-r--r--include/dsp/kissfft.h391
-rw-r--r--include/dsp/samplefifo.h68
-rw-r--r--include/dsp/samplesink.h42
-rw-r--r--include/dsp/samplesource/samplesource.h60
-rw-r--r--include/dsp/threadedsamplesink.h40
-rw-r--r--include/plugin/pluginapi.h56
-rw-r--r--include/plugin/plugingui.h29
-rw-r--r--include/plugin/plugininterface.h48
-rw-r--r--include/util/message.h50
-rw-r--r--include/util/messagequeue.h30
-rw-r--r--include/util/miniz.h7
-rw-r--r--include/util/simpleserializer.h111
-rw-r--r--include/util/spinlock.h39
15 files changed, 1064 insertions, 0 deletions
diff --git a/include/dsp/channelmarker.h b/include/dsp/channelmarker.h
new file mode 100644
index 0000000..229e7f1
--- /dev/null
+++ b/include/dsp/channelmarker.h
@@ -0,0 +1,39 @@
+#ifndef INCLUDE_CHANNELMARKER_H
+#define INCLUDE_CHANNELMARKER_H
+
+#include <QObject>
+#include <QColor>
+
+class ChannelMarker : public QObject {
+ Q_OBJECT
+
+public:
+ ChannelMarker(QObject* parent = NULL);
+
+ void setTitle(const QString& title);
+ const QString& getTitle() const { return m_title; }
+
+ void setCenterFrequency(int centerFrequency);
+ int getCenterFrequency() const { return m_centerFrequency; }
+
+ void setBandwidth(int bandwidth);
+ int getBandwidth() const { return m_bandwidth; }
+
+ void setVisible(bool visible);
+ bool getVisible() const { return m_visible; }
+
+ void setColor(const QColor& color);
+ const QColor& getColor() const { return m_color; }
+
+protected:
+ QString m_title;
+ int m_centerFrequency;
+ int m_bandwidth;
+ bool m_visible;
+ QColor m_color;
+
+signals:
+ void changed();
+};
+
+#endif // INCLUDE_CHANNELMARKER_H
diff --git a/include/dsp/dsptypes.h b/include/dsp/dsptypes.h
new file mode 100644
index 0000000..b6bbf67
--- /dev/null
+++ b/include/dsp/dsptypes.h
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDE_DSPTYPES_H
+#define INCLUDE_DSPTYPES_H
+
+#include <complex>
+#include <vector>
+#include <QtGlobal>
+
+typedef float Real;
+typedef std::complex<Real> Complex;
+
+typedef qint16 FixReal;
+
+#pragma pack(push, 1)
+struct Sample {
+ Sample() {}
+ Sample(FixReal real) : m_real(real), m_imag(0) {}
+ Sample(FixReal real, FixReal imag) : m_real(real), m_imag(imag) {}
+ Sample(const Sample& other) : m_real(other.m_real), m_imag(other.m_imag) {}
+ Sample& operator=(const Sample& other) { m_real = other.m_real; m_imag = other.m_imag; return *this; }
+
+ Sample& operator+=(const Sample& other) { m_real += other.m_real; m_imag += other.m_imag; return *this; }
+ Sample& operator-=(const Sample& other) { m_real -= other.m_real; m_imag -= other.m_imag; return *this; }
+
+ void setReal(FixReal v) { m_real = v; }
+ void setImag(FixReal v) { m_imag = v; }
+
+ FixReal real() const { return m_real; }
+ FixReal imag() const { return m_imag; }
+
+ FixReal m_real;
+ FixReal m_imag;
+};
+#pragma pack(pop)
+
+typedef std::vector<Sample> SampleVector;
+
+#endif // INCLUDE_DSPTYPES_H
diff --git a/include/dsp/kissfft.h b/include/dsp/kissfft.h
new file mode 100644
index 0000000..ba1256c
--- /dev/null
+++ b/include/dsp/kissfft.h
@@ -0,0 +1,391 @@
+#ifndef INCLUDE_KISSFFT_H
+#define INCLUDE_KISSFFT_H
+
+#include <complex>
+#include <vector>
+
+/*
+Copyright (c) 2003-2010 Mark Borgerding
+
+All rights reserved.
+
+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 author nor the names of any 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 OWNER 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.
+*/
+
+namespace kissfft_utils {
+
+ template<typename T_scalar, typename T_complex>
+ struct traits {
+ typedef T_scalar scalar_type;
+ typedef T_complex cpx_type;
+ void fill_twiddles(std::complex<T_scalar>* dst, int nfft, bool inverse)
+ {
+ T_scalar phinc = (inverse ? 2 : -2) * acos((T_scalar)-1) / nfft;
+ for(int i = 0; i < nfft; ++i)
+ dst[i] = exp(std::complex<T_scalar>(0, i * phinc));
+ }
+
+ void prepare(std::vector<std::complex<T_scalar> >& dst, int nfft, bool inverse, std::vector<int>& stageRadix, std::vector<int>& stageRemainder)
+ {
+ _twiddles.resize(nfft);
+ fill_twiddles(&_twiddles[0], nfft, inverse);
+ dst = _twiddles;
+
+ //factorize
+ //start factoring out 4's, then 2's, then 3,5,7,9,...
+ int n = nfft;
+ int p = 4;
+ do {
+ while(n % p) {
+ switch(p) {
+ case 4:
+ p = 2;
+ break;
+ case 2:
+ p = 3;
+ break;
+ default:
+ p += 2;
+ break;
+ }
+ if(p * p > n)
+ p = n;// no more factors
+ }
+ n /= p;
+ stageRadix.push_back(p);
+ stageRemainder.push_back(n);
+ } while(n > 1);
+ }
+ std::vector<cpx_type> _twiddles;
+
+ const cpx_type twiddle(int i)
+ {
+ return _twiddles[i];
+ }
+ };
+
+} // namespace
+
+template<typename T_Scalar, typename T_Complex, typename T_traits = kissfft_utils::traits<T_Scalar, T_Complex> >
+class kissfft {
+public:
+ typedef T_traits traits_type;
+ typedef typename traits_type::scalar_type scalar_type;
+ typedef typename traits_type::cpx_type cpx_type;
+
+ kissfft()
+ {
+ }
+
+ kissfft(int nfft, bool inverse, const traits_type & traits = traits_type()) :
+ _nfft(nfft), _inverse(inverse), _traits(traits)
+ {
+ _traits.prepare(_twiddles, _nfft, _inverse, _stageRadix, _stageRemainder);
+ }
+
+ void configure(int nfft, bool inverse, const traits_type & traits = traits_type())
+ {
+ _twiddles.clear();
+ _stageRadix.clear();
+ _stageRemainder.clear();
+
+ _nfft = nfft;
+ _inverse = inverse;
+ _traits = traits;
+ _traits.prepare(_twiddles, _nfft, _inverse, _stageRadix, _stageRemainder);
+ }
+
+ void transform(const cpx_type* src, cpx_type* dst)
+ {
+ kf_work(0, dst, src, 1, 1);
+ }
+
+private:
+ void kf_work(int stage, cpx_type* Fout, const cpx_type* f, size_t fstride, size_t in_stride)
+ {
+ int p = _stageRadix[stage];
+ int m = _stageRemainder[stage];
+ cpx_type * Fout_beg = Fout;
+ cpx_type * Fout_end = Fout + p * m;
+
+ if(m == 1) {
+ do {
+ *Fout = *f;
+ f += fstride * in_stride;
+ } while(++Fout != Fout_end);
+ } else {
+ do {
+ // recursive call:
+ // DFT of size m*p performed by doing
+ // p instances of smaller DFTs of size m,
+ // each one takes a decimated version of the input
+ kf_work(stage + 1, Fout, f, fstride * p, in_stride);
+ f += fstride * in_stride;
+ } while((Fout += m) != Fout_end);
+ }
+
+ Fout = Fout_beg;
+
+ // recombine the p smaller DFTs
+ switch(p) {
+ case 2:
+ kf_bfly2(Fout, fstride, m);
+ break;
+ case 3:
+ kf_bfly3(Fout, fstride, m);
+ break;
+ case 4:
+ kf_bfly4(Fout, fstride, m);
+ break;
+ case 5:
+ kf_bfly5(Fout, fstride, m);
+ break;
+ default:
+ kf_bfly_generic(Fout, fstride, m, p);
+ break;
+ }
+ }
+
+ // these were #define macros in the original kiss_fft
+ void C_ADD(cpx_type& c, const cpx_type& a, const cpx_type& b)
+ {
+ c = a + b;
+ }
+ void C_MUL(cpx_type& c, const cpx_type& a, const cpx_type& b)
+ {
+ //c = a * b;
+ c = cpx_type(a.real() * b.real() - a.imag() * b.imag(), a.real() * b.imag() + a.imag() * b.real());
+ }
+ void C_SUB(cpx_type& c, const cpx_type& a, const cpx_type& b)
+ {
+ c = a - b;
+ }
+ void C_ADDTO(cpx_type& c, const cpx_type& a)
+ {
+ c += a;
+ }
+ void C_FIXDIV(cpx_type&, int)
+ {
+ } // NO-OP for float types
+ scalar_type S_MUL(const scalar_type& a, const scalar_type& b)
+ {
+ return a * b;
+ }
+ scalar_type HALF_OF(const scalar_type& a)
+ {
+ return a * .5;
+ }
+ void C_MULBYSCALAR(cpx_type& c, const scalar_type& a)
+ {
+ c *= a;
+ }
+
+ void kf_bfly2(cpx_type* Fout, const size_t fstride, int m)
+ {
+ for(int k = 0; k < m; ++k) {
+ //cpx_type t = Fout[m + k] * _traits.twiddle(k * fstride);
+ cpx_type t;
+ C_MUL(t, Fout[m + k], _traits.twiddle(k * fstride));
+ Fout[m + k] = Fout[k] - t;
+ Fout[k] += t;
+ }
+ }
+
+ void kf_bfly4(cpx_type* Fout, const size_t fstride, const size_t m)
+ {
+ cpx_type scratch[7];
+ int negative_if_inverse = _inverse * -2 + 1;
+ for(size_t k = 0; k < m; ++k) {
+ //scratch[0] = Fout[k + m] * _traits.twiddle(k * fstride);
+ C_MUL(scratch[0], Fout[k + m], _traits.twiddle(k * fstride));
+ C_MUL(scratch[1], Fout[k + 2 * m], _traits.twiddle(k * fstride * 2));
+ C_MUL(scratch[2], Fout[k + 3 * m], _traits.twiddle(k * fstride * 3));
+ scratch[5] = Fout[k] - scratch[1];
+
+ Fout[k] += scratch[1];
+ scratch[3] = scratch[0] + scratch[2];
+ scratch[4] = scratch[0] - scratch[2];
+ scratch[4] = cpx_type(scratch[4].imag() * negative_if_inverse, -scratch[4].real() * negative_if_inverse);
+
+ Fout[k + 2 * m] = Fout[k] - scratch[3];
+ Fout[k] += scratch[3];
+ Fout[k + m] = scratch[5] + scratch[4];
+ Fout[k + 3 * m] = scratch[5] - scratch[4];
+ }
+ }
+
+ void kf_bfly3(cpx_type* Fout, const size_t fstride, const size_t m)
+ {
+ size_t k = m;
+ const size_t m2 = 2 * m;
+ cpx_type* tw1;
+ cpx_type* tw2;
+ cpx_type scratch[5];
+ cpx_type epi3;
+ epi3 = _twiddles[fstride * m];
+ tw1 = tw2 = &_twiddles[0];
+
+ do {
+ C_FIXDIV(*Fout, 3);
+ C_FIXDIV(Fout[m], 3);
+ C_FIXDIV(Fout[m2], 3);
+
+ C_MUL(scratch[1], Fout[m], *tw1);
+ C_MUL(scratch[2], Fout[m2], *tw2);
+
+ C_ADD(scratch[3], scratch[1], scratch[2]);
+ C_SUB(scratch[0], scratch[1], scratch[2]);
+ tw1 += fstride;
+ tw2 += fstride * 2;
+
+ Fout[m] = cpx_type(Fout->real() - HALF_OF(scratch[3].real()), Fout->imag() - HALF_OF(scratch[3].imag()));
+
+ C_MULBYSCALAR(scratch[0], epi3.imag());
+
+ C_ADDTO(*Fout, scratch[3]);
+
+ Fout[m2] = cpx_type(Fout[m].real() + scratch[0].imag(), Fout[m].imag() - scratch[0].real());
+
+ C_ADDTO(Fout[m], cpx_type(-scratch[0].imag(), scratch[0].real()));
+ ++Fout;
+ } while(--k);
+ }
+
+ void kf_bfly5(cpx_type* Fout, const size_t fstride, const size_t m)
+ {
+ cpx_type* Fout0;
+ cpx_type* Fout1;
+ cpx_type* Fout2;
+ cpx_type* Fout3;
+ cpx_type* Fout4;
+ size_t u;
+ cpx_type scratch[13];
+ cpx_type* twiddles = &_twiddles[0];
+ cpx_type* tw;
+ cpx_type ya, yb;
+ ya = twiddles[fstride * m];
+ yb = twiddles[fstride * 2 * m];
+
+ Fout0 = Fout;
+ Fout1 = Fout0 + m;
+ Fout2 = Fout0 + 2 * m;
+ Fout3 = Fout0 + 3 * m;
+ Fout4 = Fout0 + 4 * m;
+
+ tw = twiddles;
+ for(u = 0; u < m; ++u) {
+ C_FIXDIV(*Fout0, 5);
+ C_FIXDIV(*Fout1, 5);
+ C_FIXDIV(*Fout2, 5);
+ C_FIXDIV(*Fout3, 5);
+ C_FIXDIV(*Fout4, 5);
+ scratch[0] = *Fout0;
+
+ C_MUL(scratch[1], *Fout1, tw[u * fstride]);
+ C_MUL(scratch[2], *Fout2, tw[2 * u * fstride]);
+ C_MUL(scratch[3], *Fout3, tw[3 * u * fstride]);
+ C_MUL(scratch[4], *Fout4, tw[4 * u * fstride]);
+
+ C_ADD(scratch[7], scratch[1], scratch[4]);
+ C_SUB(scratch[10], scratch[1], scratch[4]);
+ C_ADD(scratch[8], scratch[2], scratch[3]);
+ C_SUB(scratch[9], scratch[2], scratch[3]);
+
+ C_ADDTO(*Fout0, scratch[7]);
+ C_ADDTO(*Fout0, scratch[8]);
+
+ scratch[5] = scratch[0] + cpx_type(S_MUL(scratch[7].real(), ya.real()) + S_MUL(scratch[8].real(), yb.real()), S_MUL(scratch[7].imag(), ya.real())
+ + S_MUL(scratch[8].imag(), yb.real()));
+
+ scratch[6] = cpx_type(S_MUL(scratch[10].imag(), ya.imag()) + S_MUL(scratch[9].imag(), yb.imag()), -S_MUL(scratch[10].real(), ya.imag()) - S_MUL(
+ scratch[9].real(), yb.imag()));
+
+ C_SUB(*Fout1, scratch[5], scratch[6]);
+ C_ADD(*Fout4, scratch[5], scratch[6]);
+
+ scratch[11] = scratch[0] + cpx_type(S_MUL(scratch[7].real(), yb.real()) + S_MUL(scratch[8].real(), ya.real()), S_MUL(scratch[7].imag(), yb.real())
+ + S_MUL(scratch[8].imag(), ya.real()));
+
+ scratch[12] = cpx_type(-S_MUL(scratch[10].imag(), yb.imag()) + S_MUL(scratch[9].imag(), ya.imag()), S_MUL(scratch[10].real(), yb.imag()) - S_MUL(
+ scratch[9].real(), ya.imag()));
+
+ C_ADD(*Fout2, scratch[11], scratch[12]);
+ C_SUB(*Fout3, scratch[11], scratch[12]);
+
+ ++Fout0;
+ ++Fout1;
+ ++Fout2;
+ ++Fout3;
+ ++Fout4;
+ }
+ }
+
+ /* perform the butterfly for one stage of a mixed radix FFT */
+ void kf_bfly_generic(cpx_type* Fout, const size_t fstride, int m, int p)
+ {
+ int u;
+ int k;
+ int q1;
+ int q;
+ cpx_type* twiddles = &_twiddles[0];
+ cpx_type t;
+ int Norig = _nfft;
+ cpx_type* scratchbuf = new cpx_type[p];
+
+ for(u = 0; u < m; ++u) {
+ k = u;
+ for(q1 = 0; q1 < p; ++q1) {
+ scratchbuf[q1] = Fout[k];
+ C_FIXDIV(scratchbuf[q1], p);
+ k += m;
+ }
+
+ k = u;
+ for(q1 = 0; q1 < p; ++q1) {
+ int twidx = 0;
+ Fout[k] = scratchbuf[0];
+ for(q = 1; q < p; ++q) {
+ twidx += fstride * k;
+ if(twidx >= Norig)
+ twidx -= Norig;
+ C_MUL(t, scratchbuf[q], twiddles[twidx]);
+ C_ADDTO(Fout[k], t);
+ }
+ k += m;
+ }
+ }
+
+ delete[] scratchbuf;
+ }
+
+ int _nfft;
+ bool _inverse;
+ std::vector<cpx_type> _twiddles;
+ std::vector<int> _stageRadix;
+ std::vector<int> _stageRemainder;
+ traits_type _traits;
+};
+#endif
diff --git a/include/dsp/samplefifo.h b/include/dsp/samplefifo.h
new file mode 100644
index 0000000..2ab3110
--- /dev/null
+++ b/include/dsp/samplefifo.h
@@ -0,0 +1,68 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDE_SAMPLEFIFO_H
+#define INCLUDE_SAMPLEFIFO_H
+
+#include <QObject>
+#include <QMutex>
+#include <QTime>
+#include "dsp/dsptypes.h"
+
+class SampleFifo : public QObject {
+ Q_OBJECT
+
+private:
+ QMutex m_mutex;
+ QTime m_msgRateTimer;
+ int m_suppressed;
+
+ SampleVector m_data;
+
+ uint m_size;
+ uint m_fill;
+ uint m_head;
+ uint m_tail;
+
+ void create(uint s);
+
+public:
+ SampleFifo(QObject* parent = NULL);
+ SampleFifo(int size, QObject* parent = NULL);
+ ~SampleFifo();
+
+ SampleFifo(const SampleFifo&);
+ SampleFifo& operator=(const SampleFifo&);
+
+ bool setSize(int size);
+ inline uint fill() const { return m_fill; }
+
+ uint write(const quint8* data, uint count);
+ uint write(SampleVector::const_iterator begin, SampleVector::const_iterator end);
+
+ uint read(SampleVector::iterator begin, SampleVector::iterator end);
+
+ uint readBegin(uint count,
+ SampleVector::iterator* part1Begin, SampleVector::iterator* part1End,
+ SampleVector::iterator* part2Begin, SampleVector::iterator* part2End);
+ uint readCommit(uint count);
+
+signals:
+ void dataReady();
+};
+
+#endif // INCLUDE_SAMPLEFIFO_H
diff --git a/include/dsp/samplesink.h b/include/dsp/samplesink.h
new file mode 100644
index 0000000..8a02bc8
--- /dev/null
+++ b/include/dsp/samplesink.h
@@ -0,0 +1,42 @@
+#ifndef INCLUDE_SAMPLESINK_H
+#define INCLUDE_SAMPLESINK_H
+
+#include "dsptypes.h"
+
+class Message;
+
+class SampleSink {
+public:
+ SampleSink();
+ virtual ~SampleSink();
+
+ virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool firstOfBurst) = 0;
+ virtual void start() = 0;
+ virtual void stop() = 0;
+ virtual bool handleMessage(Message* cmd) = 0;
+};
+
+#endif // INCLUDE_SAMPLESINK_H
+
+#if 0
+#ifndef INCLUDE_SAMPLESINK_H
+#define INCLUDE_SAMPLESINK_H
+
+#include "dsptypes.h"
+
+class SampleSink {
+public:
+ SampleSink();
+
+ virtual size_t workUnitSize() = 0;
+
+ void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end);
+ virtual size_t work(SampleVector::const_iterator begin, SampleVector::const_iterator end) = 0;
+
+private:
+ SampleVector m_sinkBuffer;
+ size_t m_sinkBufferFill;
+};
+
+#endif // INCLUDE_SAMPLESINK_H
+#endif
diff --git a/include/dsp/samplesource/samplesource.h b/include/dsp/samplesource/samplesource.h
new file mode 100644
index 0000000..0328a90
--- /dev/null
+++ b/include/dsp/samplesource/samplesource.h
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDE_SAMPLESOURCE_H
+#define INCLUDE_SAMPLESOURCE_H
+
+#include <QtGlobal>
+#include "dsp/samplefifo.h"
+#include "util/message.h"
+
+class PluginGUI;
+class MessageQueue;
+
+class SampleSource {
+public:
+ struct GeneralSettings {
+ quint64 m_centerFrequency;
+
+ GeneralSettings();
+ void resetToDefaults();
+ QByteArray serialize() const;
+ bool deserialize(const QByteArray& data);
+ };
+
+ SampleSource(MessageQueue* guiMessageQueue);
+ virtual ~SampleSource();
+
+ virtual bool startInput(int device) = 0;
+ virtual void stopInput() = 0;
+
+ virtual const QString& getDeviceDescription() const = 0;
+ virtual int getSampleRate() const = 0;
+ virtual quint64 getCenterFrequency() const = 0;
+
+ virtual bool handleMessage(Message* message) = 0;
+
+ SampleFifo* getSampleFifo() { return &m_sampleFifo; }
+
+protected:
+ SampleFifo m_sampleFifo;
+ MessageQueue* m_guiMessageQueue;
+
+ GeneralSettings m_generalSettings;
+};
+
+#endif // INCLUDE_SAMPLESOURCE_H
diff --git a/include/dsp/threadedsamplesink.h b/include/dsp/threadedsamplesink.h
new file mode 100644
index 0000000..f7e704e
--- /dev/null
+++ b/include/dsp/threadedsamplesink.h
@@ -0,0 +1,40 @@
+#ifndef INCLUDE_THREADEDSAMPLESINK_H
+#define INCLUDE_THREADEDSAMPLESINK_H
+
+#include <QMutex>
+#include "samplesink.h"
+#include "dsp/samplefifo.h"
+#include "util/messagequeue.h"
+
+class QThread;
+class SampleSink;
+
+class ThreadedSampleSink : public QObject, public SampleSink {
+ Q_OBJECT
+
+public:
+ ThreadedSampleSink(SampleSink* sampleSink);
+ virtual ~ThreadedSampleSink();
+
+ MessageQueue* getMessageQueue() { return &m_messageQueue; }
+
+ void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool firstOfBurst);
+ void start();
+ void stop();
+ bool handleMessage(Message* cmd);
+
+protected:
+ QMutex m_mutex;
+ QThread* m_thread;
+ MessageQueue m_messageQueue;
+ SampleFifo m_sampleFifo;
+ SampleSink* m_sampleSink;
+
+protected slots:
+ void handleData();
+ void handleMessages();
+ void threadStarted();
+ void threadFinished();
+};
+
+#endif // INCLUDE_THREADEDSAMPLESINK_H
diff --git a/include/plugin/pluginapi.h b/include/plugin/pluginapi.h
new file mode 100644
index 0000000..515eb0d
--- /dev/null
+++ b/include/plugin/pluginapi.h
@@ -0,0 +1,56 @@
+#ifndef INCLUDE_PLUGINAPI_H
+#define INCLUDE_PLUGINAPI_H
+
+#include <QObject>
+
+class QDockWidget;
+class QAction;
+
+class PluginManager;
+class PluginInterface;
+class SampleSource;
+class SampleSink;
+class DSPEngine;
+class AudioFifo;
+class MessageQueue;
+class MainWindow;
+class ChannelMarker;
+class PluginGUI;
+
+class PluginAPI : public QObject {
+ Q_OBJECT
+
+public:
+ // MainWindow access
+ QDockWidget* createMainWindowDock(Qt::DockWidgetArea dockWidgetArea, const QString& title);
+ MessageQueue* getMainWindowMessageQueue();
+
+ // Demodulator stuff
+ void registerDemodulator(const QString& demodName, PluginInterface* plugin, QAction* action);
+ void registerDemodulatorInstance(const QString& demodName, PluginGUI* pluginGUI);
+
+ void addChannelMarker(ChannelMarker* channelMarker);
+ void removeChannelMarker(ChannelMarker* channelMarker);
+
+ // DSPEngine access
+ void setSampleSource(SampleSource* sampleSource);
+ void addSampleSink(SampleSink* sampleSink);
+ void removeSampleSink(SampleSink* sampleSink);
+ MessageQueue* getDSPEngineMessageQueue();
+ void addAudioSource(AudioFifo* audioFifo);
+ void removeAudioSource(AudioFifo* audioFifo);
+
+ // Sample Source stuff
+ void registerSampleSource(const QString& sourceName, PluginInterface* plugin);
+
+protected:
+ PluginManager* m_pluginManager;
+ MainWindow* m_mainWindow;
+ DSPEngine* m_dspEngine;
+
+ PluginAPI(PluginManager* pluginManager, MainWindow* mainWindow, DSPEngine* dspEngine);
+
+ friend class PluginManager;
+};
+
+#endif // INCLUDE_PLUGINAPI_H
diff --git a/include/plugin/plugingui.h b/include/plugin/plugingui.h
new file mode 100644
index 0000000..2e48079
--- /dev/null
+++ b/include/plugin/plugingui.h
@@ -0,0 +1,29 @@
+#ifndef INCLUDE_PLUGINGUI_H
+#define INCLUDE_PLUGINGUI_H
+
+#include <QWidget>
+
+class Message;
+
+class PluginGUI : public QWidget {
+ Q_OBJECT
+
+public:
+ PluginGUI(QWidget* parent = NULL);
+ virtual void destroy() = 0;
+
+ virtual void setWidgetName(const QString& name);
+
+ virtual void resetToDefaults() = 0;
+
+ virtual QByteArray serializeGeneral() const;
+ virtual bool deserializeGeneral(const QByteArray& data);
+ virtual quint64 getCenterFrequency() const;
+
+ virtual QByteArray serialize() const = 0;
+ virtual bool deserialize(const QByteArray& data) = 0;
+
+ virtual bool handleMessage(Message* message) = 0;
+};
+
+#endif // INCLUDE_PLUGINGUI_H
diff --git a/include/plugin/plugininterface.h b/include/plugin/plugininterface.h
new file mode 100644
index 0000000..15e3c5d
--- /dev/null
+++ b/include/plugin/plugininterface.h
@@ -0,0 +1,48 @@
+#ifndef INCLUDE_PLUGININTERFACE_H
+#define INCLUDE_PLUGININTERFACE_H
+
+#include <QtPlugin>
+#include <QString>
+
+struct PluginDescriptor {
+ // general plugin description
+ const QString& displayedName;
+ const QString& version;
+ const QString& copyright;
+ const QString& website;
+ bool licenseIsGPL;
+ const QString& sourceCodeURL;
+};
+
+class PluginAPI;
+class PluginGUI;
+
+class PluginInterface {
+public:
+ struct SampleSourceDevice {
+ QString displayedName;
+ QString name;
+ QByteArray address;
+
+ SampleSourceDevice(const QString& _displayedName, const QString& _name, const QByteArray& _address) :
+ displayedName(_displayedName),
+ name(_name),
+ address(_address)
+ { }
+ };
+ typedef QList<SampleSourceDevice> SampleSourceDevices;
+
+ virtual ~PluginInterface() { };
+
+ virtual const PluginDescriptor& getPluginDescriptor() const = 0;
+ virtual void initPlugin(PluginAPI* pluginAPI) = 0;
+
+ virtual PluginGUI* createDemod(const QString& demodName) { return NULL; }
+
+ virtual SampleSourceDevices enumSampleSources() { return SampleSourceDevices(); }
+ virtual PluginGUI* createSampleSource(const QString& sourceName, const QByteArray& address) { return NULL; }
+};
+
+Q_DECLARE_INTERFACE(PluginInterface, "de.maintech.SDRangelove.PluginInterface/0.1");
+
+#endif // INCLUDE_PLUGININTERFACE_H
diff --git a/include/util/message.h b/include/util/message.h
new file mode 100644
index 0000000..8718496
--- /dev/null
+++ b/include/util/message.h
@@ -0,0 +1,50 @@
+#ifndef INCLUDE_MESSAGE_H
+#define INCLUDE_MESSAGE_H
+
+#include <QAtomicInt>
+#include <QStringList>
+
+class MessageQueue;
+class QWaitCondition;
+class QMutex;
+
+class MessageRegistrator {
+public:
+ MessageRegistrator(const char* name);
+ int operator()() const { return m_registeredID; }
+
+ const char* name() const;
+
+private:
+ int m_registeredID;
+};
+
+class Message {
+public:
+ virtual ~Message();
+
+ void submit(MessageQueue* queue, void* destination = NULL);
+ int execute(MessageQueue* queue, void* destination = NULL);
+
+ void completed(int result = 0);
+
+ int id() const { return m_id; }
+ const char* name() const;
+ void* destination() const { return m_destination; }
+
+protected:
+ Message(int id);
+
+ // adressing
+ int m_id;
+ void* m_destination;
+
+ // stuff for synchronous messages
+ bool m_synchronous;
+ QWaitCondition* m_waitCondition;
+ QMutex* m_mutex;
+ QAtomicInt m_complete;
+ int m_result;
+};
+
+#endif // INCLUDE_MESSAGE_H
diff --git a/include/util/messagequeue.h b/include/util/messagequeue.h
new file mode 100644
index 0000000..bf99ea2
--- /dev/null
+++ b/include/util/messagequeue.h
@@ -0,0 +1,30 @@
+#ifndef INCLUDE_MESSAGEQUEUE_H
+#define INCLUDE_MESSAGEQUEUE_H
+
+#include <QObject>
+#include <QQueue>
+#include "spinlock.h"
+
+class Message;
+
+class MessageQueue : public QObject {
+ Q_OBJECT
+
+public:
+ MessageQueue(QObject* parent = NULL);
+ ~MessageQueue();
+
+ void submit(Message* message);
+ Message* accept();
+
+ int countPending();
+
+signals:
+ void messageEnqueued();
+
+private:
+ Spinlock m_lock;
+ QQueue<Message*> m_queue;
+};
+
+#endif // INCLUDE_MESSAGEQUEUE_H
diff --git a/include/util/miniz.h b/include/util/miniz.h
new file mode 100644
index 0000000..0882c06
--- /dev/null
+++ b/include/util/miniz.h
@@ -0,0 +1,7 @@
+#ifndef INCLUDE_MINIZ_H
+#define INCLUDE_MINIZ_H
+
+#define MINIZ_HEADER_FILE_ONLY
+#include "../../sdrapp/util/miniz.cpp"
+
+#endif // INCLUDE_MINIZ_H
diff --git a/include/util/simpleserializer.h b/include/util/simpleserializer.h
new file mode 100644
index 0000000..3893c32
--- /dev/null
+++ b/include/util/simpleserializer.h
@@ -0,0 +1,111 @@
+#ifndef INCLUDE_SIMPLESERIALIZER_H
+#define INCLUDE_SIMPLESERIALIZER_H
+
+#include <QString>
+#include <QMap>
+#include "dsp/dsptypes.h"
+
+class SimpleSerializer {
+public:
+ SimpleSerializer(quint32 version);
+
+ void writeS32(quint32 id, qint32 value);
+ void writeU32(quint32 id, quint32 value);
+ void writeS64(quint32 id, qint64 value);
+ void writeU64(quint32 id, quint64 value);
+ void writeFloat(quint32 id, float value);
+ void writeDouble(quint32 id, double value);
+ void writeReal(quint32 id, Real value)
+ {
+ if(sizeof(Real) == 4)
+ writeFloat(id, value);
+ else writeDouble(id, value);
+ }
+ void writeBool(quint32 id, bool value);
+ void writeString(quint32 id, const QString& value);
+ void writeBlob(quint32 id, const QByteArray& value);
+
+ const QByteArray& final();
+
+protected:
+ enum Type {
+ TSigned32 = 0,
+ TUnsigned32 = 1,
+ TSigned64 = 2,
+ TUnsigned64 = 3,
+ TFloat = 4,
+ TDouble = 5,
+ TBool = 6,
+ TString = 7,
+ TBlob = 8,
+ TVersion = 9
+ };
+
+ QByteArray m_data;
+ bool m_finalized;
+
+ bool writeTag(Type type, quint32 id, quint32 length);
+};
+
+class SimpleDeserializer {
+public:
+ SimpleDeserializer(const QByteArray& data);
+
+ bool readS32(quint32 id, qint32* result, qint32 def = 0) const;
+ bool readU32(quint32 id, quint32* result, quint32 def = 0) const;
+ bool readS64(quint32 id, qint64* result, qint64 def = 0) const;
+ bool readU64(quint32 id, quint64* result, quint64 def = 0) const;
+ bool readFloat(quint32 id, float* result, float def = 0) const;
+ bool readDouble(quint32 id, double* result, double def = 0) const;
+ bool readReal(quint32 id, Real* result, Real def = 0) const;
+ bool readBool(quint32 id, bool* result, bool def = false) const;
+ bool readString(quint32 id, QString* result, const QString& def = QString::null) const;
+ bool readBlob(quint32 id, QByteArray* result, const QByteArray& def = QByteArray()) const;
+
+ bool isValid() const { return m_valid; }
+ quint32 getVersion() const { return m_version; }
+ void dump() const;
+
+private:
+ enum Type {
+ TSigned32 = 0,
+ TUnsigned32 = 1,
+ TSigned64 = 2,
+ TUnsigned64 = 3,
+ TFloat = 4,
+ TDouble = 5,
+ TBool = 6,
+ TString = 7,
+ TBlob = 8,
+ TVersion = 9
+ };
+
+ struct Element {
+ Type type;
+ quint32 ofs;
+ quint32 length;
+
+ Element(Type _type, quint32 _ofs, quint32 _length) :
+ type(_type),
+ ofs(_ofs),
+ length(_length)
+ { }
+ };
+ typedef QMap<quint32, Element> Elements;
+
+ QByteArray m_data;
+ bool m_valid;
+ Elements m_elements;
+ quint32 m_version;
+
+ bool parseAll();
+ bool readTag(uint* readOfs, uint readEnd, Type* type, quint32* id, quint32* length) const;
+ quint8 readByte(uint* readOfs) const
+ {
+ quint8 res = m_data[*readOfs];
+ (*readOfs)++;
+ return res;
+ }
+};
+
+#endif // INCLUDE_SIMPLESERIALIZER_H
diff --git a/include/util/spinlock.h b/include/util/spinlock.h
new file mode 100644
index 0000000..78af0b6
--- /dev/null
+++ b/include/util/spinlock.h
@@ -0,0 +1,39 @@
+#ifndef INCLUDE_SPINLOCK_H
+#define INCLUDE_SPINLOCK_H
+
+#include <QAtomicInt>
+
+class Spinlock {
+public:
+ void lock()
+ {
+ while(!m_atomic.testAndSetAcquire(0, 1)) ;
+ }
+
+ void unlock()
+ {
+ while(!m_atomic.testAndSetRelease(1, 0)) ;
+ }
+
+protected:
+ QAtomicInt m_atomic;
+};
+
+class SpinlockHolder {
+public:
+ SpinlockHolder(Spinlock* spinlock) :
+ m_spinlock(spinlock)
+ {
+ m_spinlock->lock();
+ }
+
+ ~SpinlockHolder()
+ {
+ m_spinlock->unlock();
+ }
+
+protected:
+ Spinlock* m_spinlock;
+};
+
+#endif // INCLUDE_SPINLOCK_H