mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-07-08 03:45:26 -04:00
Demod Analyzer: implementation for the rest of planned plugins
This commit is contained in:
parent
e8ea0665fe
commit
793d8b9f49
plugins
channelrx
demoddsd
demodnfm
demodssb
demodwfm
channeltx
modam
modnfm
modpacket
packetmod.cpppacketmodbaseband.cpppacketmodbaseband.hpacketmodplugin.cpppacketmodsource.cpppacketmodsource.h
modssb
modwfm
feature/demodanalyzer
@ -30,7 +30,7 @@
|
|||||||
const PluginDescriptor DSDDemodPlugin::m_pluginDescriptor = {
|
const PluginDescriptor DSDDemodPlugin::m_pluginDescriptor = {
|
||||||
DSDDemod::m_channelId,
|
DSDDemod::m_channelId,
|
||||||
QStringLiteral("DSD Demodulator"),
|
QStringLiteral("DSD Demodulator"),
|
||||||
QStringLiteral("6.3.3"),
|
QStringLiteral("6.4.0"),
|
||||||
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
const PluginDescriptor NFMPlugin::m_pluginDescriptor = {
|
const PluginDescriptor NFMPlugin::m_pluginDescriptor = {
|
||||||
NFMDemod::m_channelId,
|
NFMDemod::m_channelId,
|
||||||
QStringLiteral("NFM Demodulator"),
|
QStringLiteral("NFM Demodulator"),
|
||||||
QStringLiteral("6.3.3"),
|
QStringLiteral("6.4.0"),
|
||||||
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -58,6 +58,7 @@ SSBDemod::SSBDemod(DeviceAPI *deviceAPI) :
|
|||||||
m_thread = new QThread(this);
|
m_thread = new QThread(this);
|
||||||
m_basebandSink = new SSBDemodBaseband();
|
m_basebandSink = new SSBDemodBaseband();
|
||||||
m_basebandSink->setSpectrumSink(&m_spectrumVis);
|
m_basebandSink->setSpectrumSink(&m_spectrumVis);
|
||||||
|
m_basebandSink->setChannel(this);
|
||||||
m_basebandSink->moveToThread(m_thread);
|
m_basebandSink->moveToThread(m_thread);
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
|
@ -63,6 +63,11 @@ void SSBDemodBaseband::reset()
|
|||||||
m_sampleFifo.reset();
|
m_sampleFifo.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SSBDemodBaseband::setChannel(ChannelAPI *channel)
|
||||||
|
{
|
||||||
|
m_sink.setChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
void SSBDemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
void SSBDemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
||||||
{
|
{
|
||||||
m_sampleFifo.write(begin, end);
|
m_sampleFifo.write(begin, end);
|
||||||
@ -198,4 +203,4 @@ void SSBDemodBaseband::setBasebandSampleRate(int sampleRate)
|
|||||||
{
|
{
|
||||||
m_channelizer->setBasebandSampleRate(sampleRate);
|
m_channelizer->setBasebandSampleRate(sampleRate);
|
||||||
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
m_sink.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "ssbdemodsink.h"
|
#include "ssbdemodsink.h"
|
||||||
|
|
||||||
class DownChannelizer;
|
class DownChannelizer;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class SSBDemodBaseband : public QObject
|
class SSBDemodBaseband : public QObject
|
||||||
{
|
{
|
||||||
@ -69,6 +70,7 @@ public:
|
|||||||
bool getAudioActive() const { return m_sink.getAudioActive(); }
|
bool getAudioActive() const { return m_sink.getAudioActive(); }
|
||||||
void setBasebandSampleRate(int sampleRate);
|
void setBasebandSampleRate(int sampleRate);
|
||||||
void setMessageQueueToGUI(MessageQueue *messageQueue) { m_messageQueueToGUI = messageQueue; }
|
void setMessageQueueToGUI(MessageQueue *messageQueue) { m_messageQueueToGUI = messageQueue; }
|
||||||
|
void setChannel(ChannelAPI *channel);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SampleSinkFifo m_sampleFifo;
|
SampleSinkFifo m_sampleFifo;
|
||||||
@ -90,4 +92,4 @@ private slots:
|
|||||||
void handleData(); //!< Handle data when samples have to be processed
|
void handleData(); //!< Handle data when samples have to be processed
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_SSBDEMODBASEBAND_H
|
#endif // INCLUDE_SSBDEMODBASEBAND_H
|
||||||
|
@ -25,8 +25,11 @@
|
|||||||
#include "dsp/dspcommands.h"
|
#include "dsp/dspcommands.h"
|
||||||
#include "dsp/devicesamplemimo.h"
|
#include "dsp/devicesamplemimo.h"
|
||||||
#include "dsp/basebandsamplesink.h"
|
#include "dsp/basebandsamplesink.h"
|
||||||
|
#include "dsp/datafifo.h"
|
||||||
#include "device/deviceapi.h"
|
#include "device/deviceapi.h"
|
||||||
#include "util/db.h"
|
#include "util/db.h"
|
||||||
|
#include "util/messagequeue.h"
|
||||||
|
#include "maincore.h"
|
||||||
|
|
||||||
#include "ssbdemodsink.h"
|
#include "ssbdemodsink.h"
|
||||||
|
|
||||||
@ -62,6 +65,9 @@ SSBDemodSink::SSBDemodSink() :
|
|||||||
m_undersampleCount = 0;
|
m_undersampleCount = 0;
|
||||||
m_sum = 0;
|
m_sum = 0;
|
||||||
|
|
||||||
|
m_demodBuffer.resize(1<<12);
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
|
||||||
m_usb = true;
|
m_usb = true;
|
||||||
m_magsq = 0.0f;
|
m_magsq = 0.0f;
|
||||||
m_magsqSum = 0.0f;
|
m_magsqSum = 0.0f;
|
||||||
@ -194,6 +200,25 @@ void SSBDemodSink::processOneSample(Complex &ci)
|
|||||||
m_audioBuffer[m_audioBufferFill].l = sample;
|
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_demodBuffer[m_demodBufferFill] = (z.real() + z.imag()) * 0.7;
|
||||||
|
++m_demodBufferFill;
|
||||||
|
|
||||||
|
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||||
|
{
|
||||||
|
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
|
||||||
|
|
||||||
|
if (dataFifos)
|
||||||
|
{
|
||||||
|
QList<DataFifo*>::iterator it = dataFifos->begin();
|
||||||
|
|
||||||
|
for (; it != dataFifos->end(); ++it) {
|
||||||
|
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++m_audioBufferFill;
|
++m_audioBufferFill;
|
||||||
@ -279,6 +304,19 @@ void SSBDemodSink::applyAudioSampleRate(int sampleRate)
|
|||||||
|
|
||||||
m_audioFifo.setSize(sampleRate);
|
m_audioFifo.setSize(sampleRate);
|
||||||
m_audioSampleRate = sampleRate;
|
m_audioSampleRate = sampleRate;
|
||||||
|
|
||||||
|
QList<MessageQueue*> *messageQueues = MainCore::instance()->getMessagePipes().getMessageQueues(m_channel, "reportdemod");
|
||||||
|
|
||||||
|
if (messageQueues)
|
||||||
|
{
|
||||||
|
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
||||||
|
|
||||||
|
for (; it != messageQueues->end(); ++it)
|
||||||
|
{
|
||||||
|
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, sampleRate);
|
||||||
|
(*it)->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodSink::applySettings(const SSBDemodSettings& settings, bool force)
|
void SSBDemodSink::applySettings(const SSBDemodSettings& settings, bool force)
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#ifndef INCLUDE_SSBDEMODSINK_H
|
#ifndef INCLUDE_SSBDEMODSINK_H
|
||||||
#define INCLUDE_SSBDEMODSINK_H
|
#define INCLUDE_SSBDEMODSINK_H
|
||||||
|
|
||||||
#include <vector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "dsp/channelsamplesink.h"
|
#include "dsp/channelsamplesink.h"
|
||||||
#include "dsp/ncof.h"
|
#include "dsp/ncof.h"
|
||||||
@ -31,6 +31,7 @@
|
|||||||
#include "ssbdemodsettings.h"
|
#include "ssbdemodsettings.h"
|
||||||
|
|
||||||
class BasebandSampleSink;
|
class BasebandSampleSink;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class SSBDemodSink : public ChannelSampleSink {
|
class SSBDemodSink : public ChannelSampleSink {
|
||||||
public:
|
public:
|
||||||
@ -47,6 +48,7 @@ public:
|
|||||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||||
double getMagSq() const { return m_magsq; }
|
double getMagSq() const { return m_magsq; }
|
||||||
bool getAudioActive() const { return m_audioActive; }
|
bool getAudioActive() const { return m_audioActive; }
|
||||||
|
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||||
|
|
||||||
void getMagSqLevels(double& avg, double& peak, int& nbSamples)
|
void getMagSqLevels(double& avg, double& peak, int& nbSamples)
|
||||||
{
|
{
|
||||||
@ -78,6 +80,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
SSBDemodSettings m_settings;
|
SSBDemodSettings m_settings;
|
||||||
|
ChannelAPI *m_channel;
|
||||||
|
|
||||||
Real m_Bandwidth;
|
Real m_Bandwidth;
|
||||||
Real m_LowCutoff;
|
Real m_LowCutoff;
|
||||||
@ -121,10 +124,13 @@ private:
|
|||||||
AudioFifo m_audioFifo;
|
AudioFifo m_audioFifo;
|
||||||
quint32 m_audioSampleRate;
|
quint32 m_audioSampleRate;
|
||||||
|
|
||||||
|
QVector<qint16> m_demodBuffer;
|
||||||
|
int m_demodBufferFill;
|
||||||
|
|
||||||
static const int m_ssbFftLen;
|
static const int m_ssbFftLen;
|
||||||
static const int m_agcTarget;
|
static const int m_agcTarget;
|
||||||
|
|
||||||
void processOneSample(Complex &ci);
|
void processOneSample(Complex &ci);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_SSBDEMODSINK_H
|
#endif // INCLUDE_SSBDEMODSINK_H
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
const PluginDescriptor SSBPlugin::m_pluginDescriptor = {
|
const PluginDescriptor SSBPlugin::m_pluginDescriptor = {
|
||||||
SSBDemod::m_channelId,
|
SSBDemod::m_channelId,
|
||||||
QStringLiteral("SSB Demodulator"),
|
QStringLiteral("SSB Demodulator"),
|
||||||
QStringLiteral("6.3.3"),
|
QStringLiteral("6.4.0"),
|
||||||
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -59,6 +59,7 @@ WFMDemod::WFMDemod(DeviceAPI* deviceAPI) :
|
|||||||
|
|
||||||
m_thread = new QThread(this);
|
m_thread = new QThread(this);
|
||||||
m_basebandSink = new WFMDemodBaseband();
|
m_basebandSink = new WFMDemodBaseband();
|
||||||
|
m_basebandSink->setChannel(this);
|
||||||
m_basebandSink->moveToThread(m_thread);
|
m_basebandSink->moveToThread(m_thread);
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
|
@ -58,6 +58,11 @@ void WFMDemodBaseband::reset()
|
|||||||
m_sampleFifo.reset();
|
m_sampleFifo.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WFMDemodBaseband::setChannel(ChannelAPI *channel)
|
||||||
|
{
|
||||||
|
m_sink.setChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
void WFMDemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
void WFMDemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
||||||
{
|
{
|
||||||
m_sampleFifo.write(begin, end);
|
m_sampleFifo.write(begin, end);
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "wfmdemodsink.h"
|
#include "wfmdemodsink.h"
|
||||||
|
|
||||||
class DownChannelizer;
|
class DownChannelizer;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class WFMDemodBaseband : public QObject
|
class WFMDemodBaseband : public QObject
|
||||||
{
|
{
|
||||||
@ -69,6 +70,7 @@ public:
|
|||||||
bool getSquelchOpen() const { return m_sink.getSquelchOpen(); }
|
bool getSquelchOpen() const { return m_sink.getSquelchOpen(); }
|
||||||
int getSquelchState() const { return m_sink.getSquelchState(); }
|
int getSquelchState() const { return m_sink.getSquelchState(); }
|
||||||
void getMagSqLevels(double& avg, double& peak, int& nbSamples) { m_sink.getMagSqLevels(avg, peak, nbSamples); }
|
void getMagSqLevels(double& avg, double& peak, int& nbSamples) { m_sink.getMagSqLevels(avg, peak, nbSamples); }
|
||||||
|
void setChannel(ChannelAPI *channel);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SampleSinkFifo m_sampleFifo;
|
SampleSinkFifo m_sampleFifo;
|
||||||
|
@ -25,7 +25,10 @@
|
|||||||
#include "dsp/dspengine.h"
|
#include "dsp/dspengine.h"
|
||||||
#include "dsp/dspcommands.h"
|
#include "dsp/dspcommands.h"
|
||||||
#include "dsp/devicesamplemimo.h"
|
#include "dsp/devicesamplemimo.h"
|
||||||
|
#include "dsp/datafifo.h"
|
||||||
#include "util/db.h"
|
#include "util/db.h"
|
||||||
|
#include "util/messagequeue.h"
|
||||||
|
#include "maincore.h"
|
||||||
|
|
||||||
#include "wfmdemodsink.h"
|
#include "wfmdemodsink.h"
|
||||||
|
|
||||||
@ -35,6 +38,7 @@ WFMDemodSink::WFMDemodSink() :
|
|||||||
m_channelSampleRate(384000),
|
m_channelSampleRate(384000),
|
||||||
m_channelFrequencyOffset(0),
|
m_channelFrequencyOffset(0),
|
||||||
m_audioSampleRate(48000),
|
m_audioSampleRate(48000),
|
||||||
|
m_squelchState(0),
|
||||||
m_squelchOpen(false),
|
m_squelchOpen(false),
|
||||||
m_magsq(0.0f),
|
m_magsq(0.0f),
|
||||||
m_magsqSum(0.0f),
|
m_magsqSum(0.0f),
|
||||||
@ -48,6 +52,9 @@ WFMDemodSink::WFMDemodSink() :
|
|||||||
m_audioBuffer.resize(16384);
|
m_audioBuffer.resize(16384);
|
||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
|
|
||||||
|
m_demodBuffer.resize(1<<12);
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||||
}
|
}
|
||||||
@ -130,6 +137,24 @@ void WFMDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||||
|
m_demodBuffer[m_demodBufferFill] = sample;
|
||||||
|
++m_demodBufferFill;
|
||||||
|
|
||||||
|
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||||
|
{
|
||||||
|
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
|
||||||
|
|
||||||
|
if (dataFifos)
|
||||||
|
{
|
||||||
|
QList<DataFifo*>::iterator it = dataFifos->begin();
|
||||||
|
|
||||||
|
for (; it != dataFifos->end(); ++it) {
|
||||||
|
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,6 +187,19 @@ void WFMDemodSink::applyAudioSampleRate(int sampleRate)
|
|||||||
m_interpolatorDistanceRemain = (Real) m_channelSampleRate / sampleRate;
|
m_interpolatorDistanceRemain = (Real) m_channelSampleRate / sampleRate;
|
||||||
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) sampleRate;
|
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) sampleRate;
|
||||||
m_audioSampleRate = sampleRate;
|
m_audioSampleRate = sampleRate;
|
||||||
|
|
||||||
|
QList<MessageQueue*> *messageQueues = MainCore::instance()->getMessagePipes().getMessageQueues(m_channel, "reportdemod");
|
||||||
|
|
||||||
|
if (messageQueues)
|
||||||
|
{
|
||||||
|
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
||||||
|
|
||||||
|
for (; it != messageQueues->end(); ++it)
|
||||||
|
{
|
||||||
|
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, sampleRate);
|
||||||
|
(*it)->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WFMDemodSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
|
void WFMDemodSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
|
||||||
@ -186,8 +224,8 @@ void WFMDemodSink::applyChannelSettings(int channelSampleRate, int channelFreque
|
|||||||
Real lowCut = -(m_settings.m_rfBandwidth / 2.0) / channelSampleRate;
|
Real lowCut = -(m_settings.m_rfBandwidth / 2.0) / channelSampleRate;
|
||||||
Real hiCut = (m_settings.m_rfBandwidth / 2.0) / channelSampleRate;
|
Real hiCut = (m_settings.m_rfBandwidth / 2.0) / channelSampleRate;
|
||||||
m_rfFilter->create_filter(lowCut, hiCut);
|
m_rfFilter->create_filter(lowCut, hiCut);
|
||||||
m_fmExcursion = m_settings.m_rfBandwidth / (Real) channelSampleRate;
|
//m_fmExcursion = m_settings.m_rfBandwidth / (Real) channelSampleRate;
|
||||||
m_phaseDiscri.setFMScaling(1.0f/m_fmExcursion);
|
m_phaseDiscri.setFMScaling((float) channelSampleRate / ((float) 2*m_fmExcursion));
|
||||||
qDebug("WFMDemod::applySettings: m_fmExcursion: %f", m_fmExcursion);
|
qDebug("WFMDemod::applySettings: m_fmExcursion: %f", m_fmExcursion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,8 +262,10 @@ void WFMDemodSink::applySettings(const WFMDemodSettings& settings, bool force)
|
|||||||
Real lowCut = -(settings.m_rfBandwidth / 2.0) / m_channelSampleRate;
|
Real lowCut = -(settings.m_rfBandwidth / 2.0) / m_channelSampleRate;
|
||||||
Real hiCut = (settings.m_rfBandwidth / 2.0) / m_channelSampleRate;
|
Real hiCut = (settings.m_rfBandwidth / 2.0) / m_channelSampleRate;
|
||||||
m_rfFilter->create_filter(lowCut, hiCut);
|
m_rfFilter->create_filter(lowCut, hiCut);
|
||||||
m_fmExcursion = settings.m_rfBandwidth / (Real) m_channelSampleRate;
|
m_fmExcursion = (settings.m_rfBandwidth / 2) - m_settings.m_afBandwidth;
|
||||||
m_phaseDiscri.setFMScaling(1.0f/m_fmExcursion);
|
m_fmExcursion = m_fmExcursion < 2500 ? 2500 : m_fmExcursion;
|
||||||
|
//m_fmExcursion = settings.m_rfBandwidth / (Real) m_channelSampleRate;
|
||||||
|
m_phaseDiscri.setFMScaling((float) m_channelSampleRate / ((float) 2*m_fmExcursion));
|
||||||
qDebug("WFMDemodSink::applySettings: m_fmExcursion: %f", m_fmExcursion);
|
qDebug("WFMDemodSink::applySettings: m_fmExcursion: %f", m_fmExcursion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#ifndef INCLUDE_WFMDEMODSINK_H
|
#ifndef INCLUDE_WFMDEMODSINK_H
|
||||||
#define INCLUDE_WFMDEMODSINK_H
|
#define INCLUDE_WFMDEMODSINK_H
|
||||||
|
|
||||||
#include <vector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "dsp/channelsamplesink.h"
|
#include "dsp/channelsamplesink.h"
|
||||||
#include "dsp/nco.h"
|
#include "dsp/nco.h"
|
||||||
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
#include "wfmdemodsettings.h"
|
#include "wfmdemodsettings.h"
|
||||||
|
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class WFMDemodSink : public ChannelSampleSink {
|
class WFMDemodSink : public ChannelSampleSink {
|
||||||
public:
|
public:
|
||||||
WFMDemodSink();
|
WFMDemodSink();
|
||||||
@ -67,6 +69,7 @@ public:
|
|||||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||||
void applyAudioSampleRate(int sampleRate);
|
void applyAudioSampleRate(int sampleRate);
|
||||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||||
|
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct MagSqLevelsStore
|
struct MagSqLevelsStore
|
||||||
@ -87,6 +90,7 @@ private:
|
|||||||
int m_channelSampleRate;
|
int m_channelSampleRate;
|
||||||
int m_channelFrequencyOffset;
|
int m_channelFrequencyOffset;
|
||||||
WFMDemodSettings m_settings;
|
WFMDemodSettings m_settings;
|
||||||
|
ChannelAPI *m_channel;
|
||||||
|
|
||||||
int m_audioSampleRate;
|
int m_audioSampleRate;
|
||||||
|
|
||||||
@ -115,6 +119,9 @@ private:
|
|||||||
SampleVector m_sampleBuffer;
|
SampleVector m_sampleBuffer;
|
||||||
PhaseDiscriminators m_phaseDiscri;
|
PhaseDiscriminators m_phaseDiscri;
|
||||||
|
|
||||||
|
QVector<qint16> m_demodBuffer;
|
||||||
|
int m_demodBufferFill;
|
||||||
|
|
||||||
static const unsigned int m_rfFilterFftLength;
|
static const unsigned int m_rfFilterFftLength;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
const PluginDescriptor WFMPlugin::m_pluginDescriptor = {
|
const PluginDescriptor WFMPlugin::m_pluginDescriptor = {
|
||||||
WFMDemod::m_channelId,
|
WFMDemod::m_channelId,
|
||||||
QStringLiteral("WFM Demodulator"),
|
QStringLiteral("WFM Demodulator"),
|
||||||
QStringLiteral("6.3.3"),
|
QStringLiteral("6.4.0"),
|
||||||
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -343,7 +343,6 @@ void AMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
|||||||
qDebug("AMModSource::applyFeedbackAudioSampleRate: %u", sampleRate);
|
qDebug("AMModSource::applyFeedbackAudioSampleRate: %u", sampleRate);
|
||||||
|
|
||||||
m_feedbackInterpolatorDistanceRemain = 0;
|
m_feedbackInterpolatorDistanceRemain = 0;
|
||||||
m_feedbackInterpolatorConsumed = false;
|
|
||||||
m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate;
|
m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate;
|
||||||
Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f;
|
Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f;
|
||||||
m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0);
|
m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0);
|
||||||
|
@ -85,7 +85,6 @@ private:
|
|||||||
Interpolator m_feedbackInterpolator;
|
Interpolator m_feedbackInterpolator;
|
||||||
Real m_feedbackInterpolatorDistance;
|
Real m_feedbackInterpolatorDistance;
|
||||||
Real m_feedbackInterpolatorDistanceRemain;
|
Real m_feedbackInterpolatorDistanceRemain;
|
||||||
bool m_feedbackInterpolatorConsumed;
|
|
||||||
|
|
||||||
double m_magsq;
|
double m_magsq;
|
||||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||||
|
@ -66,6 +66,7 @@ NFMMod::NFMMod(DeviceAPI *deviceAPI) :
|
|||||||
m_thread = new QThread(this);
|
m_thread = new QThread(this);
|
||||||
m_basebandSource = new NFMModBaseband();
|
m_basebandSource = new NFMModBaseband();
|
||||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||||
|
m_basebandSource->setChannel(this);
|
||||||
m_basebandSource->moveToThread(m_thread);
|
m_basebandSource->moveToThread(m_thread);
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
|
@ -62,6 +62,11 @@ void NFMModBaseband::reset()
|
|||||||
m_sampleFifo.reset();
|
m_sampleFifo.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NFMModBaseband::setChannel(ChannelAPI *channel)
|
||||||
|
{
|
||||||
|
m_source.setChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
void NFMModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
void NFMModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
||||||
{
|
{
|
||||||
unsigned int part1Begin, part1End, part2Begin, part2End;
|
unsigned int part1Begin, part1End, part2Begin, part2End;
|
||||||
@ -226,4 +231,4 @@ void NFMModBaseband::applySettings(const NFMModSettings& settings, bool force)
|
|||||||
int NFMModBaseband::getChannelSampleRate() const
|
int NFMModBaseband::getChannelSampleRate() const
|
||||||
{
|
{
|
||||||
return m_channelizer->getChannelSampleRate();
|
return m_channelizer->getChannelSampleRate();
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "nfmmodsource.h"
|
#include "nfmmodsource.h"
|
||||||
|
|
||||||
class UpChannelizer;
|
class UpChannelizer;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class NFMModBaseband : public QObject
|
class NFMModBaseband : public QObject
|
||||||
{
|
{
|
||||||
@ -69,6 +70,7 @@ public:
|
|||||||
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
||||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||||
AudioFifo *getFeedbackAudioFifo() { return m_source.getFeedbackAudioFifo(); }
|
AudioFifo *getFeedbackAudioFifo() { return m_source.getFeedbackAudioFifo(); }
|
||||||
|
void setChannel(ChannelAPI *channel);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
const PluginDescriptor NFMModPlugin::m_pluginDescriptor = {
|
const PluginDescriptor NFMModPlugin::m_pluginDescriptor = {
|
||||||
NFMMod::m_channelId,
|
NFMMod::m_channelId,
|
||||||
QStringLiteral("NFM Modulator"),
|
QStringLiteral("NFM Modulator"),
|
||||||
QStringLiteral("6.3.3"),
|
QStringLiteral("6.4.0"),
|
||||||
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "dsp/datafifo.h"
|
||||||
|
#include "util/messagequeue.h"
|
||||||
|
#include "maincore.h"
|
||||||
|
|
||||||
#include "nfmmodsource.h"
|
#include "nfmmodsource.h"
|
||||||
|
|
||||||
const int NFMModSource::m_levelNbSamples = 480; // every 10ms
|
const int NFMModSource::m_levelNbSamples = 480; // every 10ms
|
||||||
@ -44,6 +48,9 @@ NFMModSource::NFMModSource() :
|
|||||||
m_feedbackAudioBuffer.resize(1<<14);
|
m_feedbackAudioBuffer.resize(1<<14);
|
||||||
m_feedbackAudioBufferFill = 0;
|
m_feedbackAudioBufferFill = 0;
|
||||||
|
|
||||||
|
m_demodBuffer.resize(1<<12);
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
|
||||||
m_magsq = 0.0;
|
m_magsq = 0.0;
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
@ -132,7 +139,7 @@ void NFMModSource::pullAudio(unsigned int nbSamplesAudio)
|
|||||||
|
|
||||||
void NFMModSource::modulateSample()
|
void NFMModSource::modulateSample()
|
||||||
{
|
{
|
||||||
Real t0, t;
|
Real t0, t1, t;
|
||||||
|
|
||||||
pullAF(t0);
|
pullAF(t0);
|
||||||
m_preemphasisFilter.process(t0, t);
|
m_preemphasisFilter.process(t0, t);
|
||||||
@ -144,11 +151,13 @@ void NFMModSource::modulateSample()
|
|||||||
calculateLevel(t);
|
calculateLevel(t);
|
||||||
|
|
||||||
if (m_settings.m_ctcssOn) {
|
if (m_settings.m_ctcssOn) {
|
||||||
m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * (0.85f * m_bandpass.filter(t) + 0.15f * 0.625f * m_ctcssNco.next()) * 1.33f;
|
t1 = (0.85f * m_bandpass.filter(t) + 0.15f * 0.625f * m_ctcssNco.next()) * 1.2f;
|
||||||
} else {
|
} else {
|
||||||
m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * m_bandpass.filter(t) * 1.33f;
|
t1 = m_bandpass.filter(t) * 1.2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * t1;
|
||||||
|
|
||||||
// limit phasor range to ]-pi,pi]
|
// limit phasor range to ]-pi,pi]
|
||||||
if (m_modPhasor > M_PI) {
|
if (m_modPhasor > M_PI) {
|
||||||
m_modPhasor -= (2.0f * M_PI);
|
m_modPhasor -= (2.0f * M_PI);
|
||||||
@ -156,6 +165,25 @@ void NFMModSource::modulateSample()
|
|||||||
|
|
||||||
m_modSample.real(cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); // -1 dB
|
m_modSample.real(cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); // -1 dB
|
||||||
m_modSample.imag(sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF);
|
m_modSample.imag(sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF);
|
||||||
|
|
||||||
|
m_demodBuffer[m_demodBufferFill] = t1 * std::numeric_limits<int16_t>::max();
|
||||||
|
++m_demodBufferFill;
|
||||||
|
|
||||||
|
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||||
|
{
|
||||||
|
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
|
||||||
|
|
||||||
|
if (dataFifos)
|
||||||
|
{
|
||||||
|
QList<DataFifo*>::iterator it = dataFifos->begin();
|
||||||
|
|
||||||
|
for (; it != dataFifos->end(); ++it) {
|
||||||
|
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NFMModSource::pullAF(Real& sample)
|
void NFMModSource::pullAF(Real& sample)
|
||||||
@ -321,6 +349,19 @@ void NFMModSource::applyAudioSampleRate(int sampleRate)
|
|||||||
m_preemphasisFilter.configure(m_preemphasis*sampleRate);
|
m_preemphasisFilter.configure(m_preemphasis*sampleRate);
|
||||||
m_audioSampleRate = sampleRate;
|
m_audioSampleRate = sampleRate;
|
||||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||||
|
|
||||||
|
QList<MessageQueue*> *messageQueues = MainCore::instance()->getMessagePipes().getMessageQueues(m_channel, "reportdemod");
|
||||||
|
|
||||||
|
if (messageQueues)
|
||||||
|
{
|
||||||
|
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
||||||
|
|
||||||
|
for (; it != messageQueues->end(); ++it)
|
||||||
|
{
|
||||||
|
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, sampleRate);
|
||||||
|
(*it)->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NFMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
void NFMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -36,6 +37,8 @@
|
|||||||
|
|
||||||
#include "nfmmodsettings.h"
|
#include "nfmmodsettings.h"
|
||||||
|
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class NFMModSource : public QObject, public ChannelSampleSource
|
class NFMModSource : public QObject, public ChannelSampleSource
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -54,6 +57,7 @@ public:
|
|||||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||||
|
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||||
double getMagSq() const { return m_magsq; }
|
double getMagSq() const { return m_magsq; }
|
||||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||||
@ -69,6 +73,7 @@ private:
|
|||||||
int m_channelSampleRate;
|
int m_channelSampleRate;
|
||||||
int m_channelFrequencyOffset;
|
int m_channelFrequencyOffset;
|
||||||
NFMModSettings m_settings;
|
NFMModSettings m_settings;
|
||||||
|
ChannelAPI *m_channel;
|
||||||
|
|
||||||
NCO m_carrierNco;
|
NCO m_carrierNco;
|
||||||
NCOF m_toneNco;
|
NCOF m_toneNco;
|
||||||
@ -86,6 +91,9 @@ private:
|
|||||||
Real m_feedbackInterpolatorDistanceRemain;
|
Real m_feedbackInterpolatorDistanceRemain;
|
||||||
bool m_feedbackInterpolatorConsumed;
|
bool m_feedbackInterpolatorConsumed;
|
||||||
|
|
||||||
|
QVector<qint16> m_demodBuffer;
|
||||||
|
int m_demodBufferFill;
|
||||||
|
|
||||||
Lowpass<Real> m_lowpass;
|
Lowpass<Real> m_lowpass;
|
||||||
Bandpass<Real> m_bandpass;
|
Bandpass<Real> m_bandpass;
|
||||||
HighPassFilterRC m_preemphasisFilter;
|
HighPassFilterRC m_preemphasisFilter;
|
||||||
|
@ -64,6 +64,7 @@ PacketMod::PacketMod(DeviceAPI *deviceAPI) :
|
|||||||
m_thread = new QThread(this);
|
m_thread = new QThread(this);
|
||||||
m_basebandSource = new PacketModBaseband();
|
m_basebandSource = new PacketModBaseband();
|
||||||
m_basebandSource->setSpectrumSampleSink(&m_spectrumVis);
|
m_basebandSource->setSpectrumSampleSink(&m_spectrumVis);
|
||||||
|
m_basebandSource->setChannel(this);
|
||||||
m_basebandSource->moveToThread(m_thread);
|
m_basebandSource->moveToThread(m_thread);
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
|
@ -56,6 +56,11 @@ void PacketModBaseband::reset()
|
|||||||
m_sampleFifo.reset();
|
m_sampleFifo.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PacketModBaseband::setChannel(ChannelAPI *channel)
|
||||||
|
{
|
||||||
|
m_source.setChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
void PacketModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
void PacketModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
||||||
{
|
{
|
||||||
unsigned int part1Begin, part1End, part2Begin, part2End;
|
unsigned int part1Begin, part1End, part2Begin, part2End;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "packetmodsource.h"
|
#include "packetmodsource.h"
|
||||||
|
|
||||||
class UpChannelizer;
|
class UpChannelizer;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class PacketModBaseband : public QObject
|
class PacketModBaseband : public QObject
|
||||||
{
|
{
|
||||||
@ -65,7 +66,7 @@ public:
|
|||||||
double getMagSq() const { return m_source.getMagSq(); }
|
double getMagSq() const { return m_source.getMagSq(); }
|
||||||
int getChannelSampleRate() const;
|
int getChannelSampleRate() const;
|
||||||
void setSpectrumSampleSink(BasebandSampleSink* sampleSink) { m_source.setSpectrumSink(sampleSink); }
|
void setSpectrumSampleSink(BasebandSampleSink* sampleSink) { m_source.setSpectrumSink(sampleSink); }
|
||||||
|
void setChannel(ChannelAPI *channel);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
const PluginDescriptor PacketModPlugin::m_pluginDescriptor = {
|
const PluginDescriptor PacketModPlugin::m_pluginDescriptor = {
|
||||||
PacketMod::m_channelId,
|
PacketMod::m_channelId,
|
||||||
QStringLiteral("Packet Modulator"),
|
QStringLiteral("Packet Modulator"),
|
||||||
QStringLiteral("6.3.3"),
|
QStringLiteral("6.4.0"),
|
||||||
QStringLiteral("(c) Jon Beniston, M7RCE"),
|
QStringLiteral("(c) Jon Beniston, M7RCE"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -20,8 +20,11 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "dsp/basebandsamplesink.h"
|
#include "dsp/basebandsamplesink.h"
|
||||||
|
#include "dsp/datafifo.h"
|
||||||
#include "packetmodsource.h"
|
#include "packetmodsource.h"
|
||||||
#include "util/crc.h"
|
#include "util/crc.h"
|
||||||
|
#include "util/messagequeue.h"
|
||||||
|
#include "maincore.h"
|
||||||
|
|
||||||
PacketModSource::PacketModSource() :
|
PacketModSource::PacketModSource() :
|
||||||
m_channelSampleRate(48000),
|
m_channelSampleRate(48000),
|
||||||
@ -46,6 +49,10 @@ PacketModSource::PacketModSource() :
|
|||||||
qDebug() << "PacketModSource::PacketModSource creating BPF : " << m_channelSampleRate;
|
qDebug() << "PacketModSource::PacketModSource creating BPF : " << m_channelSampleRate;
|
||||||
m_bandpass.create(301, m_channelSampleRate, 800.0, 2600.0);
|
m_bandpass.create(301, m_channelSampleRate, 800.0, 2600.0);
|
||||||
m_pulseShape.create(0.5, 6, m_channelSampleRate/9600);
|
m_pulseShape.create(0.5, 6, m_channelSampleRate/9600);
|
||||||
|
|
||||||
|
m_demodBuffer.resize(1<<12);
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||||
}
|
}
|
||||||
@ -266,6 +273,25 @@ void PacketModSource::modulateSample()
|
|||||||
Real s = std::real(m_modSample);
|
Real s = std::real(m_modSample);
|
||||||
calculateLevel(s);
|
calculateLevel(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_demodBuffer[m_demodBufferFill] = audioMod * std::numeric_limits<int16_t>::max();
|
||||||
|
++m_demodBufferFill;
|
||||||
|
|
||||||
|
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||||
|
{
|
||||||
|
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
|
||||||
|
|
||||||
|
if (dataFifos)
|
||||||
|
{
|
||||||
|
QList<DataFifo*>::iterator it = dataFifos->begin();
|
||||||
|
|
||||||
|
for (; it != dataFifos->end(); ++it) {
|
||||||
|
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketModSource::calculateLevel(Real& sample)
|
void PacketModSource::calculateLevel(Real& sample)
|
||||||
@ -383,6 +409,19 @@ void PacketModSource::applyChannelSettings(int channelSampleRate, int channelFre
|
|||||||
qDebug() << "m_samplesPerSymbol: " << m_samplesPerSymbol << " (" << m_channelSampleRate << "/" << m_settings.m_baud << ")";
|
qDebug() << "m_samplesPerSymbol: " << m_samplesPerSymbol << " (" << m_channelSampleRate << "/" << m_settings.m_baud << ")";
|
||||||
// Precalculate FM sensensity to save doing it in the loop
|
// Precalculate FM sensensity to save doing it in the loop
|
||||||
m_phaseSensitivity = 2.0f * M_PI * m_settings.m_fmDeviation / (double)m_channelSampleRate;
|
m_phaseSensitivity = 2.0f * M_PI * m_settings.m_fmDeviation / (double)m_channelSampleRate;
|
||||||
|
|
||||||
|
QList<MessageQueue*> *messageQueues = MainCore::instance()->getMessagePipes().getMessageQueues(m_channel, "reportdemod");
|
||||||
|
|
||||||
|
if (messageQueues)
|
||||||
|
{
|
||||||
|
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
||||||
|
|
||||||
|
for (; it != messageQueues->end(); ++it)
|
||||||
|
{
|
||||||
|
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, m_channelSampleRate);
|
||||||
|
(*it)->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *ax25_address(uint8_t *p, QString address, uint8_t crrl)
|
static uint8_t *ax25_address(uint8_t *p, QString address, uint8_t crrl)
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -44,6 +45,7 @@
|
|||||||
#define AX25_NO_L3 0xf0
|
#define AX25_NO_L3 0xf0
|
||||||
|
|
||||||
class BasebandSampleSink;
|
class BasebandSampleSink;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class PacketModSource : public ChannelSampleSource
|
class PacketModSource : public ChannelSampleSource
|
||||||
{
|
{
|
||||||
@ -66,12 +68,14 @@ public:
|
|||||||
void applySettings(const PacketModSettings& settings, bool force = false);
|
void applySettings(const PacketModSettings& settings, bool force = false);
|
||||||
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
|
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
|
||||||
void addTXPacket(QString callsign, QString to, QString via, QString data);
|
void addTXPacket(QString callsign, QString to, QString via, QString data);
|
||||||
|
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_channelSampleRate;
|
int m_channelSampleRate;
|
||||||
int m_channelFrequencyOffset;
|
int m_channelFrequencyOffset;
|
||||||
int m_spectrumRate;
|
int m_spectrumRate;
|
||||||
PacketModSettings m_settings;
|
PacketModSettings m_settings;
|
||||||
|
ChannelAPI *m_channel;
|
||||||
|
|
||||||
NCO m_carrierNco;
|
NCO m_carrierNco;
|
||||||
Real m_audioPhase;
|
Real m_audioPhase;
|
||||||
@ -126,6 +130,9 @@ private:
|
|||||||
|
|
||||||
std::ofstream m_audioFile; // For debug output of baseband waveform
|
std::ofstream m_audioFile; // For debug output of baseband waveform
|
||||||
|
|
||||||
|
QVector<qint16> m_demodBuffer;
|
||||||
|
int m_demodBufferFill;
|
||||||
|
|
||||||
bool bitsValid(); // Are there and bits to transmit
|
bool bitsValid(); // Are there and bits to transmit
|
||||||
int getBit(); // Get bit from m_bits
|
int getBit(); // Get bit from m_bits
|
||||||
void addBit(int bit); // Add bit to m_bits, with zero stuffing
|
void addBit(int bit); // Add bit to m_bits, with zero stuffing
|
||||||
|
@ -67,6 +67,7 @@ SSBMod::SSBMod(DeviceAPI *deviceAPI) :
|
|||||||
m_basebandSource = new SSBModBaseband();
|
m_basebandSource = new SSBModBaseband();
|
||||||
m_basebandSource->setSpectrumSink(&m_spectrumVis);
|
m_basebandSource->setSpectrumSink(&m_spectrumVis);
|
||||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||||
|
m_basebandSource->setChannel(this);
|
||||||
m_basebandSource->moveToThread(m_thread);
|
m_basebandSource->moveToThread(m_thread);
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
|
@ -63,6 +63,11 @@ void SSBModBaseband::reset()
|
|||||||
m_sampleFifo.reset();
|
m_sampleFifo.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SSBModBaseband::setChannel(ChannelAPI *channel)
|
||||||
|
{
|
||||||
|
m_source.setChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
void SSBModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
void SSBModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
||||||
{
|
{
|
||||||
unsigned int part1Begin, part1End, part2Begin, part2End;
|
unsigned int part1Begin, part1End, part2Begin, part2End;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
class UpChannelizer;
|
class UpChannelizer;
|
||||||
class BasebandSampleSink;
|
class BasebandSampleSink;
|
||||||
class SpectrumVis;
|
class SpectrumVis;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class SSBModBaseband : public QObject
|
class SSBModBaseband : public QObject
|
||||||
{
|
{
|
||||||
@ -72,6 +73,7 @@ public:
|
|||||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||||
AudioFifo *getFeedbackAudioFifo() { return m_source.getFeedbackAudioFifo(); }
|
AudioFifo *getFeedbackAudioFifo() { return m_source.getFeedbackAudioFifo(); }
|
||||||
void setSpectrumSink(SpectrumVis *sampleSink) { m_spectrumVis = sampleSink; m_source.setSpectrumSink((BasebandSampleSink *) sampleSink); }
|
void setSpectrumSink(SpectrumVis *sampleSink) { m_spectrumVis = sampleSink; m_source.setSpectrumSink((BasebandSampleSink *) sampleSink); }
|
||||||
|
void setChannel(ChannelAPI *channel);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
const PluginDescriptor SSBModPlugin::m_pluginDescriptor = {
|
const PluginDescriptor SSBModPlugin::m_pluginDescriptor = {
|
||||||
SSBMod::m_channelId,
|
SSBMod::m_channelId,
|
||||||
QStringLiteral("SSB Modulator"),
|
QStringLiteral("SSB Modulator"),
|
||||||
QStringLiteral("6.3.3"),
|
QStringLiteral("6.4.0"),
|
||||||
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
#include "dsp/basebandsamplesink.h"
|
#include "dsp/basebandsamplesink.h"
|
||||||
#include "dsp/misc.h"
|
#include "dsp/misc.h"
|
||||||
|
#include "dsp/datafifo.h"
|
||||||
|
#include "util/messagequeue.h"
|
||||||
|
#include "maincore.h"
|
||||||
|
|
||||||
#include "ssbmodsource.h"
|
#include "ssbmodsource.h"
|
||||||
|
|
||||||
const int SSBModSource::m_ssbFftLen = 1024;
|
const int SSBModSource::m_ssbFftLen = 1024;
|
||||||
@ -51,6 +55,9 @@ SSBModSource::SSBModSource() :
|
|||||||
m_feedbackAudioBuffer.resize(1<<14);
|
m_feedbackAudioBuffer.resize(1<<14);
|
||||||
m_feedbackAudioBufferFill = 0;
|
m_feedbackAudioBufferFill = 0;
|
||||||
|
|
||||||
|
m_demodBuffer.resize(1<<12);
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
|
||||||
m_sum.real(0.0f);
|
m_sum.real(0.0f);
|
||||||
m_sum.imag(0.0f);
|
m_sum.imag(0.0f);
|
||||||
m_undersampleCount = 0;
|
m_undersampleCount = 0;
|
||||||
@ -163,6 +170,26 @@ void SSBModSource::modulateSample()
|
|||||||
}
|
}
|
||||||
|
|
||||||
calculateLevel(m_modSample);
|
calculateLevel(m_modSample);
|
||||||
|
|
||||||
|
// take projection on real axis
|
||||||
|
m_demodBuffer[m_demodBufferFill] = m_modSample.real() * std::numeric_limits<int16_t>::max();
|
||||||
|
++m_demodBufferFill;
|
||||||
|
|
||||||
|
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||||
|
{
|
||||||
|
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
|
||||||
|
|
||||||
|
if (dataFifos)
|
||||||
|
{
|
||||||
|
QList<DataFifo*>::iterator it = dataFifos->begin();
|
||||||
|
|
||||||
|
for (; it != dataFifos->end(); ++it) {
|
||||||
|
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBModSource::pullAF(Complex& sample)
|
void SSBModSource::pullAF(Complex& sample)
|
||||||
@ -574,6 +601,19 @@ void SSBModSource::applyAudioSampleRate(int sampleRate)
|
|||||||
m_audioSampleRate = sampleRate;
|
m_audioSampleRate = sampleRate;
|
||||||
|
|
||||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||||
|
|
||||||
|
QList<MessageQueue*> *messageQueues = MainCore::instance()->getMessagePipes().getMessageQueues(m_channel, "reportdemod");
|
||||||
|
|
||||||
|
if (messageQueues)
|
||||||
|
{
|
||||||
|
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
||||||
|
|
||||||
|
for (; it != messageQueues->end(); ++it)
|
||||||
|
{
|
||||||
|
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, sampleRate);
|
||||||
|
(*it)->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
void SSBModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -36,6 +37,7 @@
|
|||||||
#include "ssbmodsettings.h"
|
#include "ssbmodsettings.h"
|
||||||
|
|
||||||
class BasebandSampleSink;
|
class BasebandSampleSink;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class SSBModSource : public QObject, public ChannelSampleSource
|
class SSBModSource : public QObject, public ChannelSampleSource
|
||||||
{
|
{
|
||||||
@ -55,6 +57,7 @@ public:
|
|||||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||||
|
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||||
double getMagSq() const { return m_magsq; }
|
double getMagSq() const { return m_magsq; }
|
||||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||||
@ -71,6 +74,7 @@ private:
|
|||||||
int m_channelSampleRate;
|
int m_channelSampleRate;
|
||||||
int m_channelFrequencyOffset;
|
int m_channelFrequencyOffset;
|
||||||
SSBModSettings m_settings;
|
SSBModSettings m_settings;
|
||||||
|
ChannelAPI *m_channel;
|
||||||
|
|
||||||
NCOF m_carrierNco;
|
NCOF m_carrierNco;
|
||||||
NCOF m_toneNco;
|
NCOF m_toneNco;
|
||||||
@ -86,6 +90,9 @@ private:
|
|||||||
Real m_feedbackInterpolatorDistanceRemain;
|
Real m_feedbackInterpolatorDistanceRemain;
|
||||||
bool m_feedbackInterpolatorConsumed;
|
bool m_feedbackInterpolatorConsumed;
|
||||||
|
|
||||||
|
QVector<qint16> m_demodBuffer;
|
||||||
|
int m_demodBufferFill;
|
||||||
|
|
||||||
fftfilt* m_SSBFilter;
|
fftfilt* m_SSBFilter;
|
||||||
fftfilt* m_DSBFilter;
|
fftfilt* m_DSBFilter;
|
||||||
Complex* m_SSBFilterBuffer;
|
Complex* m_SSBFilterBuffer;
|
||||||
|
@ -64,6 +64,7 @@ WFMMod::WFMMod(DeviceAPI *deviceAPI) :
|
|||||||
m_thread = new QThread(this);
|
m_thread = new QThread(this);
|
||||||
m_basebandSource = new WFMModBaseband();
|
m_basebandSource = new WFMModBaseband();
|
||||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||||
|
m_basebandSource->setChannel(this);
|
||||||
m_basebandSource->moveToThread(m_thread);
|
m_basebandSource->moveToThread(m_thread);
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
|
@ -61,6 +61,11 @@ void WFMModBaseband::reset()
|
|||||||
m_sampleFifo.reset();
|
m_sampleFifo.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WFMModBaseband::setChannel(ChannelAPI *channel)
|
||||||
|
{
|
||||||
|
m_source.setChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
void WFMModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
void WFMModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
||||||
{
|
{
|
||||||
unsigned int part1Begin, part1End, part2Begin, part2End;
|
unsigned int part1Begin, part1End, part2Begin, part2End;
|
||||||
@ -209,4 +214,4 @@ void WFMModBaseband::applySettings(const WFMModSettings& settings, bool force)
|
|||||||
int WFMModBaseband::getChannelSampleRate() const
|
int WFMModBaseband::getChannelSampleRate() const
|
||||||
{
|
{
|
||||||
return m_channelizer->getChannelSampleRate();
|
return m_channelizer->getChannelSampleRate();
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "wfmmodsource.h"
|
#include "wfmmodsource.h"
|
||||||
|
|
||||||
class UpChannelizer;
|
class UpChannelizer;
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class WFMModBaseband : public QObject
|
class WFMModBaseband : public QObject
|
||||||
{
|
{
|
||||||
@ -68,6 +69,7 @@ public:
|
|||||||
int getChannelSampleRate() const;
|
int getChannelSampleRate() const;
|
||||||
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
||||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||||
|
void setChannel(ChannelAPI *channel);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
const PluginDescriptor WFMModPlugin::m_pluginDescriptor = {
|
const PluginDescriptor WFMModPlugin::m_pluginDescriptor = {
|
||||||
WFMMod::m_channelId,
|
WFMMod::m_channelId,
|
||||||
QStringLiteral("WFM Modulator"),
|
QStringLiteral("WFM Modulator"),
|
||||||
QStringLiteral("6.3.3"),
|
QStringLiteral("6.4.0"),
|
||||||
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
||||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "dsp/datafifo.h"
|
||||||
|
#include "util/messagequeue.h"
|
||||||
|
#include "maincore.h"
|
||||||
|
|
||||||
#include "wfmmodsource.h"
|
#include "wfmmodsource.h"
|
||||||
|
|
||||||
const int WFMModSource::m_rfFilterFFTLength = 1024;
|
const int WFMModSource::m_rfFilterFFTLength = 1024;
|
||||||
@ -46,6 +50,8 @@ WFMModSource::WFMModSource() :
|
|||||||
m_magsq = 0.0;
|
m_magsq = 0.0;
|
||||||
m_feedbackAudioBuffer.resize(1<<14);
|
m_feedbackAudioBuffer.resize(1<<14);
|
||||||
m_feedbackAudioBufferFill = 0;
|
m_feedbackAudioBufferFill = 0;
|
||||||
|
m_demodBuffer.resize(1<<12);
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||||
@ -140,6 +146,25 @@ void WFMModSource::pullOne(Sample& sample)
|
|||||||
|
|
||||||
sample.m_real = (FixReal) ci.real();
|
sample.m_real = (FixReal) ci.real();
|
||||||
sample.m_imag = (FixReal) ci.imag();
|
sample.m_imag = (FixReal) ci.imag();
|
||||||
|
|
||||||
|
m_demodBuffer[m_demodBufferFill] = t * std::numeric_limits<int16_t>::max();
|
||||||
|
++m_demodBufferFill;
|
||||||
|
|
||||||
|
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||||
|
{
|
||||||
|
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
|
||||||
|
|
||||||
|
if (dataFifos)
|
||||||
|
{
|
||||||
|
QList<DataFifo*>::iterator it = dataFifos->begin();
|
||||||
|
|
||||||
|
for (; it != dataFifos->end(); ++it) {
|
||||||
|
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_demodBufferFill = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WFMModSource::modulateAudio()
|
void WFMModSource::modulateAudio()
|
||||||
@ -237,13 +262,13 @@ void WFMModSource::pullAF(Real& sample)
|
|||||||
if (m_cwKeyer.getSample())
|
if (m_cwKeyer.getSample())
|
||||||
{
|
{
|
||||||
m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
|
m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
|
||||||
sample = m_cwToneNco.next() * m_settings.m_volumeFactor * fadeFactor;
|
sample = m_cwToneNco.next() * m_settings.m_volumeFactor * fadeFactor * 0.99f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor))
|
if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor))
|
||||||
{
|
{
|
||||||
sample = m_cwToneNco.next() * m_settings.m_volumeFactor * fadeFactor;
|
sample = m_cwToneNco.next() * m_settings.m_volumeFactor * fadeFactor * 0.99f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -339,6 +364,19 @@ void WFMModSource::applyAudioSampleRate(int sampleRate)
|
|||||||
m_cwKeyer.reset();
|
m_cwKeyer.reset();
|
||||||
m_audioSampleRate = sampleRate;
|
m_audioSampleRate = sampleRate;
|
||||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||||
|
|
||||||
|
QList<MessageQueue*> *messageQueues = MainCore::instance()->getMessagePipes().getMessageQueues(m_channel, "reportdemod");
|
||||||
|
|
||||||
|
if (messageQueues)
|
||||||
|
{
|
||||||
|
QList<MessageQueue*>::iterator it = messageQueues->begin();
|
||||||
|
|
||||||
|
for (; it != messageQueues->end(); ++it)
|
||||||
|
{
|
||||||
|
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, sampleRate);
|
||||||
|
(*it)->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WFMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
void WFMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -35,6 +36,8 @@
|
|||||||
|
|
||||||
#include "wfmmodsettings.h"
|
#include "wfmmodsettings.h"
|
||||||
|
|
||||||
|
class ChannelAPI;
|
||||||
|
|
||||||
class WFMModSource : public QObject, public ChannelSampleSource
|
class WFMModSource : public QObject, public ChannelSampleSource
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -53,6 +56,7 @@ public:
|
|||||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||||
|
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||||
double getMagSq() const { return m_magsq; }
|
double getMagSq() const { return m_magsq; }
|
||||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||||
@ -68,6 +72,7 @@ private:
|
|||||||
int m_channelSampleRate;
|
int m_channelSampleRate;
|
||||||
int m_channelFrequencyOffset;
|
int m_channelFrequencyOffset;
|
||||||
WFMModSettings m_settings;
|
WFMModSettings m_settings;
|
||||||
|
ChannelAPI *m_channel;
|
||||||
|
|
||||||
NCO m_carrierNco;
|
NCO m_carrierNco;
|
||||||
NCOF m_toneNco;
|
NCOF m_toneNco;
|
||||||
@ -85,6 +90,9 @@ private:
|
|||||||
Real m_feedbackInterpolatorDistanceRemain;
|
Real m_feedbackInterpolatorDistanceRemain;
|
||||||
bool m_feedbackInterpolatorConsumed;
|
bool m_feedbackInterpolatorConsumed;
|
||||||
|
|
||||||
|
QVector<qint16> m_demodBuffer;
|
||||||
|
int m_demodBufferFill;
|
||||||
|
|
||||||
fftfilt* m_rfFilter;
|
fftfilt* m_rfFilter;
|
||||||
static const int m_rfFilterFFTLength;
|
static const int m_rfFilterFFTLength;
|
||||||
fftfilt::cmplx *m_rfFilterBuffer;
|
fftfilt::cmplx *m_rfFilterBuffer;
|
||||||
|
@ -27,6 +27,12 @@ const QStringList DemodAnalyzerSettings::m_channelTypes = {
|
|||||||
QStringLiteral("AMMod"),
|
QStringLiteral("AMMod"),
|
||||||
QStringLiteral("DSDDemod"),
|
QStringLiteral("DSDDemod"),
|
||||||
QStringLiteral("NFMDemod"),
|
QStringLiteral("NFMDemod"),
|
||||||
|
QStringLiteral("NFMMod"),
|
||||||
|
QStringLiteral("PacketMod"),
|
||||||
|
QStringLiteral("SSBDemod"),
|
||||||
|
QStringLiteral("SSBMod"),
|
||||||
|
QStringLiteral("WFMDemod"),
|
||||||
|
QStringLiteral("WFMMod"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const QStringList DemodAnalyzerSettings::m_channelURIs = {
|
const QStringList DemodAnalyzerSettings::m_channelURIs = {
|
||||||
@ -34,6 +40,12 @@ const QStringList DemodAnalyzerSettings::m_channelURIs = {
|
|||||||
QStringLiteral("sdrangel.channeltx.modam"),
|
QStringLiteral("sdrangel.channeltx.modam"),
|
||||||
QStringLiteral("sdrangel.channel.dsddemod"),
|
QStringLiteral("sdrangel.channel.dsddemod"),
|
||||||
QStringLiteral("sdrangel.channel.nfmdemod"),
|
QStringLiteral("sdrangel.channel.nfmdemod"),
|
||||||
|
QStringLiteral("sdrangel.channeltx.modnfm"),
|
||||||
|
QStringLiteral("sdrangel.channeltx.modpacket"),
|
||||||
|
QStringLiteral("sdrangel.channel.ssbdemod"),
|
||||||
|
QStringLiteral("sdrangel.channeltx.modssb"),
|
||||||
|
QStringLiteral("sdrangel.channel.wfmdemod"),
|
||||||
|
QStringLiteral("sdrangel.channeltx.modwfm"),
|
||||||
};
|
};
|
||||||
|
|
||||||
DemodAnalyzerSettings::DemodAnalyzerSettings() :
|
DemodAnalyzerSettings::DemodAnalyzerSettings() :
|
||||||
|
Loading…
x
Reference in New Issue
Block a user