mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-07-30 20:52:26 -04:00
Removed old sdrbase include directory
This commit is contained in:
parent
90d6cd89e9
commit
6cc4434019
@ -1,49 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_AUDIODEVICEINFO_H
|
|
||||||
#define INCLUDE_AUDIODEVICEINFO_H
|
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API AudioDeviceInfo {
|
|
||||||
public:
|
|
||||||
struct Device {
|
|
||||||
QString name;
|
|
||||||
QString api;
|
|
||||||
int id;
|
|
||||||
|
|
||||||
Device(const QString& _name, const QString& _api, int _id) :
|
|
||||||
name(_name),
|
|
||||||
api(_api),
|
|
||||||
id(_id)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
typedef QList<Device> Devices;
|
|
||||||
|
|
||||||
AudioDeviceInfo();
|
|
||||||
|
|
||||||
int match(const QString& api, const QString device) const;
|
|
||||||
|
|
||||||
const Devices& getDevices() const { return m_devices; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Devices m_devices;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_AUDIODEVICEINFO_H
|
|
@ -1,67 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_AUDIOFIFO_H
|
|
||||||
#define INCLUDE_AUDIOFIFO_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QWaitCondition>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API AudioFifo : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
AudioFifo();
|
|
||||||
AudioFifo(uint sampleSize, uint numSamples);
|
|
||||||
~AudioFifo();
|
|
||||||
|
|
||||||
bool setSize(uint sampleSize, uint numSamples);
|
|
||||||
|
|
||||||
uint write(const quint8* data, uint numSamples, int timeout_ms = INT_MAX);
|
|
||||||
uint read(quint8* data, uint numSamples, int timeout_ms = INT_MAX);
|
|
||||||
|
|
||||||
uint drain(uint numSamples);
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
inline uint flush() { return drain(m_fill); }
|
|
||||||
inline uint fill() const { return m_fill; }
|
|
||||||
inline bool isEmpty() const { return m_fill == 0; }
|
|
||||||
inline bool isFull() const { return m_fill == m_size; }
|
|
||||||
inline uint size() const { return m_size; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QMutex m_mutex;
|
|
||||||
|
|
||||||
qint8* m_fifo;
|
|
||||||
|
|
||||||
uint m_sampleSize;
|
|
||||||
|
|
||||||
uint m_size;
|
|
||||||
uint m_fill;
|
|
||||||
uint m_head;
|
|
||||||
uint m_tail;
|
|
||||||
|
|
||||||
QMutex m_writeWaitLock;
|
|
||||||
QMutex m_readWaitLock;
|
|
||||||
QWaitCondition m_writeWaitCondition;
|
|
||||||
QWaitCondition m_readWaitCondition;
|
|
||||||
|
|
||||||
bool create(uint sampleSize, uint numSamples);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_AUDIOFIFO_H
|
|
@ -1,62 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_AUDIOOUTPUT_H
|
|
||||||
#define INCLUDE_AUDIOOUTPUT_H
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QIODevice>
|
|
||||||
#include <QAudioFormat>
|
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class QAudioOutput;
|
|
||||||
class AudioFifo;
|
|
||||||
class AudioOutputPipe;
|
|
||||||
|
|
||||||
class SDRANGEL_API AudioOutput : QIODevice {
|
|
||||||
public:
|
|
||||||
AudioOutput();
|
|
||||||
virtual ~AudioOutput();
|
|
||||||
|
|
||||||
bool start(int device, int rate);
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
void addFifo(AudioFifo* audioFifo);
|
|
||||||
void removeFifo(AudioFifo* audioFifo);
|
|
||||||
|
|
||||||
uint getRate() const { return m_audioFormat.sampleRate(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QMutex m_mutex;
|
|
||||||
QAudioOutput* m_audioOutput;
|
|
||||||
|
|
||||||
typedef std::list<AudioFifo*> AudioFifos;
|
|
||||||
AudioFifos m_audioFifos;
|
|
||||||
std::vector<qint32> m_mixBuffer;
|
|
||||||
|
|
||||||
QAudioFormat m_audioFormat;
|
|
||||||
|
|
||||||
//virtual bool open(OpenMode mode);
|
|
||||||
virtual qint64 readData(char* data, qint64 maxLen);
|
|
||||||
virtual qint64 writeData(const char* data, qint64 len);
|
|
||||||
|
|
||||||
friend class AudioOutputPipe;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_AUDIOOUTPUT_H
|
|
@ -1,90 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB. //
|
|
||||||
// //
|
|
||||||
// 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_GPL_DSP_AFSQUELCH_H_
|
|
||||||
#define INCLUDE_GPL_DSP_AFSQUELCH_H_
|
|
||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "dsp/movingaverage.h"
|
|
||||||
|
|
||||||
/** AFSquelch: AF squelch class based on the Modified Goertzel
|
|
||||||
* algorithm.
|
|
||||||
*/
|
|
||||||
class AFSquelch {
|
|
||||||
public:
|
|
||||||
// Constructors and Destructor
|
|
||||||
AFSquelch();
|
|
||||||
// allows user defined tone pair
|
|
||||||
AFSquelch(unsigned int nbTones,
|
|
||||||
const Real *tones);
|
|
||||||
virtual ~AFSquelch();
|
|
||||||
|
|
||||||
// setup the basic parameters and coefficients
|
|
||||||
void setCoefficients(
|
|
||||||
int N, //!< the algorithm "block" size
|
|
||||||
unsigned int nbAvg, //!< averaging size
|
|
||||||
int SampleRate, //!< input signal sample rate
|
|
||||||
int _samplesAttack, //!< number of results before squelch opens
|
|
||||||
int _samplesDecay); //!< number of results keeping squelch open
|
|
||||||
|
|
||||||
// set the detection threshold
|
|
||||||
void setThreshold(double _threshold);
|
|
||||||
|
|
||||||
// analyze a sample set and optionally filter
|
|
||||||
// the tone frequencies.
|
|
||||||
bool analyze(Real sample); // input signal sample
|
|
||||||
bool evaluate(); // evaluate result
|
|
||||||
|
|
||||||
// get the tone set
|
|
||||||
const Real *getToneSet() const
|
|
||||||
{
|
|
||||||
return m_toneSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool open() const {
|
|
||||||
return m_isOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset(); // reset the analysis algorithm
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void feedback(Real sample);
|
|
||||||
void feedForward();
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int m_nbAvg; //!< number of power samples taken for moving average
|
|
||||||
int m_N;
|
|
||||||
int m_sampleRate;
|
|
||||||
int m_samplesProcessed;
|
|
||||||
int m_maxPowerIndex;
|
|
||||||
int m_nTones;
|
|
||||||
int m_samplesAttack;
|
|
||||||
int m_attackCount;
|
|
||||||
int m_samplesDecay;
|
|
||||||
int m_decayCount;
|
|
||||||
bool m_isOpen;
|
|
||||||
double m_threshold;
|
|
||||||
double *m_k;
|
|
||||||
double *m_coef;
|
|
||||||
Real *m_toneSet;
|
|
||||||
double *m_u0;
|
|
||||||
double *m_u1;
|
|
||||||
double *m_power;
|
|
||||||
std::vector<MovingAverage<Real> > m_movingAverages;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDE_GPL_DSP_CTCSSDETECTOR_H_ */
|
|
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* kissagc.h
|
|
||||||
*
|
|
||||||
* Created on: May 12, 2015
|
|
||||||
* Author: f4exb
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INCLUDE_GPL_DSP_AGC_H_
|
|
||||||
#define INCLUDE_GPL_DSP_AGC_H_
|
|
||||||
|
|
||||||
#include "movingaverage.h"
|
|
||||||
|
|
||||||
class AGC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
AGC();
|
|
||||||
AGC(int historySize, Real R);
|
|
||||||
virtual ~AGC();
|
|
||||||
|
|
||||||
void resize(int historySize, Real R);
|
|
||||||
Real getValue();
|
|
||||||
Real getAverage();
|
|
||||||
virtual void feed(Complex& ci) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Real m_u0;
|
|
||||||
Real m_R; // objective mag
|
|
||||||
MovingAverage<Real> m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC.
|
|
||||||
int m_historySize;
|
|
||||||
int m_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MagSquaredAGC : public AGC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MagSquaredAGC();
|
|
||||||
MagSquaredAGC(int historySize, Real R);
|
|
||||||
virtual ~MagSquaredAGC();
|
|
||||||
virtual void feed(Complex& ci);
|
|
||||||
Real getMagSq() const { return m_magsq; }
|
|
||||||
private:
|
|
||||||
Real m_magsq;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MagAGC : public AGC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MagAGC();
|
|
||||||
MagAGC(int historySize, Real R);
|
|
||||||
virtual ~MagAGC();
|
|
||||||
virtual void feed(Complex& ci);
|
|
||||||
Real getMagSq() const { return m_magsq; }
|
|
||||||
private:
|
|
||||||
Real m_magsq;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AlphaAGC : public AGC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AlphaAGC();
|
|
||||||
AlphaAGC(int historySize, Real R);
|
|
||||||
AlphaAGC(int historySize, Real R, Real alpha);
|
|
||||||
virtual ~AlphaAGC();
|
|
||||||
void resize(int historySize, Real R, Real alpha);
|
|
||||||
virtual void feed(Complex& ci);
|
|
||||||
Real getMagSq() const { return m_magsq; }
|
|
||||||
private:
|
|
||||||
Real m_alpha;
|
|
||||||
Real m_magsq;
|
|
||||||
bool m_squelchOpen;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SimpleAGC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SimpleAGC() :
|
|
||||||
m_squelchOpen(false),
|
|
||||||
m_fill(0),
|
|
||||||
m_cutoff(0),
|
|
||||||
m_clip(0),
|
|
||||||
m_moving_average()
|
|
||||||
{}
|
|
||||||
|
|
||||||
SimpleAGC(int historySize, Real initial, Real cutoff=0, Real clip=0) :
|
|
||||||
m_squelchOpen(false),
|
|
||||||
m_fill(initial),
|
|
||||||
m_cutoff(cutoff),
|
|
||||||
m_clip(clip),
|
|
||||||
m_moving_average(historySize, initial)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void resize(int historySize, Real initial, Real cutoff=0, Real clip=0)
|
|
||||||
{
|
|
||||||
m_fill = initial;
|
|
||||||
m_cutoff = cutoff;
|
|
||||||
m_clip = clip;
|
|
||||||
m_moving_average.resize(historySize, initial);
|
|
||||||
}
|
|
||||||
|
|
||||||
Real getValue()
|
|
||||||
{
|
|
||||||
if (m_moving_average.average() > m_clip)
|
|
||||||
{
|
|
||||||
return m_moving_average.average();
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
return m_clip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void feed(Real value)
|
|
||||||
{
|
|
||||||
if (value > m_cutoff)
|
|
||||||
{
|
|
||||||
m_moving_average.feed(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_squelchOpen; // open for processing
|
|
||||||
Real m_fill; // refill average at this level
|
|
||||||
Real m_cutoff; // consider samples only above this level
|
|
||||||
Real m_clip; // never go below this level
|
|
||||||
MovingAverage<Real> m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC.
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INCLUDE_GPL_DSP_AGC_H_ */
|
|
@ -1,127 +0,0 @@
|
|||||||
#ifndef INCLUDE_BANDPASS_H
|
|
||||||
#define INCLUDE_BANDPASS_H
|
|
||||||
|
|
||||||
#define _USE_MATH_DEFINES
|
|
||||||
#include <math.h>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
template <class Type> class Bandpass {
|
|
||||||
public:
|
|
||||||
Bandpass() { }
|
|
||||||
|
|
||||||
void create(int nTaps, double sampleRate, double lowCutoff, double highCutoff)
|
|
||||||
{
|
|
||||||
std::vector<Real> taps_lp;
|
|
||||||
std::vector<Real> taps_hp;
|
|
||||||
double wcl = 2.0 * M_PI * lowCutoff;
|
|
||||||
double Wcl = wcl / sampleRate;
|
|
||||||
double wch = 2.0 * M_PI * highCutoff;
|
|
||||||
double Wch = wch / sampleRate;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// check constraints
|
|
||||||
if(!(nTaps & 1)) {
|
|
||||||
qDebug("Bandpass filter has to have an odd number of taps");
|
|
||||||
nTaps++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make room
|
|
||||||
m_samples.resize(nTaps);
|
|
||||||
for(int i = 0; i < nTaps; i++)
|
|
||||||
m_samples[i] = 0;
|
|
||||||
m_ptr = 0;
|
|
||||||
m_taps.resize(nTaps / 2 + 1);
|
|
||||||
taps_lp.resize(nTaps / 2 + 1);
|
|
||||||
taps_hp.resize(nTaps / 2 + 1);
|
|
||||||
|
|
||||||
// generate Sinc filter core
|
|
||||||
for(i = 0; i < nTaps / 2 + 1; i++) {
|
|
||||||
if(i == (nTaps - 1) / 2) {
|
|
||||||
taps_lp[i] = Wch / M_PI;
|
|
||||||
taps_hp[i] = -(Wcl / M_PI);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
taps_lp[i] = sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wch) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI);
|
|
||||||
taps_hp[i] = -sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wcl) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
taps_hp[(nTaps - 1) / 2] += 1;
|
|
||||||
|
|
||||||
// apply Hamming window and combine lowpass and highpass
|
|
||||||
for(i = 0; i < nTaps / 2 + 1; i++) {
|
|
||||||
taps_lp[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps);
|
|
||||||
taps_hp[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps);
|
|
||||||
m_taps[i] = -(taps_lp[i]+taps_hp[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_taps[(nTaps - 1) / 2] += 1;
|
|
||||||
|
|
||||||
// normalize
|
|
||||||
Real sum = 0;
|
|
||||||
|
|
||||||
for(i = 0; i < (int)m_taps.size() - 1; i++) {
|
|
||||||
sum += m_taps[i] * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
sum += m_taps[i];
|
|
||||||
|
|
||||||
for(i = 0; i < (int)m_taps.size(); i++) {
|
|
||||||
m_taps[i] /= sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Type filter(Type sample)
|
|
||||||
{
|
|
||||||
Type acc = 0;
|
|
||||||
int a = m_ptr;
|
|
||||||
int b = a - 1;
|
|
||||||
int i, n_taps, size;
|
|
||||||
|
|
||||||
m_samples[m_ptr] = sample;
|
|
||||||
size = m_samples.size(); // Valgrind optim (2)
|
|
||||||
|
|
||||||
while(b < 0)
|
|
||||||
{
|
|
||||||
b += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
n_taps = m_taps.size() - 1; // Valgrind optim
|
|
||||||
|
|
||||||
for(i = 0; i < n_taps; i++)
|
|
||||||
{
|
|
||||||
acc += (m_samples[a] + m_samples[b]) * m_taps[i];
|
|
||||||
a++;
|
|
||||||
|
|
||||||
while (a >= size)
|
|
||||||
{
|
|
||||||
a -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
b--;
|
|
||||||
|
|
||||||
while(b < 0)
|
|
||||||
{
|
|
||||||
b += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
acc += m_samples[a] * m_taps[i];
|
|
||||||
|
|
||||||
m_ptr++;
|
|
||||||
|
|
||||||
while (m_ptr >= size)
|
|
||||||
{
|
|
||||||
m_ptr -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<Real> m_taps;
|
|
||||||
std::vector<Type> m_samples;
|
|
||||||
int m_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_BANDPASS_H
|
|
@ -1,85 +0,0 @@
|
|||||||
#ifndef INCLUDE_CHANNELIZER_H
|
|
||||||
#define INCLUDE_CHANNELIZER_H
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <QMutex>
|
|
||||||
#include "dsp/samplesink.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
#include "util/message.h"
|
|
||||||
|
|
||||||
class MessageQueue;
|
|
||||||
class IntHalfbandFilter;
|
|
||||||
|
|
||||||
class SDRANGEL_API Channelizer : public SampleSink {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
class SDRANGEL_API MsgChannelizerNotification : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
MsgChannelizerNotification(int samplerate, qint64 frequencyOffset) :
|
|
||||||
Message(),
|
|
||||||
m_sampleRate(samplerate),
|
|
||||||
m_frequencyOffset(frequencyOffset)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
|
||||||
qint64 getFrequencyOffset() const { return m_frequencyOffset; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_sampleRate;
|
|
||||||
qint64 m_frequencyOffset;
|
|
||||||
};
|
|
||||||
|
|
||||||
Channelizer(SampleSink* sampleSink);
|
|
||||||
virtual ~Channelizer();
|
|
||||||
|
|
||||||
void configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency);
|
|
||||||
int getInputSampleRate() const { return m_inputSampleRate; }
|
|
||||||
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
|
||||||
virtual bool handleMessage(const Message& cmd);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
struct FilterStage {
|
|
||||||
enum Mode {
|
|
||||||
ModeCenter,
|
|
||||||
ModeLowerHalf,
|
|
||||||
ModeUpperHalf
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef bool (IntHalfbandFilter::*WorkFunction)(Sample* s);
|
|
||||||
IntHalfbandFilter* m_filter;
|
|
||||||
WorkFunction m_workFunction;
|
|
||||||
|
|
||||||
FilterStage(Mode mode);
|
|
||||||
~FilterStage();
|
|
||||||
|
|
||||||
bool work(Sample* sample)
|
|
||||||
{
|
|
||||||
return (m_filter->*m_workFunction)(sample);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typedef std::list<FilterStage*> FilterStages;
|
|
||||||
FilterStages m_filterStages;
|
|
||||||
SampleSink* m_sampleSink;
|
|
||||||
int m_inputSampleRate;
|
|
||||||
int m_requestedOutputSampleRate;
|
|
||||||
int m_requestedCenterFrequency;
|
|
||||||
int m_currentOutputSampleRate;
|
|
||||||
int m_currentCenterFrequency;
|
|
||||||
SampleVector m_sampleBuffer;
|
|
||||||
QMutex m_mutex;
|
|
||||||
|
|
||||||
void applyConfiguration();
|
|
||||||
bool signalContainsChannel(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd) const;
|
|
||||||
Real createFilterChain(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd);
|
|
||||||
void freeFilterChain();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void inputSampleRateChanged();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_CHANNELIZER_H
|
|
@ -1,62 +0,0 @@
|
|||||||
#ifndef INCLUDE_CHANNELMARKER_H
|
|
||||||
#define INCLUDE_CHANNELMARKER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QColor>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API ChannelMarker : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef enum sidebands_e
|
|
||||||
{
|
|
||||||
dsb,
|
|
||||||
lsb,
|
|
||||||
usb
|
|
||||||
} sidebands_t;
|
|
||||||
|
|
||||||
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 setLowCutoff(int lowCutoff);
|
|
||||||
int getLowCutoff() const { return m_lowCutoff; }
|
|
||||||
|
|
||||||
void setSidebands(sidebands_t sidebands);
|
|
||||||
sidebands_t getSidebands() const { return m_sidebands; }
|
|
||||||
|
|
||||||
void setVisible(bool visible);
|
|
||||||
bool getVisible() const { return m_visible; }
|
|
||||||
|
|
||||||
void setHighlighted(bool highlighted);
|
|
||||||
bool getHighlighted() const { return m_highlighted; }
|
|
||||||
|
|
||||||
void setColor(const QColor& color);
|
|
||||||
const QColor& getColor() const { return m_color; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static QRgb m_colorTable[];
|
|
||||||
static int m_nextColor;
|
|
||||||
|
|
||||||
QString m_title;
|
|
||||||
int m_centerFrequency;
|
|
||||||
int m_bandwidth;
|
|
||||||
int m_lowCutoff;
|
|
||||||
sidebands_t m_sidebands;
|
|
||||||
bool m_visible;
|
|
||||||
bool m_highlighted;
|
|
||||||
QColor m_color;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void changed();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_CHANNELMARKER_H
|
|
@ -1,43 +0,0 @@
|
|||||||
// ----------------------------------------------------------------------------
|
|
||||||
// complex.h -- Complex arithmetic
|
|
||||||
//
|
|
||||||
// Copyright (C) 2006-2008
|
|
||||||
// Dave Freese, W1HKJ
|
|
||||||
// Copyright (C) 2008
|
|
||||||
// Stelios Bounanos, M0GLD
|
|
||||||
//
|
|
||||||
// This file is part of fldigi.
|
|
||||||
//
|
|
||||||
// Fldigi 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, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// Fldigi 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 for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef _COMPLEX_H
|
|
||||||
#define _COMPLEX_H
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <complex>
|
|
||||||
|
|
||||||
typedef std::complex<float> cmplx;
|
|
||||||
|
|
||||||
inline cmplx cmac (const cmplx *a, const cmplx *b, int ptr, int len) {
|
|
||||||
cmplx z;
|
|
||||||
ptr %= len;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
z += a[i] * b[ptr];
|
|
||||||
ptr = (ptr + 1) % len;
|
|
||||||
}
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* ctcssdetector.h
|
|
||||||
*
|
|
||||||
* Created on: Jun 16, 2015
|
|
||||||
* Author: f4exb
|
|
||||||
* See: http://www.embedded.com/design/connectivity/4025660/Detecting-CTCSS-tones-with-Goertzel-s-algorithm
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INCLUDE_GPL_DSP_CTCSSDETECTOR_H_
|
|
||||||
#define INCLUDE_GPL_DSP_CTCSSDETECTOR_H_
|
|
||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
/** CTCSSDetector: Continuous Tone Coded Squelch System
|
|
||||||
* tone detector class based on the Modified Goertzel
|
|
||||||
* algorithm.
|
|
||||||
*/
|
|
||||||
class CTCSSDetector {
|
|
||||||
public:
|
|
||||||
// Constructors and Destructor
|
|
||||||
CTCSSDetector();
|
|
||||||
// allows user defined CTCSS tone set
|
|
||||||
CTCSSDetector(int _nTones, Real *tones);
|
|
||||||
virtual ~CTCSSDetector();
|
|
||||||
|
|
||||||
// setup the basic parameters and coefficients
|
|
||||||
void setCoefficients(
|
|
||||||
int zN, // the algorithm "block" size
|
|
||||||
int SampleRate); // input signal sample rate
|
|
||||||
|
|
||||||
// set the detection threshold
|
|
||||||
void setThreshold(double thold);
|
|
||||||
|
|
||||||
// analyze a sample set and optionally filter
|
|
||||||
// the tone frequencies.
|
|
||||||
bool analyze(Real *sample); // input signal sample
|
|
||||||
|
|
||||||
// get the number of defined tones.
|
|
||||||
int getNTones() const {
|
|
||||||
return nTones;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the tone set
|
|
||||||
const Real *getToneSet() const
|
|
||||||
{
|
|
||||||
return toneSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the currently detected tone, if any
|
|
||||||
bool getDetectedTone(int &maxTone) const
|
|
||||||
{
|
|
||||||
maxTone = maxPowerIndex;
|
|
||||||
return toneDetected;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the max power at the detected tone.
|
|
||||||
Real getMaxPower() const
|
|
||||||
{
|
|
||||||
return maxPower;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset(); // reset the analysis algorithm
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Override these to change behavior of the detector
|
|
||||||
virtual void initializePower();
|
|
||||||
virtual void evaluatePower();
|
|
||||||
void feedback(Real sample);
|
|
||||||
void feedForward();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int N;
|
|
||||||
int sampleRate;
|
|
||||||
int nTones;
|
|
||||||
int samplesProcessed;
|
|
||||||
int maxPowerIndex;
|
|
||||||
bool toneDetected;
|
|
||||||
Real maxPower;
|
|
||||||
Real *k;
|
|
||||||
Real *coef;
|
|
||||||
Real *toneSet;
|
|
||||||
Real *u0;
|
|
||||||
Real *u1;
|
|
||||||
Real *power;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDE_GPL_DSP_CTCSSDETECTOR_H_ */
|
|
File diff suppressed because it is too large
Load Diff
@ -1,268 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_DSPCOMMANDS_H
|
|
||||||
#define INCLUDE_DSPCOMMANDS_H
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include "util/message.h"
|
|
||||||
#include "fftwindow.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SampleSource;
|
|
||||||
class SampleSink;
|
|
||||||
class ThreadedSampleSink;
|
|
||||||
class AudioFifo;
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPExit : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPAcquisitionInit : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPAcquisitionStart : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPAcquisitionStop : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPGetSourceDeviceDescription : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setDeviceDescription(const QString& text) { m_deviceDescription = text; }
|
|
||||||
const QString& getDeviceDescription() const { return m_deviceDescription; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_deviceDescription;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPGetErrorMessage : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setErrorMessage(const QString& text) { m_errorMessage = text; }
|
|
||||||
const QString& getErrorMessage() const { return m_errorMessage; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_errorMessage;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPSetSource : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPSetSource(SampleSource* sampleSource) : Message(), m_sampleSource(sampleSource) { }
|
|
||||||
|
|
||||||
SampleSource* getSampleSource() const { return m_sampleSource; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
SampleSource* m_sampleSource;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPAddSink : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPAddSink(SampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
|
|
||||||
|
|
||||||
SampleSink* getSampleSink() const { return m_sampleSink; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
SampleSink* m_sampleSink;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPRemoveSink : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPRemoveSink(SampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
|
|
||||||
|
|
||||||
SampleSink* getSampleSink() const { return m_sampleSink; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
SampleSink* m_sampleSink;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPAddThreadedSampleSink : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPAddThreadedSampleSink(ThreadedSampleSink* threadedSampleSink) : Message(), m_threadedSampleSink(threadedSampleSink) { }
|
|
||||||
|
|
||||||
ThreadedSampleSink* getThreadedSampleSink() const { return m_threadedSampleSink; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ThreadedSampleSink* m_threadedSampleSink;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPRemoveThreadedSampleSink : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPRemoveThreadedSampleSink(ThreadedSampleSink* threadedSampleSink) : Message(), m_threadedSampleSink(threadedSampleSink) { }
|
|
||||||
|
|
||||||
ThreadedSampleSink* getThreadedSampleSink() const { return m_threadedSampleSink; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ThreadedSampleSink* m_threadedSampleSink;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPAddAudioSink : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPAddAudioSink(AudioFifo* audioFifo) : Message(), m_audioFifo(audioFifo) { }
|
|
||||||
|
|
||||||
AudioFifo* getAudioFifo() const { return m_audioFifo; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
AudioFifo* m_audioFifo;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPRemoveAudioSink : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPRemoveAudioSink(AudioFifo* audioFifo) : Message(), m_audioFifo(audioFifo) { }
|
|
||||||
|
|
||||||
AudioFifo* getAudioFifo() const { return m_audioFifo; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
AudioFifo* m_audioFifo;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPConfigureSpectrumVis : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPConfigureSpectrumVis(int fftSize, int overlapPercent, FFTWindow::Function window) :
|
|
||||||
Message(),
|
|
||||||
m_fftSize(fftSize),
|
|
||||||
m_overlapPercent(overlapPercent),
|
|
||||||
m_window(window)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int getFFTSize() const { return m_fftSize; }
|
|
||||||
int getOverlapPercent() const { return m_overlapPercent; }
|
|
||||||
FFTWindow::Function getWindow() const { return m_window; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_fftSize;
|
|
||||||
int m_overlapPercent;
|
|
||||||
FFTWindow::Function m_window;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPConfigureCorrection : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPConfigureCorrection(bool dcOffsetCorrection, bool iqImbalanceCorrection) :
|
|
||||||
Message(),
|
|
||||||
m_dcOffsetCorrection(dcOffsetCorrection),
|
|
||||||
m_iqImbalanceCorrection(iqImbalanceCorrection)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
bool getDCOffsetCorrection() const { return m_dcOffsetCorrection; }
|
|
||||||
bool getIQImbalanceCorrection() const { return m_iqImbalanceCorrection; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_dcOffsetCorrection;
|
|
||||||
bool m_iqImbalanceCorrection;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPEngineReport : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPEngineReport(int sampleRate, quint64 centerFrequency) :
|
|
||||||
Message(),
|
|
||||||
m_sampleRate(sampleRate),
|
|
||||||
m_centerFrequency(centerFrequency)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
|
||||||
quint64 getCenterFrequency() const { return m_centerFrequency; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_sampleRate;
|
|
||||||
quint64 m_centerFrequency;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPConfigureScopeVis : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPConfigureScopeVis(int triggerChannel, Real triggerLevelHigh, Real triggerLevelLow) :
|
|
||||||
Message(),
|
|
||||||
m_triggerChannel(triggerChannel),
|
|
||||||
m_triggerLevelHigh(triggerLevelHigh),
|
|
||||||
m_triggerLevelLow(triggerLevelLow)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int getTriggerChannel() const { return m_triggerChannel; }
|
|
||||||
Real getTriggerLevelHigh() const { return m_triggerLevelHigh; }
|
|
||||||
Real getTriggerLevelLow() const { return m_triggerLevelLow; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_triggerChannel;
|
|
||||||
Real m_triggerLevelHigh;
|
|
||||||
Real m_triggerLevelLow;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPSignalNotification : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPSignalNotification(int samplerate, qint64 centerFrequency) :
|
|
||||||
Message(),
|
|
||||||
m_sampleRate(samplerate),
|
|
||||||
m_centerFrequency(centerFrequency)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
|
||||||
qint64 getCenterFrequency() const { return m_centerFrequency; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_sampleRate;
|
|
||||||
qint64 m_centerFrequency;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPConfigureChannelizer : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
DSPConfigureChannelizer(int sampleRate, int centerFrequency) :
|
|
||||||
Message(),
|
|
||||||
m_sampleRate(sampleRate),
|
|
||||||
m_centerFrequency(centerFrequency)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
|
||||||
int getCenterFrequency() const { return m_centerFrequency; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_sampleRate;
|
|
||||||
int m_centerFrequency;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_DSPCOMMANDS_H
|
|
@ -1,125 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_DSPDEVICEENGINE_H
|
|
||||||
#define INCLUDE_DSPDEVICEENGINE_H
|
|
||||||
|
|
||||||
#include <QThread>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QWaitCondition>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "dsp/fftwindow.h"
|
|
||||||
#include "dsp/samplefifo.h"
|
|
||||||
#include "util/messagequeue.h"
|
|
||||||
#include "util/syncmessenger.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SampleSource;
|
|
||||||
class SampleSink;
|
|
||||||
class ThreadedSampleSink;
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPDeviceEngine : public QThread {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum State {
|
|
||||||
StNotStarted, //!< engine is before initialization
|
|
||||||
StIdle, //!< engine is idle
|
|
||||||
StReady, //!< engine is ready to run
|
|
||||||
StRunning, //!< engine is running
|
|
||||||
StError //!< engine is in error
|
|
||||||
};
|
|
||||||
|
|
||||||
DSPDeviceEngine(QObject* parent = NULL);
|
|
||||||
~DSPDeviceEngine();
|
|
||||||
|
|
||||||
MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
|
|
||||||
MessageQueue* getOutputMessageQueue() { return &m_outputMessageQueue; }
|
|
||||||
|
|
||||||
void start(); //!< This thread start
|
|
||||||
void stop(); //!< This thread stop
|
|
||||||
|
|
||||||
bool initAcquisition(); //!< Initialize acquisition sequence
|
|
||||||
bool startAcquisition(); //!< Start acquisition sequence
|
|
||||||
void stopAcquistion(); //!< Stop acquisition sequence
|
|
||||||
|
|
||||||
void setSource(SampleSource* source); //!< Set the sample source type
|
|
||||||
void setSourceSequence(int sequence); //!< Set the sample source sequence in type
|
|
||||||
|
|
||||||
void addSink(SampleSink* sink); //!< Add a sample sink
|
|
||||||
void removeSink(SampleSink* sink); //!< Remove a sample sink
|
|
||||||
|
|
||||||
void addThreadedSink(ThreadedSampleSink* sink); //!< Add a sample sink that will run on its own thread
|
|
||||||
void removeThreadedSink(ThreadedSampleSink* sink); //!< Remove a sample sink that runs on its own thread
|
|
||||||
|
|
||||||
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection); //!< Configure DSP corrections
|
|
||||||
|
|
||||||
State state() const { return m_state; } //!< Return DSP engine current state
|
|
||||||
|
|
||||||
QString errorMessage(); //!< Return the current error message
|
|
||||||
QString sourceDeviceDescription(); //!< Return the source device description
|
|
||||||
|
|
||||||
private:
|
|
||||||
MessageQueue m_inputMessageQueue; //<! Input message queue. Post here.
|
|
||||||
MessageQueue m_outputMessageQueue; //<! Output message queue. Listen here.
|
|
||||||
SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread
|
|
||||||
|
|
||||||
State m_state;
|
|
||||||
|
|
||||||
QString m_errorMessage;
|
|
||||||
QString m_deviceDescription;
|
|
||||||
|
|
||||||
SampleSource* m_sampleSource;
|
|
||||||
int m_sampleSourceSequence;
|
|
||||||
|
|
||||||
typedef std::list<SampleSink*> SampleSinks;
|
|
||||||
SampleSinks m_sampleSinks; //!< sample sinks within main thread (usually spectrum, file output)
|
|
||||||
|
|
||||||
typedef std::list<ThreadedSampleSink*> ThreadedSampleSinks;
|
|
||||||
ThreadedSampleSinks m_threadedSampleSinks; //!< sample sinks on their own threads (usually channels)
|
|
||||||
|
|
||||||
uint m_sampleRate;
|
|
||||||
quint64 m_centerFrequency;
|
|
||||||
|
|
||||||
bool m_dcOffsetCorrection;
|
|
||||||
bool m_iqImbalanceCorrection;
|
|
||||||
double m_iOffset, m_qOffset;
|
|
||||||
qint32 m_iRange;
|
|
||||||
qint32 m_qRange;
|
|
||||||
qint32 m_imbalance;
|
|
||||||
|
|
||||||
void run();
|
|
||||||
|
|
||||||
void dcOffset(SampleVector::iterator begin, SampleVector::iterator end);
|
|
||||||
void imbalance(SampleVector::iterator begin, SampleVector::iterator end);
|
|
||||||
void work(); //!< transfer samples from source to sinks if in running state
|
|
||||||
|
|
||||||
State gotoIdle(); //!< Go to the idle state
|
|
||||||
State gotoInit(); //!< Go to the acquisition init state from idle
|
|
||||||
State gotoRunning(); //!< Go to the running state from ready state
|
|
||||||
State gotoError(const QString& errorMsg); //!< Go to an error state
|
|
||||||
|
|
||||||
void handleSetSource(SampleSource* source); //!< Manage source setting
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void handleData(); //!< Handle data when samples from source FIFO are ready to be processed
|
|
||||||
void handleInputMessages(); //!< Handle input message queue
|
|
||||||
void handleSynchronousMessages(); //!< Handle synchronous messages with the thread
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_DSPDEVICEENGINE_H
|
|
@ -1,74 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_DSPENGINE_H
|
|
||||||
#define INCLUDE_DSPENGINE_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include "dsp/dspdeviceengine.h"
|
|
||||||
#include "audio/audiooutput.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class DSPDeviceEngine;
|
|
||||||
class ThreadedSampleSink;
|
|
||||||
|
|
||||||
class SDRANGEL_API DSPEngine : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
DSPEngine();
|
|
||||||
~DSPEngine();
|
|
||||||
|
|
||||||
static DSPEngine *instance();
|
|
||||||
|
|
||||||
MessageQueue* getInputMessageQueue();
|
|
||||||
MessageQueue* getOutputMessageQueue();
|
|
||||||
|
|
||||||
uint getAudioSampleRate() const { return m_audioSampleRate; }
|
|
||||||
|
|
||||||
void start(); //!< Device engine(s) start
|
|
||||||
void stop(); //!< Device engine(s) stop
|
|
||||||
|
|
||||||
bool initAcquisition(); //!< Initialize acquisition sequence
|
|
||||||
bool startAcquisition(); //!< Start acquisition sequence
|
|
||||||
void stopAcquistion(); //!< Stop acquisition sequence
|
|
||||||
|
|
||||||
void setSource(SampleSource* source); //!< Set the sample source type
|
|
||||||
void setSourceSequence(int sequence); //!< Set the sample source sequence in type
|
|
||||||
|
|
||||||
void addSink(SampleSink* sink); //!< Add a sample sink
|
|
||||||
void removeSink(SampleSink* sink); //!< Remove a sample sink
|
|
||||||
|
|
||||||
void addThreadedSink(ThreadedSampleSink* sink); //!< Add a sample sink that will run on its own thread
|
|
||||||
void removeThreadedSink(ThreadedSampleSink* sink); //!< Remove a sample sink that runs on its own thread
|
|
||||||
|
|
||||||
void addAudioSink(AudioFifo* audioFifo); //!< Add the audio sink
|
|
||||||
void removeAudioSink(AudioFifo* audioFifo); //!< Remove the audio sink
|
|
||||||
|
|
||||||
void configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection); //!< Configure DSP corrections
|
|
||||||
|
|
||||||
DSPDeviceEngine::State state() const;
|
|
||||||
|
|
||||||
QString errorMessage(); //!< Return the current error message
|
|
||||||
QString sourceDeviceDescription(); //!< Return the source device description
|
|
||||||
|
|
||||||
private:
|
|
||||||
DSPDeviceEngine *m_deviceEngine;
|
|
||||||
AudioOutput m_audioOutput;
|
|
||||||
uint m_audioSampleRate;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_DSPENGINE_H
|
|
@ -1,57 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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>
|
|
||||||
|
|
||||||
#define SDR_SAMP_SZ 16 // internal fixed arithmetic sample size
|
|
||||||
|
|
||||||
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) {}
|
|
||||||
inline Sample& operator=(const Sample& other) { m_real = other.m_real; m_imag = other.m_imag; return *this; }
|
|
||||||
|
|
||||||
inline Sample& operator+=(const Sample& other) { m_real += other.m_real; m_imag += other.m_imag; return *this; }
|
|
||||||
inline Sample& operator-=(const Sample& other) { m_real -= other.m_real; m_imag -= other.m_imag; return *this; }
|
|
||||||
|
|
||||||
inline void setReal(FixReal v) { m_real = v; }
|
|
||||||
inline void setImag(FixReal v) { m_imag = v; }
|
|
||||||
|
|
||||||
inline FixReal real() const { return m_real; }
|
|
||||||
inline FixReal imag() const { return m_imag; }
|
|
||||||
|
|
||||||
FixReal m_real;
|
|
||||||
FixReal m_imag;
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
typedef std::vector<Sample> SampleVector;
|
|
||||||
|
|
||||||
#endif // INCLUDE_DSPTYPES_H
|
|
@ -1,20 +0,0 @@
|
|||||||
#ifndef INCLUDE_FFTENGINE_H
|
|
||||||
#define INCLUDE_FFTENGINE_H
|
|
||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API FFTEngine {
|
|
||||||
public:
|
|
||||||
virtual ~FFTEngine();
|
|
||||||
|
|
||||||
virtual void configure(int n, bool inverse) = 0;
|
|
||||||
virtual void transform() = 0;
|
|
||||||
|
|
||||||
virtual Complex* in() = 0;
|
|
||||||
virtual Complex* out() = 0;
|
|
||||||
|
|
||||||
static FFTEngine* create();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_FFTENGINE_H
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* Filters from Fldigi.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _FFTFILT_H
|
|
||||||
#define _FFTFILT_H
|
|
||||||
|
|
||||||
#include <complex>
|
|
||||||
#include "gfft.h"
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
|
|
||||||
class fftfilt {
|
|
||||||
enum {NONE, BLACKMAN, HAMMING, HANNING};
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef std::complex<float> cmplx;
|
|
||||||
|
|
||||||
fftfilt(float f1, float f2, int len);
|
|
||||||
fftfilt(float f2, int len);
|
|
||||||
~fftfilt();
|
|
||||||
// f1 < f2 ==> bandpass
|
|
||||||
// f1 > f2 ==> band reject
|
|
||||||
void create_filter(float f1, float f2);
|
|
||||||
void create_dsb_filter(float f2);
|
|
||||||
|
|
||||||
int noFilt(const cmplx& in, cmplx **out);
|
|
||||||
int runFilt(const cmplx& in, cmplx **out);
|
|
||||||
int runSSB(const cmplx& in, cmplx **out, bool usb);
|
|
||||||
int runDSB(const cmplx& in, cmplx **out);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int flen;
|
|
||||||
int flen2;
|
|
||||||
g_fft<float> *fft;
|
|
||||||
g_fft<float> *ift;
|
|
||||||
cmplx *filter;
|
|
||||||
cmplx *data;
|
|
||||||
cmplx *ovlbuf;
|
|
||||||
cmplx *output;
|
|
||||||
int inptr;
|
|
||||||
int pass;
|
|
||||||
int window;
|
|
||||||
|
|
||||||
inline float fsinc(float fc, int i, int len) {
|
|
||||||
return (i == len/2) ? 2.0 * fc:
|
|
||||||
sin(2 * M_PI * fc * (i - len/2)) / (M_PI * (i - len/2));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float _blackman(int i, int len) {
|
|
||||||
return (0.42 -
|
|
||||||
0.50 * cos(2.0 * M_PI * i / len) +
|
|
||||||
0.08 * cos(4.0 * M_PI * i / len));
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_filter();
|
|
||||||
void init_dsb_filter();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Sliding FFT filter from Fldigi */
|
|
||||||
class sfft {
|
|
||||||
#define K1 0.99999
|
|
||||||
public:
|
|
||||||
typedef std::complex<float> cmplx;
|
|
||||||
sfft(int len);
|
|
||||||
~sfft();
|
|
||||||
void run(const cmplx& input);
|
|
||||||
void fetch(float *result);
|
|
||||||
private:
|
|
||||||
int fftlen;
|
|
||||||
int first;
|
|
||||||
int last;
|
|
||||||
int ptr;
|
|
||||||
struct vrot_bins_pair;
|
|
||||||
vrot_bins_pair *vrot_bins;
|
|
||||||
cmplx *delay;
|
|
||||||
float k2;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,37 +0,0 @@
|
|||||||
#ifndef INCLUDE_FFTWENGINE_H
|
|
||||||
#define INCLUDE_FFTWENGINE_H
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <fftw3.h>
|
|
||||||
#include <list>
|
|
||||||
#include "dsp/fftengine.h"
|
|
||||||
|
|
||||||
class FFTWEngine : public FFTEngine {
|
|
||||||
public:
|
|
||||||
FFTWEngine();
|
|
||||||
~FFTWEngine();
|
|
||||||
|
|
||||||
void configure(int n, bool inverse);
|
|
||||||
void transform();
|
|
||||||
|
|
||||||
Complex* in();
|
|
||||||
Complex* out();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static QMutex m_globalPlanMutex;
|
|
||||||
|
|
||||||
struct Plan {
|
|
||||||
int n;
|
|
||||||
bool inverse;
|
|
||||||
fftwf_plan plan;
|
|
||||||
fftwf_complex* in;
|
|
||||||
fftwf_complex* out;
|
|
||||||
};
|
|
||||||
typedef std::list<Plan*> Plans;
|
|
||||||
Plans m_plans;
|
|
||||||
Plan* m_currentPlan;
|
|
||||||
|
|
||||||
void freeAll();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_FFTWENGINE_H
|
|
@ -1,82 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_FFTWINDOW_H
|
|
||||||
#define INCLUDE_FFTWINDOW_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#define _USE_MATH_DEFINES
|
|
||||||
#include <math.h>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API FFTWindow {
|
|
||||||
public:
|
|
||||||
enum Function {
|
|
||||||
Bartlett,
|
|
||||||
BlackmanHarris,
|
|
||||||
Flattop,
|
|
||||||
Hamming,
|
|
||||||
Hanning,
|
|
||||||
Rectangle
|
|
||||||
};
|
|
||||||
|
|
||||||
void create(Function function, int n);
|
|
||||||
void apply(const std::vector<Real>& in, std::vector<Real>* out);
|
|
||||||
void apply(const std::vector<Complex>& in, std::vector<Complex>* out);
|
|
||||||
void apply(const Complex* in, Complex* out);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<float> m_window;
|
|
||||||
|
|
||||||
static inline Real flatTop(Real n, Real i)
|
|
||||||
{
|
|
||||||
// correction ?
|
|
||||||
return 1.0 - 1.93 * cos((2.0 * M_PI * i) / n) + 1.29 * cos((4.0 * M_PI * i) / n) - 0.388 * cos((6.0 * M_PI * i) / n) + 0.03222 * cos((8.0 * M_PI * i) / n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Real bartlett(Real n, Real i)
|
|
||||||
{
|
|
||||||
// amplitude correction = 2.0
|
|
||||||
return (2.0 / (n - 1.0)) * ( (n - 1.0) / 2.0 - fabs(i - (n - 1.0) / 2.0)) * 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Real blackmanHarris(Real n, Real i)
|
|
||||||
{
|
|
||||||
// amplitude correction = 2.79
|
|
||||||
return (0.35875 - 0.48829 * cos((2.0 * M_PI * i) / n) + 0.14128 * cos((4.0 * M_PI * i) / n) - 0.01168 * cos((6.0 * M_PI * i) / n)) * 2.79;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Real hamming(Real n, Real i)
|
|
||||||
{
|
|
||||||
// amplitude correction = 1.855, energy correction = 1.586
|
|
||||||
return (0.54 - 0.46 * cos((2.0 * M_PI * i) / n)) * 1.855;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Real hanning(Real n, Real i)
|
|
||||||
{
|
|
||||||
// amplitude correction = 2.0, energy correction = 1.633
|
|
||||||
return (0.5 - 0.5 * cos((2.0 * M_PI * i) / n)) * 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Real rectangle(Real, Real)
|
|
||||||
{
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_FFTWINDOWS_H
|
|
@ -1,72 +0,0 @@
|
|||||||
#ifndef INCLUDE_FILESINK_H
|
|
||||||
#define INCLUDE_FILESINK_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include "dsp/samplesink.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
#include "util/message.h"
|
|
||||||
#include "util/messagequeue.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API FileSink : public SampleSink {
|
|
||||||
public:
|
|
||||||
|
|
||||||
struct Header
|
|
||||||
{
|
|
||||||
int sampleRate;
|
|
||||||
quint64 centerFrequency;
|
|
||||||
std::time_t startTimeStamp;
|
|
||||||
};
|
|
||||||
|
|
||||||
FileSink();
|
|
||||||
virtual ~FileSink();
|
|
||||||
|
|
||||||
quint64 getByteCount() const { return m_byteCount; }
|
|
||||||
|
|
||||||
void configure(MessageQueue* msgQueue, const std::string& filename);
|
|
||||||
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
void startRecording();
|
|
||||||
void stopRecording();
|
|
||||||
static void readHeader(std::ifstream& samplefile, Header& header);
|
|
||||||
|
|
||||||
private:
|
|
||||||
class MsgConfigureFileSink : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
const std::string& getFileName() const { return m_fileName; }
|
|
||||||
|
|
||||||
static MsgConfigureFileSink* create(const std::string& fileName)
|
|
||||||
{
|
|
||||||
return new MsgConfigureFileSink(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_fileName;
|
|
||||||
|
|
||||||
MsgConfigureFileSink(const std::string& fileName) :
|
|
||||||
Message(),
|
|
||||||
m_fileName(fileName)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string m_fileName;
|
|
||||||
int m_sampleRate;
|
|
||||||
quint64 m_centerFrequency;
|
|
||||||
bool m_recordOn;
|
|
||||||
bool m_recordStart;
|
|
||||||
std::ofstream m_sampleFile;
|
|
||||||
quint64 m_byteCount;
|
|
||||||
|
|
||||||
void handleConfigure(const std::string& fileName);
|
|
||||||
void writeHeader();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_FILESINK_H
|
|
@ -1,50 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_DSP_FILTERRC_H_
|
|
||||||
#define INCLUDE_DSP_FILTERRC_H_
|
|
||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
/** First order low-pass IIR filter for real-valued signals. */
|
|
||||||
class LowPassFilterRC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct 1st order low-pass IIR filter.
|
|
||||||
*
|
|
||||||
* timeconst :: RC time constant in seconds (1 / (2 * PI * cutoff_freq)
|
|
||||||
*/
|
|
||||||
LowPassFilterRC(Real timeconst);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reconfigure filter with new time constant
|
|
||||||
*/
|
|
||||||
void configure(Real timeout);
|
|
||||||
|
|
||||||
/** Process samples. */
|
|
||||||
void process(const Real& sample_in, Real& sample_out);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Real m_timeconst;
|
|
||||||
Real m_y1;
|
|
||||||
Real m_a1;
|
|
||||||
Real m_b0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INCLUDE_DSP_FILTERRC_H_ */
|
|
File diff suppressed because it is too large
Load Diff
@ -1,106 +0,0 @@
|
|||||||
#ifndef INCLUDE_HIGHPASS_H
|
|
||||||
#define INCLUDE_HIGHPASS_H
|
|
||||||
|
|
||||||
#define _USE_MATH_DEFINES
|
|
||||||
#include <math.h>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
template <class Type> class Highpass {
|
|
||||||
public:
|
|
||||||
Highpass() { }
|
|
||||||
|
|
||||||
void create(int nTaps, double sampleRate, double cutoff)
|
|
||||||
{
|
|
||||||
double wc = 2.0 * M_PI * cutoff;
|
|
||||||
double Wc = wc / sampleRate;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// check constraints
|
|
||||||
if(!(nTaps & 1)) {
|
|
||||||
qDebug("Highpass filter has to have an odd number of taps");
|
|
||||||
nTaps++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make room
|
|
||||||
m_samples.resize(nTaps);
|
|
||||||
for(int i = 0; i < nTaps; i++)
|
|
||||||
m_samples[i] = 0;
|
|
||||||
m_ptr = 0;
|
|
||||||
m_taps.resize(nTaps / 2 + 1);
|
|
||||||
|
|
||||||
// generate Sinc filter core for lowpass but inverting every other tap for highpass keeping center tap
|
|
||||||
for(i = 0; i < nTaps / 2 + 1; i++) {
|
|
||||||
if(i == (nTaps - 1) / 2)
|
|
||||||
m_taps[i] = -(Wc / M_PI);
|
|
||||||
else
|
|
||||||
m_taps[i] = -sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wc) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_taps[(nTaps - 1) / 2] += 1;
|
|
||||||
|
|
||||||
// apply Hamming window
|
|
||||||
for(i = 0; i < nTaps / 2 + 1; i++)
|
|
||||||
m_taps[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps);
|
|
||||||
|
|
||||||
// normalize
|
|
||||||
Real sum = 0;
|
|
||||||
for(i = 0; i < (int)m_taps.size() - 1; i++)
|
|
||||||
sum += m_taps[i] * 2;
|
|
||||||
sum += m_taps[i];
|
|
||||||
for(i = 0; i < (int)m_taps.size(); i++)
|
|
||||||
m_taps[i] /= sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type filter(Type sample)
|
|
||||||
{
|
|
||||||
Type acc = 0;
|
|
||||||
int a = m_ptr;
|
|
||||||
int b = a - 1;
|
|
||||||
int i, n_taps, size;
|
|
||||||
|
|
||||||
m_samples[m_ptr] = sample;
|
|
||||||
size = m_samples.size(); // Valgrind optim (2)
|
|
||||||
|
|
||||||
while(b < 0)
|
|
||||||
{
|
|
||||||
b += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
n_taps = m_taps.size() - 1; // Valgrind optim
|
|
||||||
|
|
||||||
for (i = 0; i < n_taps; i++)
|
|
||||||
{
|
|
||||||
acc += (m_samples[a] + m_samples[b]) * m_taps[i];
|
|
||||||
a++;
|
|
||||||
|
|
||||||
while (a >= size)
|
|
||||||
{
|
|
||||||
a -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
b--;
|
|
||||||
|
|
||||||
while (b < 0)
|
|
||||||
{
|
|
||||||
b += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
acc += m_samples[a] * m_taps[i];
|
|
||||||
m_ptr++;
|
|
||||||
|
|
||||||
while (m_ptr >= size)
|
|
||||||
{
|
|
||||||
m_ptr -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<Real> m_taps;
|
|
||||||
std::vector<Type> m_samples;
|
|
||||||
int m_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_HIGHPASS_H
|
|
@ -1,135 +0,0 @@
|
|||||||
#ifndef INCLUDE_INTERPOLATOR_H
|
|
||||||
#define INCLUDE_INTERPOLATOR_H
|
|
||||||
|
|
||||||
#ifdef USE_SIMD
|
|
||||||
#include <immintrin.h>
|
|
||||||
#endif
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class SDRANGEL_API Interpolator {
|
|
||||||
public:
|
|
||||||
Interpolator();
|
|
||||||
~Interpolator();
|
|
||||||
|
|
||||||
void create(int phaseSteps, double sampleRate, double cutoff);
|
|
||||||
void free();
|
|
||||||
|
|
||||||
// Original code allowed for upsampling, but was never used that way
|
|
||||||
bool interpolate(Real *distance, const Complex& next, Complex* result)
|
|
||||||
{
|
|
||||||
advanceFilter(next);
|
|
||||||
*distance -= 1.0;
|
|
||||||
|
|
||||||
if (*distance >= 1.0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
doInterpolate((int) floor(*distance * (Real)m_phaseSteps), result);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
float* m_taps;
|
|
||||||
float* m_alignedTaps;
|
|
||||||
float* m_taps2;
|
|
||||||
float* m_alignedTaps2;
|
|
||||||
std::vector<Complex> m_samples;
|
|
||||||
int m_ptr;
|
|
||||||
int m_phaseSteps;
|
|
||||||
int m_nTaps;
|
|
||||||
|
|
||||||
void createTaps(int nTaps, double sampleRate, double cutoff, std::vector<Real>* taps);
|
|
||||||
|
|
||||||
void advanceFilter(const Complex& next)
|
|
||||||
{
|
|
||||||
m_ptr--;
|
|
||||||
if(m_ptr < 0)
|
|
||||||
m_ptr = m_nTaps - 1;
|
|
||||||
m_samples[m_ptr] = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void doInterpolate(int phase, Complex* result)
|
|
||||||
{
|
|
||||||
if (phase < 0)
|
|
||||||
phase = 0;
|
|
||||||
#if USE_SIMD
|
|
||||||
// beware of the ringbuffer
|
|
||||||
if(m_ptr == 0) {
|
|
||||||
// only one straight block
|
|
||||||
const float* src = (const float*)&m_samples[0];
|
|
||||||
const __m128* filter = (const __m128*)&m_alignedTaps[phase * m_nTaps * 2];
|
|
||||||
__m128 sum = _mm_setzero_ps();
|
|
||||||
int todo = m_nTaps / 2;
|
|
||||||
|
|
||||||
for(int i = 0; i < todo; i++) {
|
|
||||||
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(src), *filter));
|
|
||||||
src += 4;
|
|
||||||
filter += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add upper half to lower half and store
|
|
||||||
_mm_storel_pi((__m64*)result, _mm_add_ps(sum, _mm_shuffle_ps(sum, _mm_setzero_ps(), _MM_SHUFFLE(1, 0, 3, 2))));
|
|
||||||
} else {
|
|
||||||
// two blocks
|
|
||||||
const float* src = (const float*)&m_samples[m_ptr];
|
|
||||||
const __m128* filter = (const __m128*)&m_alignedTaps[phase * m_nTaps * 2];
|
|
||||||
__m128 sum = _mm_setzero_ps();
|
|
||||||
|
|
||||||
// first block
|
|
||||||
int block = m_nTaps - m_ptr;
|
|
||||||
int todo = block / 2;
|
|
||||||
if(block & 1)
|
|
||||||
todo++;
|
|
||||||
for(int i = 0; i < todo; i++) {
|
|
||||||
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(src), *filter));
|
|
||||||
src += 4;
|
|
||||||
filter += 1;
|
|
||||||
}
|
|
||||||
if(block & 1) {
|
|
||||||
// one sample beyond the end -> switch coefficient table
|
|
||||||
filter = (const __m128*)&m_alignedTaps2[phase * m_nTaps * 2 + todo * 4 - 4];
|
|
||||||
}
|
|
||||||
// second block
|
|
||||||
src = (const float*)&m_samples[0];
|
|
||||||
block = m_ptr;
|
|
||||||
todo = block / 2;
|
|
||||||
for(int i = 0; i < todo; i++) {
|
|
||||||
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(src), *filter));
|
|
||||||
src += 4;
|
|
||||||
filter += 1;
|
|
||||||
}
|
|
||||||
if(block & 1) {
|
|
||||||
// one sample remaining
|
|
||||||
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadl_pi(_mm_setzero_ps(), (const __m64*)src), filter[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// add upper half to lower half and store
|
|
||||||
_mm_storel_pi((__m64*)result, _mm_add_ps(sum, _mm_shuffle_ps(sum, _mm_setzero_ps(), _MM_SHUFFLE(1, 0, 3, 2))));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int sample = m_ptr;
|
|
||||||
const Real* coeff = &m_alignedTaps[phase * m_nTaps * 2];
|
|
||||||
Real rAcc = 0;
|
|
||||||
Real iAcc = 0;
|
|
||||||
|
|
||||||
for(int i = 0; i < m_nTaps; i++) {
|
|
||||||
rAcc += *coeff * m_samples[sample].real();
|
|
||||||
iAcc += *coeff * m_samples[sample].imag();
|
|
||||||
sample = (sample + 1) % m_nTaps;
|
|
||||||
coeff += 2;
|
|
||||||
}
|
|
||||||
*result = Complex(rAcc, iAcc);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_INTERPOLATOR_H
|
|
@ -1,476 +0,0 @@
|
|||||||
#ifndef INCLUDE_INTHALFBANDFILTER_H
|
|
||||||
#define INCLUDE_INTHALFBANDFILTER_H
|
|
||||||
|
|
||||||
#include <QtGlobal>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
// uses Q1.14 format internally, input and output are S16
|
|
||||||
|
|
||||||
/*
|
|
||||||
* supported filter orders: 64, 48, 32
|
|
||||||
*/
|
|
||||||
#define HB_FILTERORDER 32
|
|
||||||
#define HB_SHIFT 14
|
|
||||||
|
|
||||||
class SDRANGEL_API IntHalfbandFilter {
|
|
||||||
public:
|
|
||||||
IntHalfbandFilter();
|
|
||||||
|
|
||||||
// downsample by 2, return center part of original spectrum
|
|
||||||
bool workDecimateCenter(Sample* sample)
|
|
||||||
{
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = sample->real();
|
|
||||||
m_samples[m_ptr][1] = sample->imag();
|
|
||||||
|
|
||||||
switch(m_state)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 1;
|
|
||||||
|
|
||||||
// tell caller we don't have a new sample
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// save result
|
|
||||||
doFIR(sample);
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 0;
|
|
||||||
|
|
||||||
// tell caller we have a new sample
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool workDecimateCenter(qint32 *x, qint32 *y)
|
|
||||||
{
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = *x;
|
|
||||||
m_samples[m_ptr][1] = *y;
|
|
||||||
|
|
||||||
switch(m_state)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 1;
|
|
||||||
|
|
||||||
// tell caller we don't have a new sample
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// save result
|
|
||||||
doFIR(x, y);
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 0;
|
|
||||||
|
|
||||||
// tell caller we have a new sample
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// downsample by 2, return edges of spectrum rotated into center
|
|
||||||
bool workDecimateFullRotate(Sample* sample)
|
|
||||||
{
|
|
||||||
switch(m_state)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = sample->real();
|
|
||||||
m_samples[m_ptr][1] = sample->imag();
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 1;
|
|
||||||
|
|
||||||
// tell caller we don't have a new sample
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = -sample->real();
|
|
||||||
m_samples[m_ptr][1] = sample->imag();
|
|
||||||
|
|
||||||
// save result
|
|
||||||
doFIR(sample);
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 0;
|
|
||||||
|
|
||||||
// tell caller we have a new sample
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// downsample by 2, return lower half of original spectrum
|
|
||||||
bool workDecimateLowerHalf(Sample* sample)
|
|
||||||
{
|
|
||||||
switch(m_state)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = -sample->imag();
|
|
||||||
m_samples[m_ptr][1] = sample->real();
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 1;
|
|
||||||
|
|
||||||
// tell caller we don't have a new sample
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = -sample->real();
|
|
||||||
m_samples[m_ptr][1] = -sample->imag();
|
|
||||||
|
|
||||||
// save result
|
|
||||||
doFIR(sample);
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 2;
|
|
||||||
|
|
||||||
// tell caller we have a new sample
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = sample->imag();
|
|
||||||
m_samples[m_ptr][1] = -sample->real();
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 3;
|
|
||||||
|
|
||||||
// tell caller we don't have a new sample
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = sample->real();
|
|
||||||
m_samples[m_ptr][1] = sample->imag();
|
|
||||||
|
|
||||||
// save result
|
|
||||||
doFIR(sample);
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 0;
|
|
||||||
|
|
||||||
// tell caller we have a new sample
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// downsample by 2, return upper half of original spectrum
|
|
||||||
bool workDecimateUpperHalf(Sample* sample)
|
|
||||||
{
|
|
||||||
switch(m_state)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = sample->imag();
|
|
||||||
m_samples[m_ptr][1] = -sample->real();
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 1;
|
|
||||||
|
|
||||||
// tell caller we don't have a new sample
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = -sample->real();
|
|
||||||
m_samples[m_ptr][1] = -sample->imag();
|
|
||||||
|
|
||||||
// save result
|
|
||||||
doFIR(sample);
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 2;
|
|
||||||
|
|
||||||
// tell caller we have a new sample
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = -sample->imag();
|
|
||||||
m_samples[m_ptr][1] = sample->real();
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 3;
|
|
||||||
|
|
||||||
// tell caller we don't have a new sample
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// insert sample into ring-buffer
|
|
||||||
m_samples[m_ptr][0] = sample->real();
|
|
||||||
m_samples[m_ptr][1] = sample->imag();
|
|
||||||
|
|
||||||
// save result
|
|
||||||
doFIR(sample);
|
|
||||||
|
|
||||||
// advance write-pointer
|
|
||||||
m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
|
||||||
|
|
||||||
// next state
|
|
||||||
m_state = 0;
|
|
||||||
|
|
||||||
// tell caller we have a new sample
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void myDecimate(const Sample* sample1, Sample* sample2)
|
|
||||||
{
|
|
||||||
static const qint16 mod33[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
|
|
||||||
20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2};
|
|
||||||
|
|
||||||
m_samples[m_ptr][0] = sample1->real();
|
|
||||||
m_samples[m_ptr][1] = sample1->imag();
|
|
||||||
m_ptr = mod33[m_ptr + 2 - 1];
|
|
||||||
|
|
||||||
m_samples[m_ptr][0] = sample2->real();
|
|
||||||
m_samples[m_ptr][1] = sample2->imag();
|
|
||||||
|
|
||||||
doFIR(sample2);
|
|
||||||
|
|
||||||
m_ptr = mod33[m_ptr + 2 - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
void myDecimate(qint32 x1, qint32 y1, qint32 *x2, qint32 *y2)
|
|
||||||
{
|
|
||||||
static const qint16 mod33[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
|
|
||||||
20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2};
|
|
||||||
|
|
||||||
m_samples[m_ptr][0] = x1;
|
|
||||||
m_samples[m_ptr][1] = y1;
|
|
||||||
m_ptr = mod33[m_ptr + 2 - 1];
|
|
||||||
|
|
||||||
m_samples[m_ptr][0] = *x2;
|
|
||||||
m_samples[m_ptr][1] = *y2;
|
|
||||||
|
|
||||||
doFIR(x2, y2);
|
|
||||||
|
|
||||||
m_ptr = mod33[m_ptr + 2 - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
qint32 m_samples[HB_FILTERORDER + 1][2]; // Valgrind optim (from qint16)
|
|
||||||
qint16 m_ptr;
|
|
||||||
int m_state;
|
|
||||||
|
|
||||||
void doFIR(Sample* sample)
|
|
||||||
{
|
|
||||||
// coefficents
|
|
||||||
|
|
||||||
#if HB_FILTERORDER == 64
|
|
||||||
static const qint32 COEFF[16] = {
|
|
||||||
-0.001114417441601693505720538368564120901 * (1 << HB_SHIFT),
|
|
||||||
0.001268007827185253051302527005361753254 * (1 << HB_SHIFT),
|
|
||||||
-0.001959831378850490895410230152151598304 * (1 << HB_SHIFT),
|
|
||||||
0.002878308307661380308073439948657323839 * (1 << HB_SHIFT),
|
|
||||||
-0.004071361818258721100571850826099762344 * (1 << HB_SHIFT),
|
|
||||||
0.005597288494657440618973431867289036745 * (1 << HB_SHIFT),
|
|
||||||
-0.007532345003308904551886371336877346039 * (1 << HB_SHIFT),
|
|
||||||
0.009980346844667375288961963519795972388 * (1 << HB_SHIFT),
|
|
||||||
-0.013092614174300500062830820979797863401 * (1 << HB_SHIFT),
|
|
||||||
0.01710934914871829748417297878404497169 * (1 << HB_SHIFT),
|
|
||||||
-0.022443558692997273018576720460259821266 * (1 << HB_SHIFT),
|
|
||||||
0.029875811511593811098386197500076377764 * (1 << HB_SHIFT),
|
|
||||||
-0.041086352085710403647667021687084343284 * (1 << HB_SHIFT),
|
|
||||||
0.060465467462665789533104998554335907102 * (1 << HB_SHIFT),
|
|
||||||
-0.104159517495977321788203084906854201108 * (1 << HB_SHIFT),
|
|
||||||
0.317657589850154464805598308885237202048 * (1 << HB_SHIFT),
|
|
||||||
};
|
|
||||||
#elif HB_FILTERORDER == 48
|
|
||||||
static const qint32 COEFF[12] = {
|
|
||||||
-0.004102576237611492253332112767338912818 * (1 << HB_SHIFT),
|
|
||||||
0.003950551047979387886410762575906119309 * (1 << HB_SHIFT),
|
|
||||||
-0.005807875789391703583164350277456833282 * (1 << HB_SHIFT),
|
|
||||||
0.00823497890520805998770814682075069868 * (1 << HB_SHIFT),
|
|
||||||
-0.011372226513199541059195851744334504474 * (1 << HB_SHIFT),
|
|
||||||
0.015471557140973646315984524335362948477 * (1 << HB_SHIFT),
|
|
||||||
-0.020944996398689276484450516591095947661 * (1 << HB_SHIFT),
|
|
||||||
0.028568078132034283034279553703527199104 * (1 << HB_SHIFT),
|
|
||||||
-0.040015143905614086738964374490024056286 * (1 << HB_SHIFT),
|
|
||||||
0.059669519431831075095828964549582451582 * (1 << HB_SHIFT),
|
|
||||||
-0.103669138691865420076609893840213771909 * (1 << HB_SHIFT),
|
|
||||||
0.317491986549921390015072120149852707982 * (1 << HB_SHIFT)
|
|
||||||
};
|
|
||||||
#elif HB_FILTERORDER == 32
|
|
||||||
static const qint16 mod33[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
|
|
||||||
20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2} ;
|
|
||||||
static const qint32 COEFF[8] = {
|
|
||||||
(qint32)(-0.015956912844043127236437484839370881673 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)( 0.013023031678944928940522274274371739011 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)(-0.01866942273717486777684371190844103694 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)( 0.026550887571157304190005987720724078827 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)(-0.038350314277854319344740474662103224546 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)( 0.058429248652825838128421764849917963147 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)(-0.102889802028955756885153505209018476307 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)( 0.317237706405931241260276465254719369113 * (1 << HB_SHIFT))
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
#error unsupported filter order
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// init read-pointer
|
|
||||||
int a = mod33[m_ptr + 2 + 1]; // 0 + 1
|
|
||||||
int b = mod33[m_ptr + 2 - 2]; //-1 - 1
|
|
||||||
|
|
||||||
// go through samples in buffer
|
|
||||||
qint32 iAcc = 0;
|
|
||||||
qint32 qAcc = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < HB_FILTERORDER / 4; i++)
|
|
||||||
{
|
|
||||||
// do multiply-accumulate
|
|
||||||
//qint32 iTmp = m_samples[a][0] + m_samples[b][0]; // Valgrind optim
|
|
||||||
//qint32 qTmp = m_samples[a][1] + m_samples[b][1]; // Valgrind optim
|
|
||||||
iAcc += (m_samples[a][0] + m_samples[b][0]) * COEFF[i];
|
|
||||||
qAcc += (m_samples[a][1] + m_samples[b][1]) * COEFF[i];
|
|
||||||
|
|
||||||
// update read-pointer
|
|
||||||
a = mod33[a + 2 + 2];
|
|
||||||
b = mod33[b + 2 - 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
a = mod33[a + 2 - 1];
|
|
||||||
|
|
||||||
iAcc += ((qint32)m_samples[a][0] + 1) << (HB_SHIFT - 1);
|
|
||||||
qAcc += ((qint32)m_samples[a][1] + 1) << (HB_SHIFT - 1);
|
|
||||||
|
|
||||||
sample->setReal(iAcc >> HB_SHIFT);
|
|
||||||
sample->setImag(qAcc >> HB_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void doFIR(qint32 *x, qint32 *y)
|
|
||||||
{
|
|
||||||
// coefficents
|
|
||||||
|
|
||||||
#if HB_FILTERORDER == 64
|
|
||||||
static const qint32 COEFF[16] = {
|
|
||||||
-0.001114417441601693505720538368564120901 * (1 << HB_SHIFT),
|
|
||||||
0.001268007827185253051302527005361753254 * (1 << HB_SHIFT),
|
|
||||||
-0.001959831378850490895410230152151598304 * (1 << HB_SHIFT),
|
|
||||||
0.002878308307661380308073439948657323839 * (1 << HB_SHIFT),
|
|
||||||
-0.004071361818258721100571850826099762344 * (1 << HB_SHIFT),
|
|
||||||
0.005597288494657440618973431867289036745 * (1 << HB_SHIFT),
|
|
||||||
-0.007532345003308904551886371336877346039 * (1 << HB_SHIFT),
|
|
||||||
0.009980346844667375288961963519795972388 * (1 << HB_SHIFT),
|
|
||||||
-0.013092614174300500062830820979797863401 * (1 << HB_SHIFT),
|
|
||||||
0.01710934914871829748417297878404497169 * (1 << HB_SHIFT),
|
|
||||||
-0.022443558692997273018576720460259821266 * (1 << HB_SHIFT),
|
|
||||||
0.029875811511593811098386197500076377764 * (1 << HB_SHIFT),
|
|
||||||
-0.041086352085710403647667021687084343284 * (1 << HB_SHIFT),
|
|
||||||
0.060465467462665789533104998554335907102 * (1 << HB_SHIFT),
|
|
||||||
-0.104159517495977321788203084906854201108 * (1 << HB_SHIFT),
|
|
||||||
0.317657589850154464805598308885237202048 * (1 << HB_SHIFT),
|
|
||||||
};
|
|
||||||
#elif HB_FILTERORDER == 48
|
|
||||||
static const qint32 COEFF[12] = {
|
|
||||||
-0.004102576237611492253332112767338912818 * (1 << HB_SHIFT),
|
|
||||||
0.003950551047979387886410762575906119309 * (1 << HB_SHIFT),
|
|
||||||
-0.005807875789391703583164350277456833282 * (1 << HB_SHIFT),
|
|
||||||
0.00823497890520805998770814682075069868 * (1 << HB_SHIFT),
|
|
||||||
-0.011372226513199541059195851744334504474 * (1 << HB_SHIFT),
|
|
||||||
0.015471557140973646315984524335362948477 * (1 << HB_SHIFT),
|
|
||||||
-0.020944996398689276484450516591095947661 * (1 << HB_SHIFT),
|
|
||||||
0.028568078132034283034279553703527199104 * (1 << HB_SHIFT),
|
|
||||||
-0.040015143905614086738964374490024056286 * (1 << HB_SHIFT),
|
|
||||||
0.059669519431831075095828964549582451582 * (1 << HB_SHIFT),
|
|
||||||
-0.103669138691865420076609893840213771909 * (1 << HB_SHIFT),
|
|
||||||
0.317491986549921390015072120149852707982 * (1 << HB_SHIFT)
|
|
||||||
};
|
|
||||||
#elif HB_FILTERORDER == 32
|
|
||||||
static const int mod33[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
|
|
||||||
20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2} ;
|
|
||||||
static const qint32 COEFF[8] = {
|
|
||||||
(qint32)(-0.015956912844043127236437484839370881673 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)( 0.013023031678944928940522274274371739011 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)(-0.01866942273717486777684371190844103694 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)( 0.026550887571157304190005987720724078827 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)(-0.038350314277854319344740474662103224546 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)( 0.058429248652825838128421764849917963147 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)(-0.102889802028955756885153505209018476307 * (1 << HB_SHIFT)),
|
|
||||||
(qint32)( 0.317237706405931241260276465254719369113 * (1 << HB_SHIFT))
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
#error unsupported filter order
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// init read-pointer
|
|
||||||
int a = mod33[m_ptr + 2 + 1]; // 0 + 1
|
|
||||||
int b = mod33[m_ptr + 2 - 2]; //-1 - 1
|
|
||||||
|
|
||||||
// go through samples in buffer
|
|
||||||
qint32 iAcc = 0;
|
|
||||||
qint32 qAcc = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < HB_FILTERORDER / 4; i++)
|
|
||||||
{
|
|
||||||
// do multiply-accumulate
|
|
||||||
//qint32 iTmp = m_samples[a][0] + m_samples[b][0]; // Valgrind optim
|
|
||||||
//qint32 qTmp = m_samples[a][1] + m_samples[b][1]; // Valgrind optim
|
|
||||||
iAcc += (m_samples[a][0] + m_samples[b][0]) * COEFF[i];
|
|
||||||
qAcc += (m_samples[a][1] + m_samples[b][1]) * COEFF[i];
|
|
||||||
|
|
||||||
// update read-pointer
|
|
||||||
a = mod33[a + 2 + 2];
|
|
||||||
b = mod33[b + 2 - 2];
|
|
||||||
}
|
|
||||||
|
|
||||||
a = mod33[a + 2 - 1];
|
|
||||||
|
|
||||||
iAcc += ((qint32)m_samples[a][0] + 1) << (HB_SHIFT - 1);
|
|
||||||
qAcc += ((qint32)m_samples[a][1] + 1) << (HB_SHIFT - 1);
|
|
||||||
|
|
||||||
*x = iAcc >> (HB_SHIFT -1); // HB_SHIFT incorrect do not loose the gained bit
|
|
||||||
*y = qAcc >> (HB_SHIFT -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_INTHALFBANDFILTER_H
|
|
@ -1,23 +0,0 @@
|
|||||||
#ifndef INCLUDE_KISSENGINE_H
|
|
||||||
#define INCLUDE_KISSENGINE_H
|
|
||||||
|
|
||||||
#include "dsp/fftengine.h"
|
|
||||||
#include "dsp/kissfft.h"
|
|
||||||
|
|
||||||
class KissEngine : public FFTEngine {
|
|
||||||
public:
|
|
||||||
void configure(int n, bool inverse);
|
|
||||||
void transform();
|
|
||||||
|
|
||||||
Complex* in();
|
|
||||||
Complex* out();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typedef kissfft<Real, Complex> KissFFT;
|
|
||||||
KissFFT m_fft;
|
|
||||||
|
|
||||||
std::vector<Complex> m_in;
|
|
||||||
std::vector<Complex> m_out;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_KISSENGINE_H
|
|
@ -1,391 +0,0 @@
|
|||||||
#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
|
|
@ -1,104 +0,0 @@
|
|||||||
#ifndef INCLUDE_LOWPASS_H
|
|
||||||
#define INCLUDE_LOWPASS_H
|
|
||||||
|
|
||||||
#define _USE_MATH_DEFINES
|
|
||||||
#include <math.h>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
template <class Type> class Lowpass {
|
|
||||||
public:
|
|
||||||
Lowpass() { }
|
|
||||||
|
|
||||||
void create(int nTaps, double sampleRate, double cutoff)
|
|
||||||
{
|
|
||||||
double wc = 2.0 * M_PI * cutoff;
|
|
||||||
double Wc = wc / sampleRate;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// check constraints
|
|
||||||
if(!(nTaps & 1)) {
|
|
||||||
qDebug("Lowpass filter has to have an odd number of taps");
|
|
||||||
nTaps++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make room
|
|
||||||
m_samples.resize(nTaps);
|
|
||||||
for(int i = 0; i < nTaps; i++)
|
|
||||||
m_samples[i] = 0;
|
|
||||||
m_ptr = 0;
|
|
||||||
m_taps.resize(nTaps / 2 + 1);
|
|
||||||
|
|
||||||
// generate Sinc filter core
|
|
||||||
for(i = 0; i < nTaps / 2 + 1; i++) {
|
|
||||||
if(i == (nTaps - 1) / 2)
|
|
||||||
m_taps[i] = Wc / M_PI;
|
|
||||||
else
|
|
||||||
m_taps[i] = sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wc) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI);
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply Hamming window
|
|
||||||
for(i = 0; i < nTaps / 2 + 1; i++)
|
|
||||||
m_taps[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps);
|
|
||||||
|
|
||||||
// normalize
|
|
||||||
Real sum = 0;
|
|
||||||
for(i = 0; i < (int)m_taps.size() - 1; i++)
|
|
||||||
sum += m_taps[i] * 2;
|
|
||||||
sum += m_taps[i];
|
|
||||||
for(i = 0; i < (int)m_taps.size(); i++)
|
|
||||||
m_taps[i] /= sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type filter(Type sample)
|
|
||||||
{
|
|
||||||
Type acc = 0;
|
|
||||||
int a = m_ptr;
|
|
||||||
int b = a - 1;
|
|
||||||
int i, n_taps, size;
|
|
||||||
|
|
||||||
m_samples[m_ptr] = sample;
|
|
||||||
size = m_samples.size(); // Valgrind optim (2)
|
|
||||||
|
|
||||||
while (b < 0)
|
|
||||||
{
|
|
||||||
b += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
n_taps = m_taps.size() - 1; // Valgrind optim
|
|
||||||
|
|
||||||
for (i = 0; i < n_taps; i++)
|
|
||||||
{
|
|
||||||
acc += (m_samples[a] + m_samples[b]) * m_taps[i];
|
|
||||||
a++;
|
|
||||||
|
|
||||||
while (a >= size)
|
|
||||||
{
|
|
||||||
a -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
b--;
|
|
||||||
|
|
||||||
while(b < 0)
|
|
||||||
{
|
|
||||||
b += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
acc += m_samples[a] * m_taps[i];
|
|
||||||
m_ptr++;
|
|
||||||
|
|
||||||
while(m_ptr >= size)
|
|
||||||
{
|
|
||||||
m_ptr -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<Real> m_taps;
|
|
||||||
std::vector<Type> m_samples;
|
|
||||||
int m_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_LOWPASS_H
|
|
@ -1,75 +0,0 @@
|
|||||||
// ----------------------------------------------------------------------------
|
|
||||||
// misc.h -- Miscellaneous helper functions
|
|
||||||
//
|
|
||||||
// Copyright (C) 2006-2008
|
|
||||||
// Dave Freese, W1HKJ
|
|
||||||
//
|
|
||||||
// This file is part of fldigi. These filters were adapted from code contained
|
|
||||||
// in the gmfsk source code distribution.
|
|
||||||
//
|
|
||||||
// Fldigi 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, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// Fldigi 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 for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef _MISC_H
|
|
||||||
#define _MISC_H
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
inline float sinc(float x)
|
|
||||||
{
|
|
||||||
return (fabs(x) < 1e-10) ? 1.0 : (sin(M_PI * x) / (M_PI * x));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float cosc(float x)
|
|
||||||
{
|
|
||||||
return (fabs(x) < 1e-10) ? 0.0 : ((1.0 - cos(M_PI * x)) / (M_PI * x));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float clamp(float x, float min, float max)
|
|
||||||
{
|
|
||||||
return (x < min) ? min : ((x > max) ? max : x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is always called with an int weight
|
|
||||||
inline float decayavg(float average, float input, int weight)
|
|
||||||
{
|
|
||||||
if (weight <= 1) return input;
|
|
||||||
return ( ( input - average ) / (float)weight ) + average ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// following are defined inline to provide best performance
|
|
||||||
inline float blackman(float x)
|
|
||||||
{
|
|
||||||
return (0.42 - 0.50 * cos(2 * M_PI * x) + 0.08 * cos(4 * M_PI * x));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float hamming(float x)
|
|
||||||
{
|
|
||||||
return 0.54 - 0.46 * cos(2 * M_PI * x);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float hanning(float x)
|
|
||||||
{
|
|
||||||
return 0.5 - 0.5 * cos(2 * M_PI * x);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float rcos( float t, float T, float alpha=1.0 )
|
|
||||||
{
|
|
||||||
if( t == 0 ) return 1.0;
|
|
||||||
float taT = T / (2.0 * alpha);
|
|
||||||
if( fabs(t) == taT ) return ((alpha/2.0) * sin(M_PI/(2.0*alpha)));
|
|
||||||
return (sin(M_PI*t/T)/(M_PI*t/T))*cos(alpha*M_PI*t/T)/(1.0-(t/taT)*(t/taT));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,65 +0,0 @@
|
|||||||
#ifndef INCLUDE_MOVINGAVERAGE_H
|
|
||||||
#define INCLUDE_MOVINGAVERAGE_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
template<class Type> class MovingAverage {
|
|
||||||
public:
|
|
||||||
MovingAverage() :
|
|
||||||
m_history(),
|
|
||||||
m_sum(0),
|
|
||||||
m_ptr(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MovingAverage(int historySize, Type initial) :
|
|
||||||
m_history(historySize, initial),
|
|
||||||
m_sum((float) historySize * initial),
|
|
||||||
m_ptr(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(int historySize, Type initial)
|
|
||||||
{
|
|
||||||
m_history.resize(historySize);
|
|
||||||
for(size_t i = 0; i < m_history.size(); i++)
|
|
||||||
m_history[i] = initial;
|
|
||||||
m_sum = (float) m_history.size() * initial;
|
|
||||||
m_ptr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void feed(Type value)
|
|
||||||
{
|
|
||||||
m_sum -= m_history[m_ptr];
|
|
||||||
m_history[m_ptr] = value;
|
|
||||||
m_sum += value;
|
|
||||||
m_ptr++;
|
|
||||||
if(m_ptr >= m_history.size())
|
|
||||||
m_ptr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill(Type value)
|
|
||||||
{
|
|
||||||
for(size_t i = 0; i < m_history.size(); i++)
|
|
||||||
m_history[i] = value;
|
|
||||||
m_sum = (float) m_history.size() * value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type average() const
|
|
||||||
{
|
|
||||||
return m_sum / (float) m_history.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
Type sum() const
|
|
||||||
{
|
|
||||||
return m_sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<Type> m_history;
|
|
||||||
Type m_sum;
|
|
||||||
uint m_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_MOVINGAVERAGE_H
|
|
@ -1,45 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_NCO_H
|
|
||||||
#define INCLUDE_NCO_H
|
|
||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API NCO {
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
TableSize = (1 << 12),
|
|
||||||
};
|
|
||||||
static Real m_table[TableSize];
|
|
||||||
static bool m_tableInitialized;
|
|
||||||
|
|
||||||
static void initTable();
|
|
||||||
|
|
||||||
int m_phaseIncrement;
|
|
||||||
int m_phase;
|
|
||||||
|
|
||||||
public:
|
|
||||||
NCO();
|
|
||||||
|
|
||||||
void setFreq(Real freq, Real sampleRate);
|
|
||||||
Real next();
|
|
||||||
Complex nextIQ();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_NCO_H
|
|
@ -1,22 +0,0 @@
|
|||||||
#ifndef INCLUDE_NULLSINK_H
|
|
||||||
#define INCLUDE_NULLSINK_H
|
|
||||||
|
|
||||||
#include "dsp/samplesink.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class Message;
|
|
||||||
|
|
||||||
class SDRANGEL_API NullSink : public SampleSink {
|
|
||||||
public:
|
|
||||||
|
|
||||||
NullSink();
|
|
||||||
virtual ~NullSink();
|
|
||||||
|
|
||||||
virtual bool init(const Message& cmd);
|
|
||||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_NULLSINK_H
|
|
@ -1,78 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_DSP_PHASEDISCRI_H_
|
|
||||||
#define INCLUDE_DSP_PHASEDISCRI_H_
|
|
||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
class PhaseDiscriminators
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Reset stored values
|
|
||||||
*/
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
m_m1Sample = 0;
|
|
||||||
m_m2Sample = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scaling factor so that resulting excursion maps to [-1,+1]
|
|
||||||
*/
|
|
||||||
void setFMScaling(Real fmScaling)
|
|
||||||
{
|
|
||||||
m_fmScaling = fmScaling;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard discriminator using atan2. On modern processors this is as efficient as the non atan2 one.
|
|
||||||
* This is better for high fidelity.
|
|
||||||
*/
|
|
||||||
Real phaseDiscriminator(const Complex& sample)
|
|
||||||
{
|
|
||||||
Complex d(std::conj(m_m1Sample) * sample);
|
|
||||||
m_m1Sample = sample;
|
|
||||||
return (std::atan2(d.imag(), d.real()) / M_PI_2) * m_fmScaling;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alternative without atan at the expense of a slight distorsion on very wideband signals
|
|
||||||
* http://www.embedded.com/design/configurable-systems/4212086/DSP-Tricks--Frequency-demodulation-algorithms-
|
|
||||||
* in addition it needs scaling by instantaneous magnitude squared and volume (0..10) adjustment factor
|
|
||||||
*/
|
|
||||||
Real phaseDiscriminator2(const Complex& sample)
|
|
||||||
{
|
|
||||||
Real ip = sample.real() - m_m2Sample.real();
|
|
||||||
Real qp = sample.imag() - m_m2Sample.imag();
|
|
||||||
Real h1 = m_m1Sample.real() * qp;
|
|
||||||
Real h2 = m_m1Sample.imag() * ip;
|
|
||||||
|
|
||||||
m_m2Sample = m_m1Sample;
|
|
||||||
m_m1Sample = sample;
|
|
||||||
|
|
||||||
return ((h1 - h2) / M_PI_2) * m_fmScaling;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Complex m_m1Sample;
|
|
||||||
Complex m_m2Sample;
|
|
||||||
Real m_fmScaling;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INCLUDE_DSP_PHASEDISCRI_H_ */
|
|
@ -1,159 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
/** Phase-locked loop mainly for broadcadt FM stereo pilot. */
|
|
||||||
class PhaseLock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/** Expected pilot frequency (used for PPS events). */
|
|
||||||
static const int pilot_frequency = 19000;
|
|
||||||
|
|
||||||
/** Timestamp event produced once every 19000 pilot periods. */
|
|
||||||
struct PpsEvent
|
|
||||||
{
|
|
||||||
quint64 pps_index;
|
|
||||||
quint64 sample_index;
|
|
||||||
double block_position;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct phase-locked loop.
|
|
||||||
*
|
|
||||||
* freq :: 19 kHz center frequency relative to sample freq
|
|
||||||
* (0.5 is Nyquist)
|
|
||||||
* bandwidth :: bandwidth relative to sample frequency
|
|
||||||
* minsignal :: minimum pilot amplitude
|
|
||||||
*/
|
|
||||||
PhaseLock(Real freq, Real bandwidth, Real minsignal);
|
|
||||||
|
|
||||||
virtual ~PhaseLock()
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change phase locked loop parameters
|
|
||||||
*
|
|
||||||
* freq :: 19 kHz center frequency relative to sample freq
|
|
||||||
* (0.5 is Nyquist)
|
|
||||||
* bandwidth :: bandwidth relative to sample frequency
|
|
||||||
* minsignal :: minimum pilot amplitude
|
|
||||||
*/
|
|
||||||
void configure(Real freq, Real bandwidth, Real minsignal);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process samples and extract 19 kHz pilot tone.
|
|
||||||
* Generate phase-locked 38 kHz tone with unit amplitude.
|
|
||||||
* Bufferized version with input and output vectors
|
|
||||||
*/
|
|
||||||
void process(const std::vector<Real>& samples_in, std::vector<Real>& samples_out);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process samples and track a pilot tone. Generate samples for single or multiple phase-locked
|
|
||||||
* signals. Implement the processPhase virtual method to produce the output samples.
|
|
||||||
* In flow version. Ex: Use 19 kHz stereo pilot tone to generate 38 kHz (stereo) and 57 kHz
|
|
||||||
* pilots (see RDSPhaseLock class below).
|
|
||||||
* This is the in flow version
|
|
||||||
*/
|
|
||||||
void process(const Real& sample_in, Real *samples_out);
|
|
||||||
|
|
||||||
/** Return true if the phase-locked loop is locked. */
|
|
||||||
bool locked() const
|
|
||||||
{
|
|
||||||
return m_lock_cnt >= m_lock_delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return detected amplitude of pilot signal. */
|
|
||||||
Real get_pilot_level() const
|
|
||||||
{
|
|
||||||
return 2 * m_pilot_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Real m_phase;
|
|
||||||
Real m_psin;
|
|
||||||
Real m_pcos;
|
|
||||||
/**
|
|
||||||
* Callback method to produce multiple outputs from the current phase value in m_phase
|
|
||||||
* and/or the sin and cos values in m_psin and m_pcos
|
|
||||||
*/
|
|
||||||
virtual void processPhase(Real *samples_out) const {};
|
|
||||||
|
|
||||||
private:
|
|
||||||
Real m_minfreq, m_maxfreq;
|
|
||||||
Real m_phasor_b0, m_phasor_a1, m_phasor_a2;
|
|
||||||
Real m_phasor_i1, m_phasor_i2, m_phasor_q1, m_phasor_q2;
|
|
||||||
Real m_loopfilter_b0, m_loopfilter_b1;
|
|
||||||
Real m_loopfilter_x1;
|
|
||||||
Real m_freq;
|
|
||||||
Real m_minsignal;
|
|
||||||
Real m_pilot_level;
|
|
||||||
int m_lock_delay;
|
|
||||||
int m_lock_cnt;
|
|
||||||
int m_pilot_periods;
|
|
||||||
quint64 m_pps_cnt;
|
|
||||||
quint64 m_sample_cnt;
|
|
||||||
std::vector<PpsEvent> m_pps_events;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StereoPhaseLock : public PhaseLock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StereoPhaseLock(Real freq, Real bandwidth, Real minsignal) :
|
|
||||||
PhaseLock(freq, bandwidth, minsignal)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual ~StereoPhaseLock()
|
|
||||||
{}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void processPhase(Real *samples_out) const
|
|
||||||
{
|
|
||||||
samples_out[0] = m_psin; // f Pilot
|
|
||||||
// Generate double-frequency output.
|
|
||||||
// sin(2*x) = 2 * sin(x) * cos(x)
|
|
||||||
samples_out[1] = 2.0 * m_psin * m_pcos; // 2f Pilot sin
|
|
||||||
// cos(2*x) = 2 * cos(x) * cos(x) - 1
|
|
||||||
samples_out[2] = (2.0 * m_pcos * m_pcos) - 1.0; // 2f Pilot cos
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class RDSPhaseLock : public PhaseLock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RDSPhaseLock(Real freq, Real bandwidth, Real minsignal) :
|
|
||||||
PhaseLock(freq, bandwidth, minsignal)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual ~RDSPhaseLock()
|
|
||||||
{}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void processPhase(Real *samples_out) const
|
|
||||||
{
|
|
||||||
samples_out[0] = m_psin; // Pilot signal (f)
|
|
||||||
// Generate double-frequency output.
|
|
||||||
// sin(2*x) = 2 * sin(x) * cos(x)
|
|
||||||
samples_out[1] = 2.0 * m_psin * m_pcos; // Pilot signal (2f)
|
|
||||||
// cos(2*x) = 2 * cos(x) * cos(x) - 1
|
|
||||||
samples_out[2] = (2.0 * m_pcos * m_pcos) - 1.0; // 2f Pilot cos
|
|
||||||
samples_out[3] = m_phase; // Pilot phase
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,28 +0,0 @@
|
|||||||
#ifndef INCLUDE_PIDCONTROLLER_H
|
|
||||||
#define INCLUDE_PIDCONTROLLER_H
|
|
||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
class PIDController {
|
|
||||||
private:
|
|
||||||
Real m_p;
|
|
||||||
Real m_i;
|
|
||||||
Real m_d;
|
|
||||||
Real m_int;
|
|
||||||
Real m_diff;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PIDController();
|
|
||||||
|
|
||||||
void setup(Real p, Real i, Real d);
|
|
||||||
|
|
||||||
Real feed(Real v)
|
|
||||||
{
|
|
||||||
m_int += v * m_i;
|
|
||||||
Real d = m_d * (m_diff - v);
|
|
||||||
m_diff = v;
|
|
||||||
return (v * m_p) + m_int + d;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_PIDCONTROLLER_H
|
|
@ -1,67 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API 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();
|
|
||||||
|
|
||||||
bool setSize(int size);
|
|
||||||
inline uint size() const { return m_size; }
|
|
||||||
inline uint fill() { QMutexLocker mutexLocker(&m_mutex); uint fill = m_fill; return 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
|
|
@ -1,33 +0,0 @@
|
|||||||
#ifndef INCLUDE_SAMPLESINK_H
|
|
||||||
#define INCLUDE_SAMPLESINK_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include "dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
#include "util/messagequeue.h"
|
|
||||||
|
|
||||||
class Message;
|
|
||||||
|
|
||||||
class SDRANGEL_API SampleSink : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
SampleSink();
|
|
||||||
virtual ~SampleSink();
|
|
||||||
|
|
||||||
virtual void start() = 0;
|
|
||||||
virtual void stop() = 0;
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) = 0;
|
|
||||||
virtual bool handleMessage(const Message& cmd) = 0; //!< Processing of a message. Returns true if message has actually been processed
|
|
||||||
|
|
||||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
|
||||||
MessageQueue *getOutputMessageQueue() { return &m_outputMessageQueue; } //!< Get the queue for asynchronous outbound communication
|
|
||||||
|
|
||||||
protected:
|
|
||||||
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
|
|
||||||
MessageQueue m_outputMessageQueue; //!< Queue for asynchronous outbound communication
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void handleInputMessages();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_SAMPLESINK_H
|
|
@ -1,56 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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"
|
|
||||||
#include "util/messagequeue.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API SampleSource : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
SampleSource();
|
|
||||||
virtual ~SampleSource();
|
|
||||||
|
|
||||||
virtual bool init(const Message& cmd) = 0;
|
|
||||||
virtual bool start(int device) = 0;
|
|
||||||
virtual void stop() = 0;
|
|
||||||
|
|
||||||
virtual const QString& getDeviceDescription() const = 0;
|
|
||||||
virtual int getSampleRate() const = 0; //!< Sample rate exposed by the source
|
|
||||||
virtual quint64 getCenterFrequency() const = 0; //!< Center frequency exposed by the source
|
|
||||||
|
|
||||||
virtual bool handleMessage(const Message& message) = 0;
|
|
||||||
|
|
||||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
|
||||||
MessageQueue *getOutputMessageQueueToGUI() { return &m_outputMessageQueueToGUI; }
|
|
||||||
SampleFifo* getSampleFifo() { return &m_sampleFifo; }
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void handleInputMessages();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
SampleFifo m_sampleFifo;
|
|
||||||
MessageQueue m_inputMessageQueue; //!< Input queue to the source
|
|
||||||
MessageQueue m_outputMessageQueueToGUI; //!< Output queue specialized for the source GUI
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_SAMPLESOURCE_H
|
|
@ -1,169 +0,0 @@
|
|||||||
#ifndef INCLUDE_SCOPEVIS_H
|
|
||||||
#define INCLUDE_SCOPEVIS_H
|
|
||||||
|
|
||||||
#include <boost/circular_buffer.hpp>
|
|
||||||
#include "dsp/samplesink.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
#include "util/message.h"
|
|
||||||
|
|
||||||
class GLScope;
|
|
||||||
class MessageQueue;
|
|
||||||
|
|
||||||
class SDRANGEL_API ScopeVis : public SampleSink {
|
|
||||||
public:
|
|
||||||
enum TriggerChannel {
|
|
||||||
TriggerFreeRun,
|
|
||||||
TriggerChannelI,
|
|
||||||
TriggerChannelQ,
|
|
||||||
TriggerMagLin,
|
|
||||||
TriggerMagDb,
|
|
||||||
TriggerPhase,
|
|
||||||
TriggerDPhase
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint m_traceChunkSize;
|
|
||||||
static const uint m_nbTriggers = 10;
|
|
||||||
|
|
||||||
ScopeVis(GLScope* glScope = NULL);
|
|
||||||
virtual ~ScopeVis();
|
|
||||||
|
|
||||||
void configure(MessageQueue* msgQueue,
|
|
||||||
uint triggerIndex,
|
|
||||||
TriggerChannel triggerChannel,
|
|
||||||
Real triggerLevel,
|
|
||||||
bool triggerPositiveEdge,
|
|
||||||
bool triggerBothEdges,
|
|
||||||
uint triggerPre,
|
|
||||||
uint triggerDelay,
|
|
||||||
uint triggerCounts,
|
|
||||||
uint traceSize);
|
|
||||||
void setOneShot(bool oneShot);
|
|
||||||
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
|
|
||||||
void setSampleRate(int sampleRate);
|
|
||||||
int getSampleRate() const { return m_sampleRate; }
|
|
||||||
SampleVector::const_iterator getTriggerPoint() const { return m_triggerPoint; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
class MsgConfigureScopeVis : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
uint getTriggerIndex() const { return m_triggerIndex; }
|
|
||||||
int getTriggerChannel() const { return m_triggerChannel; }
|
|
||||||
Real getTriggerLevel() const { return m_triggerLevel; }
|
|
||||||
Real getTriggerPositiveEdge() const { return m_triggerPositiveEdge; }
|
|
||||||
Real getTriggerBothEdges() const { return m_triggerBothEdges; }
|
|
||||||
uint getTriggerPre() const { return m_triggerPre; }
|
|
||||||
uint getTriggerDelay() const { return m_triggerDelay; }
|
|
||||||
uint getTriggerCounts() const { return m_triggerCounts; }
|
|
||||||
uint getTraceSize() const { return m_traceSize; }
|
|
||||||
|
|
||||||
static MsgConfigureScopeVis* create(uint triggerIndex,
|
|
||||||
int triggerChannel,
|
|
||||||
Real triggerLevel,
|
|
||||||
bool triggerPositiveEdge,
|
|
||||||
bool triggerBothEdges,
|
|
||||||
uint triggerPre,
|
|
||||||
uint triggerDelay,
|
|
||||||
uint triggerCounts,
|
|
||||||
uint traceSize)
|
|
||||||
{
|
|
||||||
return new MsgConfigureScopeVis(triggerIndex,
|
|
||||||
triggerChannel,
|
|
||||||
triggerLevel,
|
|
||||||
triggerPositiveEdge,
|
|
||||||
triggerBothEdges,
|
|
||||||
triggerPre,
|
|
||||||
triggerDelay,
|
|
||||||
triggerCounts,
|
|
||||||
traceSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint m_triggerIndex;
|
|
||||||
int m_triggerChannel;
|
|
||||||
Real m_triggerLevel;
|
|
||||||
bool m_triggerPositiveEdge;
|
|
||||||
bool m_triggerBothEdges;
|
|
||||||
uint m_triggerPre;
|
|
||||||
uint m_triggerDelay;
|
|
||||||
uint m_triggerCounts;
|
|
||||||
uint m_traceSize;
|
|
||||||
|
|
||||||
MsgConfigureScopeVis(uint triggerIndex,
|
|
||||||
int triggerChannel,
|
|
||||||
Real triggerLevel,
|
|
||||||
bool triggerPositiveEdge,
|
|
||||||
bool triggerBothEdges,
|
|
||||||
uint triggerPre,
|
|
||||||
uint triggerDelay,
|
|
||||||
uint triggerCounts,
|
|
||||||
uint traceSize) :
|
|
||||||
Message(),
|
|
||||||
m_triggerIndex(triggerIndex),
|
|
||||||
m_triggerChannel(triggerChannel),
|
|
||||||
m_triggerLevel(triggerLevel),
|
|
||||||
m_triggerPositiveEdge(triggerPositiveEdge),
|
|
||||||
m_triggerBothEdges(triggerBothEdges),
|
|
||||||
m_triggerPre(triggerPre),
|
|
||||||
m_triggerDelay(triggerDelay),
|
|
||||||
m_triggerCounts(triggerCounts),
|
|
||||||
m_traceSize(traceSize)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TriggerState: (repeat at each successive non freerun trigger)
|
|
||||||
*
|
|
||||||
* send a Trigger condition +--------------------+
|
|
||||||
* dummy trace - Immediate m_triggerOneShot | |
|
|
||||||
* Config -------------> Untriggered ----------------------------------> Triggered ----------------> WaitForReset |
|
|
||||||
* ^ ^ | ^ | | ^ |
|
|
||||||
* | | | - Delayed Delay expired | | | | setOneShot(true)|
|
|
||||||
* | | +---------------------> Delay ----------------+ | | +-----------------+
|
|
||||||
* | | !m_triggerOneShot | |
|
|
||||||
* | +--------------------------------------------------+ setOneShot(false) |
|
|
||||||
* +-------------------------------------------------------------------------------+
|
|
||||||
*/
|
|
||||||
enum TriggerState {
|
|
||||||
Untriggered, //!< Search for trigger
|
|
||||||
Config, //!< New configuration has just been received
|
|
||||||
Triggered, //!< Trigger was kicked off
|
|
||||||
WaitForReset, //!< Wait for release from GUI
|
|
||||||
Delay //!< Trigger delay engaged
|
|
||||||
};
|
|
||||||
|
|
||||||
GLScope* m_glScope;
|
|
||||||
std::vector<Complex> m_trace; //!< Raw trace to be used by GLScope
|
|
||||||
boost::circular_buffer<Complex> m_traceback; //!< FIFO for samples prior to triggering point to support pre-trigger (when in triggered mode)
|
|
||||||
uint m_tracebackCount; //!< Count of samples stored into trace memory since triggering is active up to trace memory size
|
|
||||||
uint m_fill;
|
|
||||||
TriggerState m_triggerState;
|
|
||||||
uint m_triggerIndex; //!< current active trigger index
|
|
||||||
TriggerChannel m_triggerChannel[m_nbTriggers];
|
|
||||||
Real m_triggerLevel[m_nbTriggers];
|
|
||||||
bool m_triggerPositiveEdge[m_nbTriggers];
|
|
||||||
bool m_triggerBothEdges[m_nbTriggers];
|
|
||||||
bool m_prevTrigger;
|
|
||||||
uint m_triggerPre; //!< Pre-trigger delay in number of samples
|
|
||||||
bool m_triggerOneShot;
|
|
||||||
bool m_armed;
|
|
||||||
uint m_triggerDelay[m_nbTriggers]; //!< Trigger delay in number of trace sizes
|
|
||||||
uint m_triggerDelayCount; //!< trace sizes delay counter
|
|
||||||
uint m_triggerCounts[m_nbTriggers]; //!< Number of trigger events before the actual trigger is kicked off
|
|
||||||
uint m_triggerCount;
|
|
||||||
int m_sampleRate;
|
|
||||||
SampleVector::const_iterator m_triggerPoint;
|
|
||||||
Real m_prevArg;
|
|
||||||
bool m_firstArg;
|
|
||||||
|
|
||||||
bool triggerCondition(SampleVector::const_iterator& it);
|
|
||||||
bool nextTrigger(); //!< move to next trigger. Returns true if next trigger is active.
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_SCOPEVIS_H
|
|
@ -1,27 +0,0 @@
|
|||||||
#ifndef INCLUDE_SPECTRUMSCOPECOMBOVIS_H
|
|
||||||
#define INCLUDE_SPECTRUMSCOPECOMBOVIS_H
|
|
||||||
|
|
||||||
#include "dsp/samplesink.h"
|
|
||||||
#include "dsp/spectrumvis.h"
|
|
||||||
#include "dsp/scopevis.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class Message;
|
|
||||||
|
|
||||||
class SDRANGEL_API SpectrumScopeComboVis : public SampleSink {
|
|
||||||
public:
|
|
||||||
|
|
||||||
SpectrumScopeComboVis(SpectrumVis* spectrumVis, ScopeVis* scopeVis);
|
|
||||||
virtual ~SpectrumScopeComboVis();
|
|
||||||
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
SpectrumVis* m_spectrumVis;
|
|
||||||
ScopeVis* m_scopeVis;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_SPECTRUMSCOPECOMBOVIS_H
|
|
@ -1,70 +0,0 @@
|
|||||||
#ifndef INCLUDE_SPECTRUMVIS_H
|
|
||||||
#define INCLUDE_SPECTRUMVIS_H
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include "dsp/samplesink.h"
|
|
||||||
#include "dsp/fftengine.h"
|
|
||||||
#include "fftwindow.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
#include "util/message.h"
|
|
||||||
|
|
||||||
class GLSpectrum;
|
|
||||||
class MessageQueue;
|
|
||||||
|
|
||||||
class SDRANGEL_API SpectrumVis : public SampleSink {
|
|
||||||
|
|
||||||
public:
|
|
||||||
class SDRANGEL_API MsgConfigureSpectrumVis : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
MsgConfigureSpectrumVis(int fftSize, int overlapPercent, FFTWindow::Function window) :
|
|
||||||
Message(),
|
|
||||||
m_fftSize(fftSize),
|
|
||||||
m_overlapPercent(overlapPercent),
|
|
||||||
m_window(window)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int getFFTSize() const { return m_fftSize; }
|
|
||||||
int getOverlapPercent() const { return m_overlapPercent; }
|
|
||||||
FFTWindow::Function getWindow() const { return m_window; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_fftSize;
|
|
||||||
int m_overlapPercent;
|
|
||||||
FFTWindow::Function m_window;
|
|
||||||
};
|
|
||||||
|
|
||||||
SpectrumVis(GLSpectrum* glSpectrum = NULL);
|
|
||||||
virtual ~SpectrumVis();
|
|
||||||
|
|
||||||
void configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, FFTWindow::Function window);
|
|
||||||
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
|
||||||
void feedTriggered(const SampleVector::const_iterator& triggerPoint, const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
|
||||||
virtual void start();
|
|
||||||
virtual void stop();
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FFTEngine* m_fft;
|
|
||||||
FFTWindow m_window;
|
|
||||||
|
|
||||||
std::vector<Complex> m_fftBuffer;
|
|
||||||
std::vector<Real> m_logPowerSpectrum;
|
|
||||||
|
|
||||||
std::size_t m_fftSize;
|
|
||||||
std::size_t m_overlapPercent;
|
|
||||||
std::size_t m_overlapSize;
|
|
||||||
std::size_t m_refillSize;
|
|
||||||
std::size_t m_fftBufferFill;
|
|
||||||
bool m_needMoreSamples;
|
|
||||||
|
|
||||||
GLSpectrum* m_glSpectrum;
|
|
||||||
|
|
||||||
QMutex m_mutex;
|
|
||||||
|
|
||||||
void handleConfigure(int fftSize, int overlapPercent, FFTWindow::Function window);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_SPECTRUMVIS_H
|
|
@ -1,78 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_THREADEDSAMPLESINK_H
|
|
||||||
#define INCLUDE_THREADEDSAMPLESINK_H
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include "samplesink.h"
|
|
||||||
#include "dsp/samplefifo.h"
|
|
||||||
#include "util/messagequeue.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SampleSink;
|
|
||||||
class QThread;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Because Qt is a piece of shit this class cannot be a nested protected class of ThreadedSampleSink
|
|
||||||
* So let's make everything public
|
|
||||||
*/
|
|
||||||
class ThreadedSampleFifo : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ThreadedSampleFifo(SampleSink* sampleSink, std::size_t size = 1<<18);
|
|
||||||
~ThreadedSampleFifo();
|
|
||||||
void writeToFifo(SampleVector::const_iterator& begin, SampleVector::const_iterator& end);
|
|
||||||
|
|
||||||
SampleSink* m_sampleSink;
|
|
||||||
SampleFifo m_sampleFifo;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void handleFifoData();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is a wrapper for SampleSink that runs the SampleSink object in its own thread
|
|
||||||
*/
|
|
||||||
class SDRANGEL_API ThreadedSampleSink : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ThreadedSampleSink(SampleSink* sampleSink, QObject *parent = 0);
|
|
||||||
~ThreadedSampleSink();
|
|
||||||
|
|
||||||
const SampleSink *getSink() const { return m_sampleSink; }
|
|
||||||
MessageQueue* getInputMessageQueue() { return m_sampleSink->getInputMessageQueue(); } //!< Return pointer to sample sink's input message queue
|
|
||||||
MessageQueue* getOutputMessageQueue() { return m_sampleSink->getOutputMessageQueue(); } //!< Return pointer to sample sink's output message queue
|
|
||||||
|
|
||||||
void start(); //!< this thread start()
|
|
||||||
void stop(); //!< this thread exit() and wait()
|
|
||||||
|
|
||||||
bool handleSinkMessage(const Message& cmd); //!< Send message to sink synchronously
|
|
||||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly); //!< Feed sink with samples
|
|
||||||
|
|
||||||
QString getSampleSinkObjectName() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
QThread *m_thread; //!< The thead object
|
|
||||||
ThreadedSampleFifo *m_threadedSampleFifo;
|
|
||||||
SampleSink* m_sampleSink;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_THREADEDSAMPLESINK_H
|
|
@ -1,21 +0,0 @@
|
|||||||
#ifndef INCLUDE_ABOUTDIALOG_H
|
|
||||||
#define INCLUDE_ABOUTDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class AboutDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AboutDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit AboutDialog(QWidget* parent = NULL);
|
|
||||||
~AboutDialog();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::AboutDialog* ui;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_ABOUTDIALOG_H
|
|
@ -1,32 +0,0 @@
|
|||||||
#ifndef INCLUDE_ADDPRESETDIALOG_H
|
|
||||||
#define INCLUDE_ADDPRESETDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class AddPresetDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AddPresetDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit AddPresetDialog(const QStringList& groups, const QString& group, QWidget* parent = NULL);
|
|
||||||
~AddPresetDialog();
|
|
||||||
|
|
||||||
QString group() const;
|
|
||||||
QString description() const;
|
|
||||||
void setGroup(QString& group);
|
|
||||||
void setDescription(QString& description);
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum Audio {
|
|
||||||
ATDefault,
|
|
||||||
ATInterface,
|
|
||||||
ATDevice
|
|
||||||
};
|
|
||||||
|
|
||||||
Ui::AddPresetDialog* ui;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_ADDPRESETDIALOG_H
|
|
@ -1,34 +0,0 @@
|
|||||||
#ifndef INCLUDE_BASICCHANNELSETTINGSWIDGET_H
|
|
||||||
#define INCLUDE_BASICCHANNELSETTINGSWIDGET_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class BasicChannelSettingsWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChannelMarker;
|
|
||||||
|
|
||||||
class SDRANGEL_API BasicChannelSettingsWidget : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit BasicChannelSettingsWidget(ChannelMarker* marker, QWidget* parent = NULL);
|
|
||||||
~BasicChannelSettingsWidget();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_title_textChanged(const QString& text);
|
|
||||||
void on_colorBtn_clicked();
|
|
||||||
void on_red_valueChanged(int value);
|
|
||||||
void on_green_valueChanged(int value);
|
|
||||||
void on_blue_valueChanged(int value);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::BasicChannelSettingsWidget* ui;
|
|
||||||
ChannelMarker* m_channelMarker;
|
|
||||||
|
|
||||||
void paintColor();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_BASICCHANNELSETTINGSWIDGET_H
|
|
@ -1,19 +0,0 @@
|
|||||||
#ifndef INCLUDE_BUTTONSWITCH_H
|
|
||||||
#define INCLUDE_BUTTONSWITCH_H
|
|
||||||
|
|
||||||
#include <QToolButton>
|
|
||||||
|
|
||||||
class ButtonSwitch : public QToolButton {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ButtonSwitch(QWidget* parent = NULL);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onToggled(bool checked);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QPalette m_originalPalette;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_BUTTONSWITCH_H
|
|
@ -1,25 +0,0 @@
|
|||||||
#ifndef INCLUDE_CHANNELWINDOW_H
|
|
||||||
#define INCLUDE_CHANNELWINDOW_H
|
|
||||||
|
|
||||||
#include <QScrollArea>
|
|
||||||
|
|
||||||
class QBoxLayout;
|
|
||||||
class QSpacerItem;
|
|
||||||
class RollupWidget;
|
|
||||||
|
|
||||||
class ChannelWindow : public QScrollArea {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ChannelWindow(QWidget* parent = NULL);
|
|
||||||
|
|
||||||
void addRollupWidget(QWidget* rollupWidget);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QWidget* m_container;
|
|
||||||
QBoxLayout* m_layout;
|
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* event);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_CHANNELWINDOW_H
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* colormap.h
|
|
||||||
*
|
|
||||||
* Created on: Jul 19, 2015
|
|
||||||
* Author: f4exb
|
|
||||||
*/
|
|
||||||
#ifndef INCLUDE_GPL_GUI_COLORMAPPER_H_
|
|
||||||
#define INCLUDE_GPL_GUI_COLORMAPPER_H_
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
#include <vector>
|
|
||||||
#include <utility>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API ColorMapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Theme {
|
|
||||||
Normal,
|
|
||||||
Gold,
|
|
||||||
ReverseGold,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<std::pair<float, QColor> > colormap;
|
|
||||||
|
|
||||||
ColorMapper(Theme theme = Normal);
|
|
||||||
~ColorMapper();
|
|
||||||
|
|
||||||
const colormap& getDialBackgroundColorMap() const { return m_dialBackgroundcolorMap; };
|
|
||||||
const QColor& getForegroundColor() const { return m_foregroundColor; };
|
|
||||||
const QColor& getSecondaryForegroundColor() const { return m_secondaryForegroundColor; };
|
|
||||||
const QColor& getHighlightColor() const { return m_highlightColor; };
|
|
||||||
const QColor& getBoundaryColor() const { return m_boundaryColor; };
|
|
||||||
const QColor& getBoundaryAlphaColor() const { return m_boundaryAlphaColor; };
|
|
||||||
|
|
||||||
private:
|
|
||||||
Theme m_theme;
|
|
||||||
std::vector<std::pair<float, QColor> > m_dialBackgroundcolorMap;
|
|
||||||
QColor m_foregroundColor;
|
|
||||||
QColor m_secondaryForegroundColor;
|
|
||||||
QColor m_highlightColor;
|
|
||||||
QColor m_boundaryColor;
|
|
||||||
QColor m_boundaryAlphaColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INCLUDE_GPL_GUI_COLORMAPPER_H_ */
|
|
@ -1,190 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2016 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// OpenGL interface modernization. //
|
|
||||||
// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html //
|
|
||||||
// //
|
|
||||||
// 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_GLSCOPE_H
|
|
||||||
#define INCLUDE_GLSCOPE_H
|
|
||||||
|
|
||||||
#include <QGLWidget>
|
|
||||||
#include <QPen>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QFont>
|
|
||||||
#include <QMatrix4x4>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "dsp/scopevis.h"
|
|
||||||
#include "gui/scaleengine.h"
|
|
||||||
#include "gui/glshadersimple.h"
|
|
||||||
#include "gui/glshadertextured.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
#include "util/bitfieldindex.h"
|
|
||||||
|
|
||||||
class DSPEngine;
|
|
||||||
class ScopeVis;
|
|
||||||
class QPainter;
|
|
||||||
|
|
||||||
class SDRANGEL_API GLScope: public QGLWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum Mode {
|
|
||||||
ModeIQ,
|
|
||||||
ModeMagLinPha,
|
|
||||||
ModeMagdBPha,
|
|
||||||
ModeMagLinDPha,
|
|
||||||
ModeMagdBDPha,
|
|
||||||
ModeDerived12,
|
|
||||||
ModeCyclostationary,
|
|
||||||
ModeIQPolar
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Displays {
|
|
||||||
DisplayBoth,
|
|
||||||
DisplayFirstOnly,
|
|
||||||
DisplaySecondOnly
|
|
||||||
};
|
|
||||||
|
|
||||||
GLScope(QWidget* parent = NULL);
|
|
||||||
~GLScope();
|
|
||||||
|
|
||||||
void setDSPEngine(DSPEngine* dspEngine);
|
|
||||||
void setAmp1(Real amp);
|
|
||||||
void setAmp1Ofs(Real ampOfs);
|
|
||||||
void setAmp2(Real amp);
|
|
||||||
void setAmp2Ofs(Real ampOfs);
|
|
||||||
void setTimeBase(int timeBase);
|
|
||||||
void setTimeOfsProMill(int timeOfsProMill);
|
|
||||||
void setMode(Mode mode);
|
|
||||||
void setDisplays(Displays displays);
|
|
||||||
void setOrientation(Qt::Orientation orientation);
|
|
||||||
void setDisplayGridIntensity(int intensity);
|
|
||||||
void setDisplayTraceIntensity(int intensity);
|
|
||||||
void setTriggerChannel(ScopeVis::TriggerChannel triggerChannel);
|
|
||||||
void setTriggerLevel(Real triggerLevel);
|
|
||||||
void setTriggerPre(Real triggerPre);
|
|
||||||
void setMemHistoryShift(int value);
|
|
||||||
|
|
||||||
void newTrace(const std::vector<Complex>& trace, int sampleRate);
|
|
||||||
int getTraceSize() const { return m_rawTrace[m_memTraceIndex - m_memTraceHistory].size(); }
|
|
||||||
|
|
||||||
void setSampleRate(int sampleRate);
|
|
||||||
int getSampleRate() const { return m_sampleRates[m_memTraceIndex - m_memTraceHistory]; }
|
|
||||||
Mode getDataMode() const { return m_mode; }
|
|
||||||
void connectTimer(const QTimer& timer);
|
|
||||||
|
|
||||||
static const int m_memHistorySizeLog2 = 5;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void traceSizeChanged(int);
|
|
||||||
void sampleRateChanged(int);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// state
|
|
||||||
QTimer m_timer;
|
|
||||||
QMutex m_mutex;
|
|
||||||
bool m_dataChanged;
|
|
||||||
bool m_configChanged;
|
|
||||||
Mode m_mode;
|
|
||||||
Displays m_displays;
|
|
||||||
Qt::Orientation m_orientation;
|
|
||||||
|
|
||||||
// traces
|
|
||||||
std::vector<Complex> m_rawTrace[1<<m_memHistorySizeLog2];
|
|
||||||
int m_sampleRates[1<<m_memHistorySizeLog2];
|
|
||||||
BitfieldIndex<m_memHistorySizeLog2> m_memTraceIndex; //!< current index of trace being written
|
|
||||||
BitfieldIndex<m_memHistorySizeLog2> m_memTraceHistory; //!< trace index shift into history
|
|
||||||
int m_memTraceIndexMax;
|
|
||||||
bool m_memTraceRecall;
|
|
||||||
std::vector<Complex> m_mathTrace;
|
|
||||||
std::vector<Complex>* m_displayTrace;
|
|
||||||
std::vector<Real> m_powTrace;
|
|
||||||
Real m_maxPow;
|
|
||||||
Real m_sumPow;
|
|
||||||
int m_oldTraceSize;
|
|
||||||
int m_sampleRate;
|
|
||||||
Real m_amp1;
|
|
||||||
Real m_amp2;
|
|
||||||
Real m_ofs1;
|
|
||||||
Real m_ofs2;
|
|
||||||
|
|
||||||
// sample sink
|
|
||||||
DSPEngine* m_dspEngine;
|
|
||||||
ScopeVis* m_scopeVis;
|
|
||||||
|
|
||||||
// config
|
|
||||||
int m_timeBase;
|
|
||||||
int m_timeOfsProMill;
|
|
||||||
ScopeVis::TriggerChannel m_triggerChannel;
|
|
||||||
Real m_triggerLevel;
|
|
||||||
Real m_triggerPre;
|
|
||||||
Real m_triggerLevelDis1;
|
|
||||||
Real m_triggerLevelDis2;
|
|
||||||
int m_nbPow;
|
|
||||||
Real m_prevArg;
|
|
||||||
|
|
||||||
// graphics stuff
|
|
||||||
QRectF m_glScopeRect1;
|
|
||||||
QRectF m_glScopeRect2;
|
|
||||||
QMatrix4x4 m_glScopeMatrix1;
|
|
||||||
QMatrix4x4 m_glScopeMatrix2;
|
|
||||||
QMatrix4x4 m_glLeft1ScaleMatrix;
|
|
||||||
QMatrix4x4 m_glRight1ScaleMatrix;
|
|
||||||
QMatrix4x4 m_glLeft2ScaleMatrix;
|
|
||||||
QMatrix4x4 m_glBot1ScaleMatrix;
|
|
||||||
QMatrix4x4 m_glBot2ScaleMatrix;
|
|
||||||
|
|
||||||
QPixmap m_left1ScalePixmap;
|
|
||||||
QPixmap m_left2ScalePixmap;
|
|
||||||
QPixmap m_bot1ScalePixmap;
|
|
||||||
QPixmap m_bot2ScalePixmap;
|
|
||||||
QPixmap m_powerOverlayPixmap1;
|
|
||||||
|
|
||||||
int m_displayGridIntensity;
|
|
||||||
int m_displayTraceIntensity;
|
|
||||||
|
|
||||||
ScaleEngine m_x1Scale;
|
|
||||||
ScaleEngine m_x2Scale;
|
|
||||||
ScaleEngine m_y1Scale;
|
|
||||||
ScaleEngine m_y2Scale;
|
|
||||||
|
|
||||||
QFont m_powerOverlayFont;
|
|
||||||
|
|
||||||
GLShaderSimple m_glShaderSimple;
|
|
||||||
GLShaderTextured m_glShaderLeft1Scale;
|
|
||||||
GLShaderTextured m_glShaderBottom1Scale;
|
|
||||||
GLShaderTextured m_glShaderLeft2Scale;
|
|
||||||
GLShaderTextured m_glShaderBottom2Scale;
|
|
||||||
GLShaderTextured m_glShaderPowerOverlay;
|
|
||||||
|
|
||||||
void initializeGL();
|
|
||||||
void resizeGL(int width, int height);
|
|
||||||
void paintGL();
|
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent*);
|
|
||||||
|
|
||||||
void handleMode();
|
|
||||||
void applyConfig();
|
|
||||||
void drawPowerOverlay();
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void cleanup();
|
|
||||||
void tick();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_GLSCOPE_H
|
|
@ -1,117 +0,0 @@
|
|||||||
#ifndef INCLUDE_GLSCOPEGUI_H
|
|
||||||
#define INCLUDE_GLSCOPEGUI_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
#include "util/message.h"
|
|
||||||
#include "dsp/scopevis.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class GLScopeGUI;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessageQueue;
|
|
||||||
class GLScope;
|
|
||||||
|
|
||||||
class SDRANGEL_API GLScopeGUI : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GLScopeGUI(QWidget* parent = NULL);
|
|
||||||
~GLScopeGUI();
|
|
||||||
|
|
||||||
void setBuddies(MessageQueue* messageQueue, ScopeVis* scopeVis, GLScope* glScope);
|
|
||||||
|
|
||||||
void setSampleRate(int sampleRate);
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
|
|
||||||
bool handleMessage(Message* message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::GLScopeGUI* ui;
|
|
||||||
|
|
||||||
MessageQueue* m_messageQueue;
|
|
||||||
ScopeVis* m_scopeVis;
|
|
||||||
GLScope* m_glScope;
|
|
||||||
|
|
||||||
int m_sampleRate;
|
|
||||||
|
|
||||||
qint32 m_displayData;
|
|
||||||
qint32 m_displayOrientation;
|
|
||||||
qint32 m_displays;
|
|
||||||
qint32 m_timeBase;
|
|
||||||
qint32 m_timeOffset;
|
|
||||||
qint32 m_amplification1;
|
|
||||||
qint32 m_amp1OffsetCoarse;
|
|
||||||
qint32 m_amp1OffsetFine;
|
|
||||||
qint32 m_amplification2;
|
|
||||||
qint32 m_amp2OffsetCoarse;
|
|
||||||
qint32 m_amp2OffsetFine;
|
|
||||||
int m_displayGridIntensity;
|
|
||||||
int m_displayTraceIntensity;
|
|
||||||
quint32 m_triggerIndex;
|
|
||||||
qint32 m_triggerChannel[ScopeVis::m_nbTriggers];
|
|
||||||
qint32 m_triggerLevelCoarse[ScopeVis::m_nbTriggers]; // percent of full range
|
|
||||||
qint32 m_triggerLevelFine[ScopeVis::m_nbTriggers]; // percent of coarse
|
|
||||||
bool m_triggerPositiveEdge[ScopeVis::m_nbTriggers];
|
|
||||||
bool m_triggerBothEdges[ScopeVis::m_nbTriggers];
|
|
||||||
qint32 m_triggerPre;
|
|
||||||
qint32 m_triggerDelay[ScopeVis::m_nbTriggers];
|
|
||||||
qint32 m_triggerCounts[ScopeVis::m_nbTriggers];
|
|
||||||
qint32 m_traceLenMult;
|
|
||||||
|
|
||||||
static const qreal amps[11];
|
|
||||||
|
|
||||||
void applySettings();
|
|
||||||
void applyTriggerSettings();
|
|
||||||
void setTimeScaleDisplay();
|
|
||||||
void setTraceLenDisplay();
|
|
||||||
void setTimeOfsDisplay();
|
|
||||||
void setAmp1ScaleDisplay();
|
|
||||||
void setAmp1OfsDisplay();
|
|
||||||
void setAmp2ScaleDisplay();
|
|
||||||
void setAmp2OfsDisplay();
|
|
||||||
void setTrigLevelDisplay();
|
|
||||||
void setTrigPreDisplay();
|
|
||||||
void setTrigDelayDisplay();
|
|
||||||
void setTrigUI(uint index);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_amp1_valueChanged(int value);
|
|
||||||
void on_amp1OfsCoarse_valueChanged(int value);
|
|
||||||
void on_amp1OfsFine_valueChanged(int value);
|
|
||||||
void on_amp2_valueChanged(int value);
|
|
||||||
void on_amp2OfsCoarse_valueChanged(int value);
|
|
||||||
void on_amp2OfsFine_valueChanged(int value);
|
|
||||||
void on_scope_traceSizeChanged(int value);
|
|
||||||
void on_scope_sampleRateChanged(int value);
|
|
||||||
void on_time_valueChanged(int value);
|
|
||||||
void on_traceLen_valueChanged(int value);
|
|
||||||
void on_timeOfs_valueChanged(int value);
|
|
||||||
void on_dataMode_currentIndexChanged(int index);
|
|
||||||
void on_gridIntensity_valueChanged(int index);
|
|
||||||
void on_traceIntensity_valueChanged(int index);
|
|
||||||
void on_trigPre_valueChanged(int value);
|
|
||||||
void on_trigDelay_valueChanged(int value);
|
|
||||||
void on_memIndex_valueChanged(int value);
|
|
||||||
void on_trigCount_valueChanged(int value);
|
|
||||||
void on_trigIndex_valueChanged(int value);
|
|
||||||
|
|
||||||
void on_horizView_clicked();
|
|
||||||
void on_vertView_clicked();
|
|
||||||
void on_onlyPrimeView_clicked();
|
|
||||||
void on_onlySecondView_clicked();
|
|
||||||
|
|
||||||
void on_trigMode_currentIndexChanged(int index);
|
|
||||||
void on_slopePos_clicked();
|
|
||||||
void on_slopeNeg_clicked();
|
|
||||||
void on_slopeBoth_clicked();
|
|
||||||
void on_oneShot_clicked();
|
|
||||||
void on_trigLevelCoarse_valueChanged(int value);
|
|
||||||
void on_trigLevelFine_valueChanged(int value);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_GLSCOPEGUI_H
|
|
@ -1,51 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2016 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_GUI_GLSHADERSIMPLE_H_
|
|
||||||
#define INCLUDE_GUI_GLSHADERSIMPLE_H_
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QOpenGLFunctions>
|
|
||||||
|
|
||||||
class QOpenGLShaderProgram;
|
|
||||||
class QMatrix4x4;
|
|
||||||
class QVector4D;
|
|
||||||
|
|
||||||
class GLShaderSimple
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GLShaderSimple();
|
|
||||||
~GLShaderSimple();
|
|
||||||
|
|
||||||
void initializeGL();
|
|
||||||
void drawPolyline(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices);
|
|
||||||
void drawSegments(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices);
|
|
||||||
void drawContour(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices);
|
|
||||||
void drawSurface(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices);
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void draw(unsigned int mode, const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices);
|
|
||||||
|
|
||||||
QOpenGLShaderProgram *m_program;
|
|
||||||
int m_matrixLoc;
|
|
||||||
int m_colorLoc;
|
|
||||||
static const QString m_vertexShaderSourceSimple;
|
|
||||||
static const QString m_fragmentShaderSourceColored;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INCLUDE_GUI_GLSHADERSIMPLE_H_ */
|
|
@ -1,55 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2016 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// See: http://glslstudio.com/primer/#gl2frag //
|
|
||||||
// https://gitlab.com/pteam/korvins-qtbase/blob/5.4/examples/opengl/cube/mainwidget.cpp //
|
|
||||||
// //
|
|
||||||
// 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_GUI_GLSHADERTEXTURED_H_
|
|
||||||
#define INCLUDE_GUI_GLSHADERTEXTURED_H_
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QOpenGLTexture>
|
|
||||||
#include <QOpenGLFunctions>
|
|
||||||
|
|
||||||
class QOpenGLShaderProgram;
|
|
||||||
class QMatrix4x4;
|
|
||||||
class QImage;
|
|
||||||
|
|
||||||
class GLShaderTextured
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GLShaderTextured();
|
|
||||||
~GLShaderTextured();
|
|
||||||
|
|
||||||
void initializeGL();
|
|
||||||
void initTexture(const QImage& image, QOpenGLTexture::WrapMode wrapMode = QOpenGLTexture::Repeat);
|
|
||||||
void subTexture(int xOffset, int yOffset, int width, int height, const void *pixels);
|
|
||||||
void drawSurface(const QMatrix4x4& transformMatrix, GLfloat* textureCoords, GLfloat *vertices, int nbVertices);
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void draw(unsigned int mode, const QMatrix4x4& transformMatrix, GLfloat *textureCoords, GLfloat *vertices, int nbVertices);
|
|
||||||
|
|
||||||
QOpenGLShaderProgram *m_program;
|
|
||||||
QOpenGLTexture *m_texture;
|
|
||||||
int m_matrixLoc;
|
|
||||||
int m_textureLoc;
|
|
||||||
static const QString m_vertexShaderSourceTextured;
|
|
||||||
static const QString m_fragmentShaderSourceTextured;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INCLUDE_GUI_GLSHADERTEXTURED_H_ */
|
|
@ -1,193 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2016 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// OpenGL interface modernization. //
|
|
||||||
// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html //
|
|
||||||
// //
|
|
||||||
// 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_GLSPECTRUM_H
|
|
||||||
#define INCLUDE_GLSPECTRUM_H
|
|
||||||
|
|
||||||
#include <QOpenGLWidget>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QOpenGLBuffer>
|
|
||||||
#include <QOpenGLVertexArrayObject>
|
|
||||||
#include <QMatrix4x4>
|
|
||||||
#include <QGLWidget>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "gui/scaleengine.h"
|
|
||||||
#include "gui/glshadersimple.h"
|
|
||||||
#include "gui/glshadertextured.h"
|
|
||||||
#include "dsp/channelmarker.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class QOpenGLShaderProgram;
|
|
||||||
|
|
||||||
class SDRANGEL_API GLSpectrum : public QGLWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
GLSpectrum(QWidget* parent = NULL);
|
|
||||||
~GLSpectrum();
|
|
||||||
|
|
||||||
void setCenterFrequency(quint64 frequency);
|
|
||||||
void setSampleRate(qint32 sampleRate);
|
|
||||||
void setReferenceLevel(Real referenceLevel);
|
|
||||||
void setPowerRange(Real powerRange);
|
|
||||||
void setDecay(int decay);
|
|
||||||
void setHistoLateHoldoff(int lateHoldoff);
|
|
||||||
void setHistoStroke(int stroke);
|
|
||||||
void setDisplayWaterfall(bool display);
|
|
||||||
void setSsbSpectrum(bool ssbSpectrum);
|
|
||||||
void setInvertedWaterfall(bool inv);
|
|
||||||
void setDisplayMaxHold(bool display);
|
|
||||||
void setDisplayCurrent(bool display);
|
|
||||||
void setDisplayHistogram(bool display);
|
|
||||||
void setDisplayGrid(bool display);
|
|
||||||
void setDisplayGridIntensity(int intensity);
|
|
||||||
void setDisplayTraceIntensity(int intensity);
|
|
||||||
|
|
||||||
void addChannelMarker(ChannelMarker* channelMarker);
|
|
||||||
void removeChannelMarker(ChannelMarker* channelMarker);
|
|
||||||
|
|
||||||
void newSpectrum(const std::vector<Real>& spectrum, int fftSize);
|
|
||||||
void clearSpectrumHistogram();
|
|
||||||
|
|
||||||
Real getWaterfallShare() const { return m_waterfallShare; }
|
|
||||||
void setWaterfallShare(Real waterfallShare);
|
|
||||||
void connectTimer(const QTimer& timer);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct ChannelMarkerState {
|
|
||||||
ChannelMarker* m_channelMarker;
|
|
||||||
QMatrix4x4 m_glMatrixWaterfall;
|
|
||||||
QMatrix4x4 m_glMatrixDsbWaterfall;
|
|
||||||
QMatrix4x4 m_glMatrixFreqScale;
|
|
||||||
QMatrix4x4 m_glMatrixDsbFreqScale;
|
|
||||||
QMatrix4x4 m_glMatrixHistogram;
|
|
||||||
QMatrix4x4 m_glMatrixDsbHistogram;
|
|
||||||
QRect m_rect;
|
|
||||||
|
|
||||||
ChannelMarkerState(ChannelMarker* channelMarker) :
|
|
||||||
m_channelMarker(channelMarker)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
QList<ChannelMarkerState*> m_channelMarkerStates;
|
|
||||||
|
|
||||||
enum CursorState {
|
|
||||||
CSNormal,
|
|
||||||
CSSplitter,
|
|
||||||
CSSplitterMoving,
|
|
||||||
CSChannel,
|
|
||||||
CSChannelMoving
|
|
||||||
};
|
|
||||||
|
|
||||||
CursorState m_cursorState;
|
|
||||||
int m_cursorChannel;
|
|
||||||
|
|
||||||
QTimer m_timer;
|
|
||||||
QMutex m_mutex;
|
|
||||||
bool m_mouseInside;
|
|
||||||
bool m_changesPending;
|
|
||||||
|
|
||||||
qint64 m_centerFrequency;
|
|
||||||
Real m_referenceLevel;
|
|
||||||
Real m_powerRange;
|
|
||||||
int m_decay;
|
|
||||||
quint32 m_sampleRate;
|
|
||||||
|
|
||||||
int m_fftSize;
|
|
||||||
|
|
||||||
bool m_displayGrid;
|
|
||||||
int m_displayGridIntensity;
|
|
||||||
int m_displayTraceIntensity;
|
|
||||||
bool m_invertedWaterfall;
|
|
||||||
|
|
||||||
std::vector<Real> m_maxHold;
|
|
||||||
bool m_displayMaxHold;
|
|
||||||
const std::vector<Real> *m_currentSpectrum;
|
|
||||||
bool m_displayCurrent;
|
|
||||||
|
|
||||||
Real m_waterfallShare;
|
|
||||||
|
|
||||||
QPixmap m_leftMarginPixmap;
|
|
||||||
QPixmap m_frequencyPixmap;
|
|
||||||
ScaleEngine m_timeScale;
|
|
||||||
ScaleEngine m_powerScale;
|
|
||||||
ScaleEngine m_frequencyScale;
|
|
||||||
QRect m_frequencyScaleRect;
|
|
||||||
QMatrix4x4 m_glFrequencyScaleBoxMatrix;
|
|
||||||
QMatrix4x4 m_glLeftScaleBoxMatrix;
|
|
||||||
|
|
||||||
QRgb m_waterfallPalette[240];
|
|
||||||
QImage* m_waterfallBuffer;
|
|
||||||
int m_waterfallBufferPos;
|
|
||||||
int m_waterfallTextureHeight;
|
|
||||||
int m_waterfallTexturePos;
|
|
||||||
QMatrix4x4 m_glWaterfallBoxMatrix;
|
|
||||||
bool m_displayWaterfall;
|
|
||||||
bool m_ssbSpectrum;
|
|
||||||
|
|
||||||
QRgb m_histogramPalette[240];
|
|
||||||
QImage* m_histogramBuffer;
|
|
||||||
quint8* m_histogram;
|
|
||||||
quint8* m_histogramHoldoff;
|
|
||||||
int m_histogramHoldoffBase;
|
|
||||||
int m_histogramHoldoffCount;
|
|
||||||
int m_histogramLateHoldoff;
|
|
||||||
int m_histogramStroke;
|
|
||||||
QMatrix4x4 m_glHistogramSpectrumMatrix;
|
|
||||||
QMatrix4x4 m_glHistogramBoxMatrix;
|
|
||||||
bool m_displayHistogram;
|
|
||||||
|
|
||||||
bool m_displayChanged;
|
|
||||||
|
|
||||||
GLShaderSimple m_glShaderSimple;
|
|
||||||
GLShaderTextured m_glShaderLeftScale;
|
|
||||||
GLShaderTextured m_glShaderFrequencyScale;
|
|
||||||
GLShaderTextured m_glShaderWaterfall;
|
|
||||||
GLShaderTextured m_glShaderHistogram;
|
|
||||||
int m_matrixLoc;
|
|
||||||
int m_colorLoc;
|
|
||||||
|
|
||||||
static const int m_waterfallBufferHeight = 256;
|
|
||||||
|
|
||||||
void updateWaterfall(const std::vector<Real>& spectrum);
|
|
||||||
void updateHistogram(const std::vector<Real>& spectrum);
|
|
||||||
|
|
||||||
void initializeGL();
|
|
||||||
void resizeGL(int width, int height);
|
|
||||||
void paintGL();
|
|
||||||
|
|
||||||
void stopDrag();
|
|
||||||
void applyChanges();
|
|
||||||
|
|
||||||
void mouseMoveEvent(QMouseEvent* event);
|
|
||||||
void mousePressEvent(QMouseEvent* event);
|
|
||||||
void mouseReleaseEvent(QMouseEvent* event);
|
|
||||||
|
|
||||||
void enterEvent(QEvent* event);
|
|
||||||
void leaveEvent(QEvent* event);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void cleanup();
|
|
||||||
void tick();
|
|
||||||
void channelMarkerChanged();
|
|
||||||
void channelMarkerDestroyed(QObject* object);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_GLSPECTRUM_H
|
|
@ -1,76 +0,0 @@
|
|||||||
#ifndef INCLUDE_GLSPECTRUMGUI_H
|
|
||||||
#define INCLUDE_GLSPECTRUMGUI_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class GLSpectrumGUI;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessageQueue;
|
|
||||||
class SpectrumVis;
|
|
||||||
class GLSpectrum;
|
|
||||||
|
|
||||||
class SDRANGEL_API GLSpectrumGUI : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GLSpectrumGUI(QWidget* parent = NULL);
|
|
||||||
~GLSpectrumGUI();
|
|
||||||
|
|
||||||
void setBuddies(MessageQueue* messageQueue, SpectrumVis* spectrumVis, GLSpectrum* glSpectrum);
|
|
||||||
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::GLSpectrumGUI* ui;
|
|
||||||
|
|
||||||
MessageQueue* m_messageQueue;
|
|
||||||
SpectrumVis* m_spectrumVis;
|
|
||||||
GLSpectrum* m_glSpectrum;
|
|
||||||
|
|
||||||
qint32 m_fftSize;
|
|
||||||
qint32 m_fftOverlap;
|
|
||||||
qint32 m_fftWindow;
|
|
||||||
Real m_refLevel;
|
|
||||||
Real m_powerRange;
|
|
||||||
int m_decay;
|
|
||||||
int m_histogramLateHoldoff;
|
|
||||||
int m_histogramStroke;
|
|
||||||
int m_displayGridIntensity;
|
|
||||||
int m_displayTraceIntensity;
|
|
||||||
bool m_displayWaterfall;
|
|
||||||
bool m_invertedWaterfall;
|
|
||||||
bool m_displayMaxHold;
|
|
||||||
bool m_displayCurrent;
|
|
||||||
bool m_displayHistogram;
|
|
||||||
bool m_displayGrid;
|
|
||||||
bool m_invert;
|
|
||||||
|
|
||||||
void applySettings();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_fftWindow_currentIndexChanged(int index);
|
|
||||||
void on_fftSize_currentIndexChanged(int index);
|
|
||||||
void on_refLevel_currentIndexChanged(int index);
|
|
||||||
void on_levelRange_currentIndexChanged(int index);
|
|
||||||
void on_decay_valueChanged(int index);
|
|
||||||
void on_holdoff_valueChanged(int index);
|
|
||||||
void on_stroke_valueChanged(int index);
|
|
||||||
void on_gridIntensity_valueChanged(int index);
|
|
||||||
void on_traceIntensity_valueChanged(int index);
|
|
||||||
|
|
||||||
void on_waterfall_toggled(bool checked);
|
|
||||||
void on_histogram_toggled(bool checked);
|
|
||||||
void on_maxHold_toggled(bool checked);
|
|
||||||
void on_current_toggled(bool checked);
|
|
||||||
void on_invert_toggled(bool checked);
|
|
||||||
void on_grid_toggled(bool checked);
|
|
||||||
void on_clearSpectrum_clicked(bool checked);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_GLSPECTRUMGUI_H
|
|
@ -1,41 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_INDICATOR_H
|
|
||||||
#define INCLUDE_INDICATOR_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API Indicator : public QWidget {
|
|
||||||
private:
|
|
||||||
Q_OBJECT;
|
|
||||||
|
|
||||||
QColor m_color;
|
|
||||||
QString m_text;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent* event);
|
|
||||||
QSize sizeHint() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Indicator(const QString& text, QWidget* parent = NULL);
|
|
||||||
|
|
||||||
void setColor(const QColor& color);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_INDICATOR_H
|
|
@ -1,36 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_PHYSICALUNIT_H
|
|
||||||
#define INCLUDE_PHYSICALUNIT_H
|
|
||||||
|
|
||||||
namespace Unit {
|
|
||||||
enum Physical {
|
|
||||||
None,
|
|
||||||
Frequency,
|
|
||||||
Information,
|
|
||||||
Percent,
|
|
||||||
Decibel,
|
|
||||||
DecibelMilliWatt,
|
|
||||||
DecibelMicroVolt,
|
|
||||||
AngleDegrees,
|
|
||||||
Time,
|
|
||||||
Volt
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_PHYSICALUNIT_H
|
|
@ -1,22 +0,0 @@
|
|||||||
#ifndef INCLUDE_PLUGINSDIALOG_H
|
|
||||||
#define INCLUDE_PLUGINSDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include "plugin/pluginmanager.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class PluginsDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class PluginsDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit PluginsDialog(PluginManager* pluginManager, QWidget* parent = NULL);
|
|
||||||
~PluginsDialog();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::PluginsDialog* ui;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_PLUGINSDIALOG_H
|
|
@ -1,34 +0,0 @@
|
|||||||
#ifndef INCLUDE_PREFERENCESDIALOG_H
|
|
||||||
#define INCLUDE_PREFERENCESDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
class AudioDeviceInfo;
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class PreferencesDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class PreferencesDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit PreferencesDialog(AudioDeviceInfo* audioDeviceInfo, QWidget* parent = NULL);
|
|
||||||
~PreferencesDialog();
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum Audio {
|
|
||||||
ATDefault,
|
|
||||||
ATInterface,
|
|
||||||
ATDevice
|
|
||||||
};
|
|
||||||
|
|
||||||
Ui::PreferencesDialog* ui;
|
|
||||||
|
|
||||||
AudioDeviceInfo* m_audioDeviceInfo;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void accept();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_PREFERENCESDIALOG_H
|
|
@ -1,27 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <QTreeWidgetItem>
|
|
||||||
|
|
||||||
class PresetItem : public QTreeWidgetItem {
|
|
||||||
public:
|
|
||||||
PresetItem(QTreeWidgetItem* parent, const QStringList& strings, quint64 frequency, int type);
|
|
||||||
bool operator<(const QTreeWidgetItem& other) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
quint64 m_frequency;
|
|
||||||
};
|
|
@ -1,42 +0,0 @@
|
|||||||
#ifndef INCLUDE_ROLLUPWIDGET_H
|
|
||||||
#define INCLUDE_ROLLUPWIDGET_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API RollupWidget : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
RollupWidget(QWidget* parent = NULL);
|
|
||||||
|
|
||||||
QByteArray saveState(int version = 0) const;
|
|
||||||
bool restoreState(const QByteArray& state, int version = 0);
|
|
||||||
|
|
||||||
void setTitleColor(const QColor& c);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void widgetRolled(QWidget* widget, bool rollDown);
|
|
||||||
void menuDoubleClickEvent();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
enum {
|
|
||||||
VersionMarker = 0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
QColor m_titleColor;
|
|
||||||
|
|
||||||
int arrangeRollups();
|
|
||||||
|
|
||||||
void paintEvent(QPaintEvent*);
|
|
||||||
int paintRollup(QWidget* rollup, int pos, QPainter* p, bool last, const QColor& frame);
|
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* size);
|
|
||||||
void mousePressEvent(QMouseEvent* event);
|
|
||||||
void mouseDoubleClickEvent(QMouseEvent* event);
|
|
||||||
|
|
||||||
bool event(QEvent* event);
|
|
||||||
bool eventFilter(QObject* object, QEvent* event);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_ROLLUPWIDGET_H
|
|
@ -1,37 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include "gui/scaleengine.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API Scale : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
Scale(QWidget* parent = NULL);
|
|
||||||
|
|
||||||
void setOrientation(Qt::Orientation orientation);
|
|
||||||
void setRange(Unit::Physical physicalUnit, float rangeMin, float rangeMax);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Qt::Orientation m_orientation;
|
|
||||||
ScaleEngine m_scaleEngine;
|
|
||||||
|
|
||||||
void paintEvent(QPaintEvent*);
|
|
||||||
void resizeEvent(QResizeEvent*);
|
|
||||||
};
|
|
@ -1,90 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_SCALEENGINE_H
|
|
||||||
#define INCLUDE_SCALEENGINE_H
|
|
||||||
|
|
||||||
#include <QFont>
|
|
||||||
#include <QString>
|
|
||||||
#include <QList>
|
|
||||||
#include "physicalunit.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API ScaleEngine {
|
|
||||||
public:
|
|
||||||
struct Tick {
|
|
||||||
float pos;
|
|
||||||
bool major;
|
|
||||||
float textPos;
|
|
||||||
float textSize;
|
|
||||||
QString text;
|
|
||||||
};
|
|
||||||
typedef QList<Tick> TickList;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// base configuration
|
|
||||||
Qt::Orientation m_orientation;
|
|
||||||
QFont m_font;
|
|
||||||
float m_charSize;
|
|
||||||
|
|
||||||
// graph configuration
|
|
||||||
float m_size;
|
|
||||||
Unit::Physical m_physicalUnit;
|
|
||||||
float m_rangeMin;
|
|
||||||
float m_rangeMax;
|
|
||||||
|
|
||||||
// calculated values
|
|
||||||
bool m_recalc;
|
|
||||||
double m_scale;
|
|
||||||
QString m_unitStr;
|
|
||||||
TickList m_tickList;
|
|
||||||
double m_majorTickValueDistance;
|
|
||||||
double m_firstMajorTickValue;
|
|
||||||
int m_numMinorTicks;
|
|
||||||
int m_decimalPlaces;
|
|
||||||
|
|
||||||
QString formatTick(double value, int decimalPlaces, bool fancyTime = true);
|
|
||||||
void calcCharSize();
|
|
||||||
void calcScaleFactor();
|
|
||||||
double calcMajorTickUnits(double distance, int* retDecimalPlaces);
|
|
||||||
int calcTickTextSize();
|
|
||||||
void forceTwoTicks();
|
|
||||||
void reCalc();
|
|
||||||
|
|
||||||
double majorTickValue(int tick);
|
|
||||||
double minorTickValue(int tick);
|
|
||||||
|
|
||||||
public:
|
|
||||||
ScaleEngine();
|
|
||||||
|
|
||||||
void setOrientation(Qt::Orientation orientation);
|
|
||||||
void setFont(const QFont& font);
|
|
||||||
void setSize(float size);
|
|
||||||
float getSize() { return m_size; }
|
|
||||||
void setRange(Unit::Physical physicalUnit, float rangeMin, float rangeMax);
|
|
||||||
|
|
||||||
float getPosFromValue(double value);
|
|
||||||
float getValueFromPos(double pos);
|
|
||||||
const TickList& getTickList();
|
|
||||||
|
|
||||||
QString getRangeMinStr();
|
|
||||||
QString getRangeMaxStr();
|
|
||||||
|
|
||||||
float getScaleWidth();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_SCALEENGINE_H
|
|
@ -1,78 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QTimer>
|
|
||||||
#include "gui/colormapper.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API ValueDial : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
ValueDial(QWidget* parent = NULL, ColorMapper colorMapper = ColorMapper(ColorMapper::Normal));
|
|
||||||
|
|
||||||
void setValue(quint64 value);
|
|
||||||
void setValueRange(uint numDigits, quint64 min, quint64 max);
|
|
||||||
void setFont(const QFont& font);
|
|
||||||
void setBold(bool bold);
|
|
||||||
void setColorMapper(ColorMapper colorMapper);
|
|
||||||
quint64 getValue() const { return m_value; }
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void changed(quint64 value);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QLinearGradient m_background;
|
|
||||||
int m_numDigits;
|
|
||||||
int m_numDecimalPoints;
|
|
||||||
int m_digitWidth;
|
|
||||||
int m_digitHeight;
|
|
||||||
int m_hightlightedDigit;
|
|
||||||
int m_cursor;
|
|
||||||
bool m_cursorState;
|
|
||||||
quint64 m_value;
|
|
||||||
quint64 m_valueMax;
|
|
||||||
quint64 m_valueMin;
|
|
||||||
QString m_text;
|
|
||||||
|
|
||||||
quint64 m_valueNew;
|
|
||||||
QString m_textNew;
|
|
||||||
int m_animationState;
|
|
||||||
QTimer m_animationTimer;
|
|
||||||
QTimer m_blinkTimer;
|
|
||||||
|
|
||||||
ColorMapper m_colorMapper;
|
|
||||||
|
|
||||||
quint64 findExponent(int digit);
|
|
||||||
QChar digitNeigh(QChar c, bool dir);
|
|
||||||
QString formatText(quint64 value);
|
|
||||||
|
|
||||||
void paintEvent(QPaintEvent*);
|
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent*);
|
|
||||||
void mouseMoveEvent(QMouseEvent*);
|
|
||||||
void wheelEvent(QWheelEvent*);
|
|
||||||
void leaveEvent(QEvent*);
|
|
||||||
void keyPressEvent(QKeyEvent*);
|
|
||||||
void focusInEvent(QFocusEvent*);
|
|
||||||
void focusOutEvent(QFocusEvent*);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void animate();
|
|
||||||
void blink();
|
|
||||||
};
|
|
@ -1,158 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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_MAINWINDOW_H
|
|
||||||
#define INCLUDE_MAINWINDOW_H
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QTimer>
|
|
||||||
#include "settings/mainsettings.h"
|
|
||||||
#include "util/messagequeue.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class QLabel;
|
|
||||||
class QTreeWidgetItem;
|
|
||||||
class QDir;
|
|
||||||
class QComboBox;
|
|
||||||
|
|
||||||
class AudioDeviceInfo;
|
|
||||||
class DSPEngine;
|
|
||||||
class Indicator;
|
|
||||||
class SpectrumVis;
|
|
||||||
class GLSpectrum;
|
|
||||||
class GLSpectrumGUI;
|
|
||||||
class ChannelWindow;
|
|
||||||
class FileSink;
|
|
||||||
class SampleSource;
|
|
||||||
class PluginAPI;
|
|
||||||
class PluginGUI;
|
|
||||||
class ChannelMarker;
|
|
||||||
class PluginManager;
|
|
||||||
class PluginInterface;
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class MainWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SDRANGEL_API MainWindow : public QMainWindow {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct DeviceUISet
|
|
||||||
{
|
|
||||||
SpectrumVis *m_spectrumVis;
|
|
||||||
GLSpectrum *m_spectrum;
|
|
||||||
GLSpectrumGUI *m_spectrumGUI;
|
|
||||||
ChannelWindow *m_channelWindow;
|
|
||||||
QComboBox *m_sampleSource;
|
|
||||||
|
|
||||||
DeviceUISet(QTimer& timer);
|
|
||||||
~DeviceUISet();
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit MainWindow(QWidget* parent = 0);
|
|
||||||
~MainWindow();
|
|
||||||
|
|
||||||
MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
|
|
||||||
|
|
||||||
void addChannelCreateAction(QAction* action);
|
|
||||||
void addChannelRollup(QWidget* widget);
|
|
||||||
void addViewAction(QAction* action);
|
|
||||||
|
|
||||||
void addChannelMarker(ChannelMarker* channelMarker);
|
|
||||||
void removeChannelMarker(ChannelMarker* channelMarker);
|
|
||||||
|
|
||||||
void setInputGUI(QWidget* gui);
|
|
||||||
const QTimer& getMasterTimer() const { return m_masterTimer; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
PGroup,
|
|
||||||
PItem
|
|
||||||
};
|
|
||||||
|
|
||||||
Ui::MainWindow* ui;
|
|
||||||
|
|
||||||
AudioDeviceInfo* m_audioDeviceInfo;
|
|
||||||
|
|
||||||
MessageQueue m_inputMessageQueue;
|
|
||||||
|
|
||||||
MainSettings m_settings;
|
|
||||||
|
|
||||||
SpectrumVis* m_rxSpectrumVis;
|
|
||||||
FileSink *m_fileSink;
|
|
||||||
|
|
||||||
std::vector<DeviceUISet*> m_deviceUIs;
|
|
||||||
|
|
||||||
DSPEngine* m_dspEngine;
|
|
||||||
|
|
||||||
QTimer m_masterTimer;
|
|
||||||
QTimer m_statusTimer;
|
|
||||||
int m_lastEngineState;
|
|
||||||
|
|
||||||
QLabel* m_sampleRateWidget;
|
|
||||||
Indicator* m_recording;
|
|
||||||
Indicator* m_engineIdle;
|
|
||||||
Indicator* m_engineRunning;
|
|
||||||
Indicator* m_engineError;
|
|
||||||
|
|
||||||
bool m_startOsmoSDRUpdateAfterStop;
|
|
||||||
|
|
||||||
QWidget* m_inputGUI;
|
|
||||||
|
|
||||||
int m_sampleRate;
|
|
||||||
quint64 m_centerFrequency;
|
|
||||||
std::string m_sampleFileName;
|
|
||||||
|
|
||||||
PluginManager* m_pluginManager;
|
|
||||||
|
|
||||||
void loadSettings();
|
|
||||||
void loadPresetSettings(const Preset* preset);
|
|
||||||
void savePresetSettings(Preset* preset);
|
|
||||||
void saveSettings();
|
|
||||||
|
|
||||||
void createStatusBar();
|
|
||||||
void closeEvent(QCloseEvent*);
|
|
||||||
void updateCenterFreqDisplay();
|
|
||||||
void updateSampleRate();
|
|
||||||
void updatePresetControls();
|
|
||||||
QTreeWidgetItem* addPresetToTree(const Preset* preset);
|
|
||||||
void applySettings();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void handleDSPMessages();
|
|
||||||
void handleMessages();
|
|
||||||
void updateStatus();
|
|
||||||
void on_action_Start_triggered();
|
|
||||||
void on_action_Stop_triggered();
|
|
||||||
void on_action_Start_Recording_triggered();
|
|
||||||
void on_action_Stop_Recording_triggered();
|
|
||||||
void on_action_View_Fullscreen_toggled(bool checked);
|
|
||||||
void on_presetSave_clicked();
|
|
||||||
void on_presetUpdate_clicked();
|
|
||||||
void on_settingsSave_clicked();
|
|
||||||
void on_presetLoad_clicked();
|
|
||||||
void on_presetDelete_clicked();
|
|
||||||
void on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
|
||||||
void on_presetTree_itemActivated(QTreeWidgetItem *item, int column);
|
|
||||||
void on_action_Loaded_Plugins_triggered();
|
|
||||||
void on_action_Preferences_triggered();
|
|
||||||
void on_sampleSource_currentIndexChanged(int index);
|
|
||||||
void on_action_About_triggered();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_MAINWINDOW_H
|
|
@ -1,65 +0,0 @@
|
|||||||
#ifndef INCLUDE_PLUGINAPI_H
|
|
||||||
#define INCLUDE_PLUGINAPI_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
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 SDRANGEL_API PluginAPI : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
// MainWindow access
|
|
||||||
QDockWidget* createMainWindowDock(Qt::DockWidgetArea dockWidgetArea, const QString& title);
|
|
||||||
MessageQueue* getMainWindowMessageQueue();
|
|
||||||
void setInputGUI(QWidget* inputGUI);
|
|
||||||
|
|
||||||
// Channel stuff
|
|
||||||
void registerChannel(const QString& channelName, PluginInterface* plugin, QAction* action);
|
|
||||||
void registerChannelInstance(const QString& channelName, PluginGUI* pluginGUI);
|
|
||||||
void addChannelRollup(QWidget* pluginGUI);
|
|
||||||
void removeChannelInstance(PluginGUI* pluginGUI);
|
|
||||||
|
|
||||||
void addChannelMarker(ChannelMarker* channelMarker);
|
|
||||||
void removeChannelMarker(ChannelMarker* channelMarker);
|
|
||||||
|
|
||||||
// DSPEngine access
|
|
||||||
/* Direct access with DSP engine singleton
|
|
||||||
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);
|
|
||||||
|
|
||||||
// R/O access to main window
|
|
||||||
const MainWindow* getMainWindow() const { return m_mainWindow; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
PluginManager* m_pluginManager;
|
|
||||||
MainWindow* m_mainWindow;
|
|
||||||
DSPEngine* m_dspEngine;
|
|
||||||
|
|
||||||
PluginAPI(PluginManager* pluginManager, MainWindow* mainWindow, DSPEngine* dspEngine);
|
|
||||||
|
|
||||||
friend class PluginManager;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_PLUGINAPI_H
|
|
@ -1,30 +0,0 @@
|
|||||||
#ifndef INCLUDE_PLUGINGUI_H
|
|
||||||
#define INCLUDE_PLUGINGUI_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class Message;
|
|
||||||
|
|
||||||
class SDRANGEL_API PluginGUI {
|
|
||||||
public:
|
|
||||||
PluginGUI() { };
|
|
||||||
virtual ~PluginGUI() { };
|
|
||||||
|
|
||||||
virtual void destroy() = 0;
|
|
||||||
|
|
||||||
virtual void setName(const QString& name) = 0;
|
|
||||||
virtual QString getName() const = 0;
|
|
||||||
|
|
||||||
virtual void resetToDefaults() = 0;
|
|
||||||
|
|
||||||
virtual qint64 getCenterFrequency() const = 0;
|
|
||||||
virtual void setCenterFrequency(qint64 centerFrequency) = 0;
|
|
||||||
|
|
||||||
virtual QByteArray serialize() const = 0;
|
|
||||||
virtual bool deserialize(const QByteArray& data) = 0;
|
|
||||||
|
|
||||||
virtual bool handleMessage(const Message& message) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_PLUGINGUI_H
|
|
@ -1,54 +0,0 @@
|
|||||||
#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 id;
|
|
||||||
QString serial;
|
|
||||||
int sequence;
|
|
||||||
|
|
||||||
SampleSourceDevice(const QString& _displayedName,
|
|
||||||
const QString& _id,
|
|
||||||
const QString& _serial,
|
|
||||||
int _sequence) :
|
|
||||||
displayedName(_displayedName),
|
|
||||||
id(_id),
|
|
||||||
serial(_serial),
|
|
||||||
sequence(_sequence)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
typedef QList<SampleSourceDevice> SampleSourceDevices;
|
|
||||||
|
|
||||||
virtual ~PluginInterface() { };
|
|
||||||
|
|
||||||
virtual const PluginDescriptor& getPluginDescriptor() const = 0;
|
|
||||||
virtual void initPlugin(PluginAPI* pluginAPI) = 0;
|
|
||||||
|
|
||||||
virtual PluginGUI* createChannel(const QString& channelName) { return 0; }
|
|
||||||
|
|
||||||
virtual SampleSourceDevices enumSampleSources() { return SampleSourceDevices(); }
|
|
||||||
virtual PluginGUI* createSampleSourcePluginGUI(const QString& sourceId) { return 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_INTERFACE(PluginInterface, "SDRangel.PluginInterface/0.1");
|
|
||||||
|
|
||||||
#endif // INCLUDE_PLUGININTERFACE_H
|
|
@ -1,146 +0,0 @@
|
|||||||
#ifndef INCLUDE_PLUGINMANAGER_H
|
|
||||||
#define INCLUDE_PLUGINMANAGER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QDir>
|
|
||||||
#include "plugin/plugininterface.h"
|
|
||||||
#include "plugin/pluginapi.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class QAction;
|
|
||||||
class QComboBox;
|
|
||||||
class QPluginLoader;
|
|
||||||
class Preset;
|
|
||||||
class MainWindow;
|
|
||||||
class SampleSource;
|
|
||||||
class Message;
|
|
||||||
|
|
||||||
class SDRANGEL_API PluginManager : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct Plugin
|
|
||||||
{
|
|
||||||
QString filename;
|
|
||||||
QPluginLoader* loader;
|
|
||||||
PluginInterface* pluginInterface;
|
|
||||||
|
|
||||||
Plugin(const QString& _filename, QPluginLoader* pluginLoader, PluginInterface* _plugin) :
|
|
||||||
filename(_filename),
|
|
||||||
loader(pluginLoader),
|
|
||||||
pluginInterface(_plugin)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef QList<Plugin> Plugins;
|
|
||||||
|
|
||||||
explicit PluginManager(MainWindow* mainWindow, DSPEngine* dspEngine, QObject* parent = NULL);
|
|
||||||
~PluginManager();
|
|
||||||
void loadPlugins();
|
|
||||||
|
|
||||||
const Plugins& getPlugins() const { return m_plugins; }
|
|
||||||
|
|
||||||
void registerChannel(const QString& channelName, PluginInterface* plugin, QAction* action);
|
|
||||||
void registerChannelInstance(const QString& channelName, PluginGUI* pluginGUI);
|
|
||||||
void addChannelRollup(QWidget* pluginGUI);
|
|
||||||
void removeChannelInstance(PluginGUI* pluginGUI);
|
|
||||||
|
|
||||||
void registerSampleSource(const QString& sourceName, PluginInterface* plugin);
|
|
||||||
|
|
||||||
void loadSettings(const Preset* preset);
|
|
||||||
void loadSourceSettings(const Preset* preset);
|
|
||||||
void saveSettings(Preset* preset);
|
|
||||||
void saveSourceSettings(Preset* preset);
|
|
||||||
|
|
||||||
void freeAll();
|
|
||||||
|
|
||||||
bool handleMessage(const Message& message);
|
|
||||||
|
|
||||||
void updateSampleSourceDevices();
|
|
||||||
void fillSampleSourceSelector(QComboBox* comboBox);
|
|
||||||
int selectSampleSourceByIndex(int index);
|
|
||||||
int selectFirstSampleSource(const QString& sourceId);
|
|
||||||
int selectSampleSourceBySerialOrSequence(const QString& sourceId, const QString& sourceSerial, int sourceSequence);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct ChannelRegistration {
|
|
||||||
QString m_channelName;
|
|
||||||
PluginInterface* m_plugin;
|
|
||||||
ChannelRegistration(const QString& channelName, PluginInterface* plugin) :
|
|
||||||
m_channelName(channelName),
|
|
||||||
m_plugin(plugin)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
typedef QList<ChannelRegistration> ChannelRegistrations;
|
|
||||||
|
|
||||||
struct ChannelInstanceRegistration {
|
|
||||||
QString m_channelName;
|
|
||||||
PluginGUI* m_gui;
|
|
||||||
ChannelInstanceRegistration() :
|
|
||||||
m_channelName(),
|
|
||||||
m_gui(NULL)
|
|
||||||
{ }
|
|
||||||
ChannelInstanceRegistration(const QString& channelName, PluginGUI* pluginGUI) :
|
|
||||||
m_channelName(channelName),
|
|
||||||
m_gui(pluginGUI)
|
|
||||||
{ }
|
|
||||||
bool operator<(const ChannelInstanceRegistration& other) const;
|
|
||||||
};
|
|
||||||
typedef QList<ChannelInstanceRegistration> ChannelInstanceRegistrations;
|
|
||||||
|
|
||||||
struct SampleSourceRegistration {
|
|
||||||
QString m_sourceId;
|
|
||||||
PluginInterface* m_plugin;
|
|
||||||
SampleSourceRegistration(const QString& sourceId, PluginInterface* plugin) :
|
|
||||||
m_sourceId(sourceId),
|
|
||||||
m_plugin(plugin)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
typedef QList<SampleSourceRegistration> SampleSourceRegistrations;
|
|
||||||
|
|
||||||
struct SampleSourceDevice {
|
|
||||||
PluginInterface* m_plugin;
|
|
||||||
QString m_displayName;
|
|
||||||
QString m_sourceId;
|
|
||||||
QString m_sourceSerial;
|
|
||||||
int m_sourceSequence;
|
|
||||||
|
|
||||||
SampleSourceDevice(PluginInterface* plugin,
|
|
||||||
const QString& displayName,
|
|
||||||
const QString& sourceId,
|
|
||||||
const QString& sourceSerial,
|
|
||||||
int sourceSequence) :
|
|
||||||
m_plugin(plugin),
|
|
||||||
m_displayName(displayName),
|
|
||||||
m_sourceId(sourceId),
|
|
||||||
m_sourceSerial(sourceSerial),
|
|
||||||
m_sourceSequence(sourceSequence)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
typedef QList<SampleSourceDevice> SampleSourceDevices;
|
|
||||||
|
|
||||||
PluginAPI m_pluginAPI;
|
|
||||||
MainWindow* m_mainWindow;
|
|
||||||
DSPEngine* m_dspEngine;
|
|
||||||
Plugins m_plugins;
|
|
||||||
|
|
||||||
ChannelRegistrations m_channelRegistrations;
|
|
||||||
ChannelInstanceRegistrations m_channelInstanceRegistrations;
|
|
||||||
SampleSourceRegistrations m_sampleSourceRegistrations;
|
|
||||||
SampleSourceDevices m_sampleSourceDevices;
|
|
||||||
|
|
||||||
QString m_sampleSourceId;
|
|
||||||
QString m_sampleSourceSerial;
|
|
||||||
int m_sampleSourceSequence;
|
|
||||||
PluginGUI* m_sampleSourcePluginGUI;
|
|
||||||
|
|
||||||
void loadPlugins(const QDir& dir);
|
|
||||||
void renameChannelInstances();
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline bool operator<(const PluginManager::Plugin& a, const PluginManager::Plugin& b)
|
|
||||||
{
|
|
||||||
return a.pluginInterface->getPluginDescriptor().displayedName < b.pluginInterface->getPluginDescriptor().displayedName;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // INCLUDE_PLUGINMANAGER_H
|
|
@ -1,34 +0,0 @@
|
|||||||
#ifndef INCLUDE_SETTINGS_H
|
|
||||||
#define INCLUDE_SETTINGS_H
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include "preferences.h"
|
|
||||||
#include "preset.h"
|
|
||||||
|
|
||||||
class MainSettings {
|
|
||||||
public:
|
|
||||||
MainSettings();
|
|
||||||
~MainSettings();
|
|
||||||
|
|
||||||
void load();
|
|
||||||
void save() const;
|
|
||||||
|
|
||||||
void resetToDefaults();
|
|
||||||
|
|
||||||
Preset* newPreset(const QString& group, const QString& description);
|
|
||||||
void deletePreset(const Preset* preset);
|
|
||||||
int getPresetCount() const { return m_presets.count(); }
|
|
||||||
const Preset* getPreset(int index) const { return m_presets[index]; }
|
|
||||||
|
|
||||||
Preset* getWorkingPreset() { return &m_workingPreset; }
|
|
||||||
int getSourceIndex() const { return m_preferences.getSourceIndex(); }
|
|
||||||
void setSourceIndex(int value) { m_preferences.setSourceIndex(value); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Preferences m_preferences;
|
|
||||||
Preset m_workingPreset;
|
|
||||||
typedef QList<Preset*> Presets;
|
|
||||||
Presets m_presets;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_SETTINGS_H
|
|
@ -1,35 +0,0 @@
|
|||||||
#ifndef INCLUDE_PREFERENCES_H
|
|
||||||
#define INCLUDE_PREFERENCES_H
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class Preferences {
|
|
||||||
public:
|
|
||||||
Preferences();
|
|
||||||
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
|
|
||||||
void setSourceType(const QString& value) { m_sourceType = value; }
|
|
||||||
const QString& getSourceType() const { return m_sourceType; }
|
|
||||||
void setSourceDevice(const QString& value) { m_sourceDevice= value; }
|
|
||||||
const QString& getSourceDevice() const { return m_sourceDevice; }
|
|
||||||
void setSourceIndex(const int value) { m_sourceIndex = value; }
|
|
||||||
int getSourceIndex() const { return m_sourceIndex; }
|
|
||||||
|
|
||||||
void setAudioType(const QString& value) { m_audioType = value; }
|
|
||||||
const QString& getAudioType() const { return m_audioType; }
|
|
||||||
void setAudioDevice(const QString& value) { m_audioDevice= value; }
|
|
||||||
const QString& getAudioDevice() const { return m_audioDevice; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QString m_sourceType;
|
|
||||||
QString m_sourceDevice;
|
|
||||||
int m_sourceIndex;
|
|
||||||
|
|
||||||
QString m_audioType;
|
|
||||||
QString m_audioDevice;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_PREFERENCES_H
|
|
@ -1,110 +0,0 @@
|
|||||||
#ifndef INCLUDE_PRESET_H
|
|
||||||
#define INCLUDE_PRESET_H
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QList>
|
|
||||||
#include <QMetaType>
|
|
||||||
|
|
||||||
class Preset {
|
|
||||||
public:
|
|
||||||
struct ChannelConfig {
|
|
||||||
QString m_channel;
|
|
||||||
QByteArray m_config;
|
|
||||||
|
|
||||||
ChannelConfig(const QString& channel, const QByteArray& config) :
|
|
||||||
m_channel(channel),
|
|
||||||
m_config(config)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
typedef QList<ChannelConfig> ChannelConfigs;
|
|
||||||
|
|
||||||
struct SourceConfig
|
|
||||||
{
|
|
||||||
QString m_sourceId;
|
|
||||||
QString m_sourceSerial;
|
|
||||||
int m_sourceSequence;
|
|
||||||
QByteArray m_config;
|
|
||||||
|
|
||||||
SourceConfig(const QString& sourceId,
|
|
||||||
const QString& sourceSerial,
|
|
||||||
int sourceSequence,
|
|
||||||
const QByteArray& config) :
|
|
||||||
m_sourceId(sourceId),
|
|
||||||
m_sourceSerial(sourceSerial),
|
|
||||||
m_sourceSequence(sourceSequence),
|
|
||||||
m_config(config)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
typedef QList<SourceConfig> SourceConfigs;
|
|
||||||
|
|
||||||
Preset();
|
|
||||||
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
|
|
||||||
void setGroup(const QString& group) { m_group = group; }
|
|
||||||
const QString& getGroup() const { return m_group; }
|
|
||||||
void setDescription(const QString& description) { m_description = description; }
|
|
||||||
const QString& getDescription() const { return m_description; }
|
|
||||||
void setCenterFrequency(const quint64 centerFrequency) { m_centerFrequency = centerFrequency; }
|
|
||||||
quint64 getCenterFrequency() const { return m_centerFrequency; }
|
|
||||||
|
|
||||||
void setSpectrumConfig(const QByteArray& data) { m_spectrumConfig = data; }
|
|
||||||
const QByteArray& getSpectrumConfig() const { return m_spectrumConfig; }
|
|
||||||
|
|
||||||
void setLayout(const QByteArray& data) { m_layout = data; }
|
|
||||||
const QByteArray& getLayout() const { return m_layout; }
|
|
||||||
|
|
||||||
void clearChannels() { m_channelConfigs.clear(); }
|
|
||||||
void addChannel(const QString& channel, const QByteArray& config) { m_channelConfigs.append(ChannelConfig(channel, config)); }
|
|
||||||
int getChannelCount() const { return m_channelConfigs.count(); }
|
|
||||||
const ChannelConfig& getChannelConfig(int index) const { return m_channelConfigs.at(index); }
|
|
||||||
|
|
||||||
void setSourceConfig(const QString& sourceId, const QString& sourceSerial, int sourceSequence, const QByteArray& config)
|
|
||||||
{
|
|
||||||
addOrUpdateSourceConfig(sourceId, sourceSerial, sourceSequence, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addOrUpdateSourceConfig(const QString& sourceId,
|
|
||||||
const QString& sourceSerial,
|
|
||||||
int sourceSequence,
|
|
||||||
const QByteArray& config);
|
|
||||||
|
|
||||||
const QByteArray* findBestSourceConfig(const QString& sourceId,
|
|
||||||
const QString& sourceSerial,
|
|
||||||
int sourceSequence) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// group and preset description
|
|
||||||
QString m_group;
|
|
||||||
QString m_description;
|
|
||||||
quint64 m_centerFrequency;
|
|
||||||
|
|
||||||
// general configuration
|
|
||||||
QByteArray m_spectrumConfig;
|
|
||||||
|
|
||||||
// dc offset and i/q imbalance correction TODO: move it into the source data
|
|
||||||
bool m_dcOffsetCorrection;
|
|
||||||
bool m_iqImbalanceCorrection;
|
|
||||||
|
|
||||||
// sample source and sample source configuration
|
|
||||||
QString m_sourceId;
|
|
||||||
QString m_sourceSerial;
|
|
||||||
int m_sourceSequence;
|
|
||||||
QByteArray m_sourceConfig;
|
|
||||||
|
|
||||||
// channels and configurations
|
|
||||||
ChannelConfigs m_channelConfigs;
|
|
||||||
|
|
||||||
// sources and configurations
|
|
||||||
SourceConfigs m_sourceConfigs;
|
|
||||||
|
|
||||||
// screen and dock layout
|
|
||||||
QByteArray m_layout;
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(const Preset*);
|
|
||||||
Q_DECLARE_METATYPE(Preset*);
|
|
||||||
|
|
||||||
#endif // INCLUDE_PRESET_H
|
|
@ -1,38 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
|
|
||||||
// //
|
|
||||||
// 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_CRC64_H_
|
|
||||||
#define INCLUDE_CRC64_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
class CRC64
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CRC64();
|
|
||||||
~CRC64();
|
|
||||||
uint64_t calculate_crc(uint8_t *stream, int length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void build_crc_table();
|
|
||||||
|
|
||||||
uint64_t m_crcTable[256];
|
|
||||||
static const uint64_t m_poly;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDE_CRC64_H_ */
|
|
@ -1,53 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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 _UTIL_BITFIELDINDEX_H_
|
|
||||||
#define _UTIL_BITFIELDINDEX_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
template <unsigned int size>
|
|
||||||
struct BitfieldIndex
|
|
||||||
{
|
|
||||||
uint32_t v : size;
|
|
||||||
|
|
||||||
BitfieldIndex() {}
|
|
||||||
BitfieldIndex(int i) { v = i; }
|
|
||||||
|
|
||||||
BitfieldIndex& operator=(const BitfieldIndex& rhs) { v = rhs.v; return *this; }
|
|
||||||
BitfieldIndex& operator=(const int& rhi) { v = rhi; return *this; }
|
|
||||||
BitfieldIndex& operator++() { v++; return *this; }
|
|
||||||
BitfieldIndex operator++(int) { BitfieldIndex x(*this); ++(*this); return x; }
|
|
||||||
BitfieldIndex& operator+=(const BitfieldIndex& b) { v += b.v; return *this; }
|
|
||||||
BitfieldIndex& operator-=(const BitfieldIndex& b) { v -= b.v; return *this; }
|
|
||||||
BitfieldIndex& operator+=(int i) { v += i; return *this; }
|
|
||||||
BitfieldIndex& operator-=(int i) { v -= i; return *this; }
|
|
||||||
BitfieldIndex operator+(const BitfieldIndex& b) const { BitfieldIndex x(*this); x.v += b.v; return x; }
|
|
||||||
BitfieldIndex operator-(const BitfieldIndex& b) const { BitfieldIndex x(*this); x.v -= b.v; return x; }
|
|
||||||
BitfieldIndex operator+(int i) const { BitfieldIndex x(*this); x.v += i; return x; }
|
|
||||||
BitfieldIndex operator-(int i) const { BitfieldIndex x(*this); x.v -= i; return x; }
|
|
||||||
|
|
||||||
operator int() const { return v; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <unsigned int size>
|
|
||||||
BitfieldIndex<size> operator+(const BitfieldIndex<size> &a, const BitfieldIndex<size> &b) { BitfieldIndex<size> x; x.v = x.a + x.b; return x; }
|
|
||||||
|
|
||||||
template <unsigned int size>
|
|
||||||
BitfieldIndex<size> operator-(const BitfieldIndex<size> &a, const BitfieldIndex<size> &b) { BitfieldIndex<size> x; x.v = x.a - x.b; return x; }
|
|
||||||
|
|
||||||
#endif // _UTIL_BITFIELDINDEX_H_
|
|
@ -1,28 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
|
||||||
// //
|
|
||||||
// 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_UTIL_DB_H_
|
|
||||||
#define INCLUDE_UTIL_DB_H_
|
|
||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
|
|
||||||
class CalcDb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static Real dbPower(Real magsq);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INCLUDE_UTIL_DB_H_ */
|
|
@ -1,45 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB. //
|
|
||||||
// //
|
|
||||||
// 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 __SDRANGEL_EXPORT_H
|
|
||||||
#define __SDRANGEL_EXPORT_H
|
|
||||||
|
|
||||||
#if defined __GNUC__
|
|
||||||
# if __GNUC__ >= 4
|
|
||||||
# define __SDR_EXPORT __attribute__((visibility("default")))
|
|
||||||
# define __SDR_IMPORT __attribute__((visibility("default")))
|
|
||||||
# else
|
|
||||||
# define __SDR_EXPORT
|
|
||||||
# define __SDR_IMPORT
|
|
||||||
# endif
|
|
||||||
#elif _MSC_VER
|
|
||||||
# define __SDR_EXPORT __declspec(dllexport)
|
|
||||||
# define __SDR_IMPORT __declspec(dllimport)
|
|
||||||
#else
|
|
||||||
# define __SDR_EXPORT
|
|
||||||
# define __SDR_IMPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef sdrangel_STATIC
|
|
||||||
# ifdef sdrangel_EXPORTS
|
|
||||||
# define SDRANGEL_API __SDR_EXPORT
|
|
||||||
# else
|
|
||||||
# define SDRANGEL_API __SDR_IMPORT
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
#define SDRANGEL_API
|
|
||||||
#endif
|
|
||||||
#endif /* __SDRANGEL_EXPORT_H */
|
|
@ -1,59 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_MESSAGE_H
|
|
||||||
#define INCLUDE_MESSAGE_H
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API Message {
|
|
||||||
public:
|
|
||||||
Message();
|
|
||||||
virtual ~Message();
|
|
||||||
|
|
||||||
virtual const char* getIdentifier() const;
|
|
||||||
virtual bool matchIdentifier(const char* identifier) const;
|
|
||||||
static bool match(const Message* message);
|
|
||||||
|
|
||||||
void* getDestination() const { return m_destination; }
|
|
||||||
void setDestination(void *destination) { m_destination = destination; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// addressing
|
|
||||||
static const char* m_identifier;
|
|
||||||
void* m_destination;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MESSAGE_CLASS_DECLARATION \
|
|
||||||
public: \
|
|
||||||
const char* getIdentifier() const; \
|
|
||||||
bool matchIdentifier(const char* identifier) const; \
|
|
||||||
static bool match(const Message& message); \
|
|
||||||
protected: \
|
|
||||||
static const char* m_identifier; \
|
|
||||||
private:
|
|
||||||
|
|
||||||
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass) \
|
|
||||||
const char* Name::m_identifier = #Name; \
|
|
||||||
const char* Name::getIdentifier() const { return m_identifier; } \
|
|
||||||
bool Name::matchIdentifier(const char* identifier) const {\
|
|
||||||
return (m_identifier == identifier) ? true : BaseClass::matchIdentifier(identifier); \
|
|
||||||
} \
|
|
||||||
bool Name::match(const Message& message) { return message.matchIdentifier(m_identifier); }
|
|
||||||
|
|
||||||
#endif // INCLUDE_MESSAGE_H
|
|
@ -1,49 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_MESSAGEQUEUE_H
|
|
||||||
#define INCLUDE_MESSAGEQUEUE_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QQueue>
|
|
||||||
#include <QMutex>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class Message;
|
|
||||||
|
|
||||||
class SDRANGEL_API MessageQueue : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MessageQueue(QObject* parent = NULL);
|
|
||||||
~MessageQueue();
|
|
||||||
|
|
||||||
void push(Message* message, bool emitSignal = true); //!< Push message onto queue
|
|
||||||
Message* pop(); //!< Pop message from queue
|
|
||||||
|
|
||||||
int size(); //!< Returns queue size
|
|
||||||
void clear(); //!< Empty queue
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void messageEnqueued();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QMutex m_lock;
|
|
||||||
QQueue<Message*> m_queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_MESSAGEQUEUE_H
|
|
@ -1,40 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
|
||||||
// //
|
|
||||||
// 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_UTIL_PRETTYPRINT_H_
|
|
||||||
#define INCLUDE_UTIL_PRETTYPRINT_H_
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class EscapeColors
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const QString red;
|
|
||||||
static const QString blue;
|
|
||||||
static const QString green;
|
|
||||||
static const QString cyan;
|
|
||||||
static const QString purple;
|
|
||||||
static const QString yellow;
|
|
||||||
static const QString lightRed;
|
|
||||||
static const QString lightBlue;
|
|
||||||
static const QString lightGreen;
|
|
||||||
static const QString lightCyan;
|
|
||||||
static const QString lightPurple;
|
|
||||||
static const QString brown;
|
|
||||||
static const QString terminator;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INCLUDE_UTIL_PRETTYPRINT_H_ */
|
|
@ -1,50 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
|
||||||
// //
|
|
||||||
// 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_UTIL_SAMPLESOURCESERIALIZER_H_
|
|
||||||
#define INCLUDE_UTIL_SAMPLESOURCESERIALIZER_H_
|
|
||||||
|
|
||||||
#include "util/simpleserializer.h"
|
|
||||||
|
|
||||||
class SampleSourceSerializer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct Data
|
|
||||||
{
|
|
||||||
quint64 m_frequency; //!< RF center frequency
|
|
||||||
qint32 m_correction; //!< LO correction factor
|
|
||||||
qint32 m_rate; //!< RF sampler sample rate
|
|
||||||
quint32 m_log2Decim; //!< Decimation ratio log2
|
|
||||||
qint32 m_bandwidth; //!< RF bandwidth
|
|
||||||
qint32 m_fcPosition; //!< Decimated band placement (infradyne, supradyne, centered)
|
|
||||||
qint32 m_lnaGain; //!< RF LNA gain
|
|
||||||
qint32 m_RxGain1; //!< Rx first stage amplifier gain
|
|
||||||
qint32 m_RxGain2; //!< Rx second stage amplifier gain
|
|
||||||
qint32 m_RxGain3; //!< Rx third stage amplifier gain
|
|
||||||
};
|
|
||||||
|
|
||||||
static void writeSerializedData(const Data& data, QByteArray& serializedData);
|
|
||||||
static bool readSerializedData(const QByteArray& serializedData, Data& data);
|
|
||||||
static void setDefaults(Data& data);
|
|
||||||
static uint getSerializerVersion() { return m_version; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static const uint m_version;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDE_UTIL_SAMPLESOURCESERIALIZER_H_ */
|
|
@ -1,112 +0,0 @@
|
|||||||
#ifndef INCLUDE_SIMPLESERIALIZER_H
|
|
||||||
#define INCLUDE_SIMPLESERIALIZER_H
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QMap>
|
|
||||||
#include "dsp/dsptypes.h"
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class SDRANGEL_API 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 SDRANGEL_API 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
|
|
@ -1,39 +0,0 @@
|
|||||||
#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
|
|
@ -1,93 +0,0 @@
|
|||||||
// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/
|
|
||||||
// published under the WTFPL v2.0
|
|
||||||
|
|
||||||
#ifndef _STACKTRACE_H_
|
|
||||||
#define _STACKTRACE_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <execinfo.h>
|
|
||||||
#include <cxxabi.h>
|
|
||||||
|
|
||||||
/** Print a demangled stack backtrace of the caller function to FILE* out. */
|
|
||||||
static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63)
|
|
||||||
{
|
|
||||||
fprintf(out, "stack trace:\n");
|
|
||||||
|
|
||||||
// storage array for stack trace address data
|
|
||||||
void* addrlist[max_frames+1];
|
|
||||||
|
|
||||||
// retrieve current stack addresses
|
|
||||||
int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
|
|
||||||
|
|
||||||
if (addrlen == 0) {
|
|
||||||
fprintf(out, " <empty, possibly corrupt>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve addresses into strings containing "filename(function+address)",
|
|
||||||
// this array must be free()-ed
|
|
||||||
char** symbollist = backtrace_symbols(addrlist, addrlen);
|
|
||||||
|
|
||||||
// allocate string which will be filled with the demangled function name
|
|
||||||
size_t funcnamesize = 256;
|
|
||||||
char* funcname = (char*)malloc(funcnamesize);
|
|
||||||
|
|
||||||
// iterate over the returned symbol lines. skip the first, it is the
|
|
||||||
// address of this function.
|
|
||||||
for (int i = 1; i < addrlen; i++)
|
|
||||||
{
|
|
||||||
char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
|
|
||||||
|
|
||||||
// find parentheses and +address offset surrounding the mangled name:
|
|
||||||
// ./module(function+0x15c) [0x8048a6d]
|
|
||||||
for (char *p = symbollist[i]; *p; ++p)
|
|
||||||
{
|
|
||||||
if (*p == '(')
|
|
||||||
begin_name = p;
|
|
||||||
else if (*p == '+')
|
|
||||||
begin_offset = p;
|
|
||||||
else if (*p == ')' && begin_offset) {
|
|
||||||
end_offset = p;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (begin_name && begin_offset && end_offset
|
|
||||||
&& begin_name < begin_offset)
|
|
||||||
{
|
|
||||||
*begin_name++ = '\0';
|
|
||||||
*begin_offset++ = '\0';
|
|
||||||
*end_offset = '\0';
|
|
||||||
|
|
||||||
// mangled name is now in [begin_name, begin_offset) and caller
|
|
||||||
// offset in [begin_offset, end_offset). now apply
|
|
||||||
// __cxa_demangle():
|
|
||||||
|
|
||||||
int status;
|
|
||||||
char* ret = abi::__cxa_demangle(begin_name,
|
|
||||||
funcname, &funcnamesize, &status);
|
|
||||||
if (status == 0) {
|
|
||||||
funcname = ret; // use possibly realloc()-ed string
|
|
||||||
fprintf(out, " %s : %s+%s\n",
|
|
||||||
symbollist[i], funcname, begin_offset);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// demangling failed. Output function name as a C function with
|
|
||||||
// no arguments.
|
|
||||||
fprintf(out, " %s : %s()+%s\n",
|
|
||||||
symbollist[i], begin_name, begin_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// couldn't parse the line? print the whole line.
|
|
||||||
fprintf(out, " %s\n", symbollist[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(funcname);
|
|
||||||
free(symbollist);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // _STACKTRACE_H_
|
|
@ -1,57 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_UTIL_SYNCMESSENGER_H_
|
|
||||||
#define INCLUDE_UTIL_SYNCMESSENGER_H_
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QWaitCondition>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QAtomicInt>
|
|
||||||
#include "util/export.h"
|
|
||||||
|
|
||||||
class Message;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is responsible of managing the synchronous processing of a message across threads
|
|
||||||
*/
|
|
||||||
class SDRANGEL_API SyncMessenger : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
SyncMessenger();
|
|
||||||
~SyncMessenger();
|
|
||||||
|
|
||||||
int sendWait(Message& message, unsigned long msPollTime = 100); //!< Send message and waits for its process completion
|
|
||||||
Message* getMessage() const { return m_message; }
|
|
||||||
void storeMessage(Message& message) { m_message = &message; }
|
|
||||||
void done(int result = 0); //!< Processing of the message is complete
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void messageSent();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QWaitCondition m_waitCondition;
|
|
||||||
QMutex m_mutex;
|
|
||||||
QAtomicInt m_complete;
|
|
||||||
Message *m_message;
|
|
||||||
int m_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDE_UTIL_SYNCMESSENGER_H_ */
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* threadsafesingleton.h
|
|
||||||
*
|
|
||||||
* Created on: Aug 7, 2015
|
|
||||||
* Author: f4exb
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INCLUDE_UTIL_THREADSAFESINGLETON_H_
|
|
||||||
#define INCLUDE_UTIL_THREADSAFESINGLETON_H_
|
|
||||||
|
|
||||||
//! Template class used to make from a class a singleton.
|
|
||||||
/** S is the type of the singleton object to instantiate.
|
|
||||||
<br> This class permits to gather all singleton code in the same place
|
|
||||||
and not to pollute object interface with singleton methods.
|
|
||||||
<br> Accessing to the instance of S is made through ThreadSafeSingleton<S>::instance()
|
|
||||||
<br><B>Note :</B> The class using this adapter should have constructor and
|
|
||||||
destructor protected and copy constructor and operator= private.
|
|
||||||
<br>Besides it should declare the class ThreadSafeSingleton<S> friend in order
|
|
||||||
this class can make the construction.
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <class S> class ThreadSafeSingleton
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static S& instance() { return *_pInstance; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ThreadSafeSingleton() {}
|
|
||||||
~ThreadSafeSingleton() { delete _pInstance; }
|
|
||||||
static S* _pInstance;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ThreadSafeSingleton(const ThreadSafeSingleton&) {}
|
|
||||||
ThreadSafeSingleton& operator = (const ThreadSafeSingleton&) {return *this;}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class S> S *ThreadSafeSingleton<S>::_pInstance = new S;
|
|
||||||
|
|
||||||
#endif /* INCLUDE_UTIL_THREADSAFESINGLETON_H_ */
|
|
@ -1,81 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 F4EXB //
|
|
||||||
// written by Edouard Griffiths //
|
|
||||||
// //
|
|
||||||
// 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_UTIL_UDPSINK_H_
|
|
||||||
#define INCLUDE_UTIL_UDPSINK_H_
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QUdpSocket>
|
|
||||||
#include <QHostAddress>
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class UDPSink
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UDPSink(QObject *parent, unsigned int udpSize, unsigned int port) :
|
|
||||||
m_udpSize(udpSize),
|
|
||||||
m_address(QHostAddress::LocalHost),
|
|
||||||
m_port(port),
|
|
||||||
m_sampleBufferIndex(0)
|
|
||||||
{
|
|
||||||
m_sampleBuffer = new T[m_udpSize];
|
|
||||||
m_socket = new QUdpSocket(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
UDPSink (QObject *parent, unsigned int udpSize, QHostAddress& address, unsigned int port) :
|
|
||||||
m_udpSize(udpSize),
|
|
||||||
m_address(address),
|
|
||||||
m_port(port),
|
|
||||||
m_sampleBufferIndex(0)
|
|
||||||
{
|
|
||||||
m_sampleBuffer = new T[m_udpSize];
|
|
||||||
m_socket = new QUdpSocket(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
~UDPSink()
|
|
||||||
{
|
|
||||||
delete[] m_sampleBuffer;
|
|
||||||
delete m_socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(T sample)
|
|
||||||
{
|
|
||||||
m_sampleBuffer[m_sampleBufferIndex] = sample;
|
|
||||||
|
|
||||||
if (m_sampleBufferIndex < m_udpSize)
|
|
||||||
{
|
|
||||||
m_sampleBufferIndex++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_socket->writeDatagram((const char*)&m_sampleBuffer[0], (qint64 ) (m_udpSize * sizeof(T)), m_address, m_port);
|
|
||||||
m_sampleBufferIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int m_udpSize;
|
|
||||||
QHostAddress m_address;
|
|
||||||
unsigned int m_port;
|
|
||||||
QUdpSocket *m_socket;
|
|
||||||
T *m_sampleBuffer;;
|
|
||||||
int m_sampleBufferIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDE_UTIL_UDPSINK_H_ */
|
|
Loading…
x
Reference in New Issue
Block a user