mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-27 02:09:14 -05: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…
Reference in New Issue
Block a user