Merge pull request #192 from cjcliffe/demod_refactor

Demodulator Refactor
This commit is contained in:
Charles J. Cliffe 2015-11-20 22:41:49 -05:00
commit 3eb3ef4a74
62 changed files with 2186 additions and 1326 deletions

View File

@ -2,8 +2,8 @@ cmake_minimum_required (VERSION 2.8)
SET(CUBICSDR_VERSION_MAJOR "0")
SET(CUBICSDR_VERSION_MINOR "1")
SET(CUBICSDR_VERSION_PATCH "16")
SET(CUBICSDR_VERSION_REL "alpha")
SET(CUBICSDR_VERSION_PATCH "17")
SET(CUBICSDR_VERSION_REL "alpha-demod-refactor")
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}")
SET(CPACK_PACKAGE_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}")
@ -234,6 +234,26 @@ SET (cubicsdr_sources
src/demod/DemodulatorWorkerThread.cpp
src/demod/DemodulatorInstance.cpp
src/demod/DemodulatorMgr.cpp
src/modules/modem/Modem.cpp
src/modules/modem/ModemAnalog.cpp
src/modules/modem/ModemDigital.cpp
src/modules/modem/digital/ModemASK.cpp
src/modules/modem/digital/ModemAPSK.cpp
src/modules/modem/digital/ModemBPSK.cpp
src/modules/modem/digital/ModemDPSK.cpp
src/modules/modem/digital/ModemPSK.cpp
src/modules/modem/digital/ModemOOK.cpp
src/modules/modem/digital/ModemST.cpp
src/modules/modem/digital/ModemSQAM.cpp
src/modules/modem/digital/ModemQAM.cpp
src/modules/modem/digital/ModemQPSK.cpp
src/modules/modem/analog/ModemAM.cpp
src/modules/modem/analog/ModemDSB.cpp
src/modules/modem/analog/ModemFM.cpp
src/modules/modem/analog/ModemFMStereo.cpp
src/modules/modem/analog/ModemIQ.cpp
src/modules/modem/analog/ModemLSB.cpp
src/modules/modem/analog/ModemUSB.cpp
src/audio/AudioThread.cpp
src/util/Gradient.cpp
src/util/Timer.cpp
@ -293,6 +313,26 @@ SET (cubicsdr_headers
src/demod/DemodulatorInstance.h
src/demod/DemodulatorMgr.h
src/demod/DemodDefs.h
src/modules/modem/Modem.h
src/modules/modem/ModemAnalog.h
src/modules/modem/ModemDigital.h
src/modules/modem/digital/ModemASK.h
src/modules/modem/digital/ModemAPSK.h
src/modules/modem/digital/ModemBPSK.h
src/modules/modem/digital/ModemDPSK.h
src/modules/modem/digital/ModemPSK.h
src/modules/modem/digital/ModemOOK.h
src/modules/modem/digital/ModemST.h
src/modules/modem/digital/ModemSQAM.h
src/modules/modem/digital/ModemQAM.h
src/modules/modem/digital/ModemQPSK.h
src/modules/modem/analog/ModemAM.h
src/modules/modem/analog/ModemDSB.h
src/modules/modem/analog/ModemFM.h
src/modules/modem/analog/ModemFMStereo.h
src/modules/modem/analog/ModemIQ.h
src/modules/modem/analog/ModemLSB.h
src/modules/modem/analog/ModemUSB.h
src/audio/AudioThread.h
src/util/Gradient.h
src/util/Timer.h
@ -372,6 +412,9 @@ SOURCE_GROUP("Base" REGULAR_EXPRESSION "src/${REG_EXT}")
SOURCE_GROUP("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_EXT}")
SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}")
SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION "src/demod/${REG_EXT}")
SOURCE_GROUP("Modem" REGULAR_EXPRESSION "src/modules/modem/${REG_EXT}")
SOURCE_GROUP("Modem-Analog" REGULAR_EXPRESSION "src/modules/modem/analog/${REG_EXT}")
SOURCE_GROUP("Modem-Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}")
SOURCE_GROUP("Audio" REGULAR_EXPRESSION "src/audio/${REG_EXT}")
SOURCE_GROUP("Utility" REGULAR_EXPRESSION "src/util/${REG_EXT}")
SOURCE_GROUP("Visual" REGULAR_EXPRESSION "src/visual/${REG_EXT}")
@ -387,6 +430,10 @@ include_directories (
${PROJECT_SOURCE_DIR}/src/forms/SDRDevices
${PROJECT_SOURCE_DIR}/src/sdr
${PROJECT_SOURCE_DIR}/src/demod
${PROJECT_SOURCE_DIR}/src/modules
${PROJECT_SOURCE_DIR}/src/modules/modem
${PROJECT_SOURCE_DIR}/src/modules/modem/digital
${PROJECT_SOURCE_DIR}/src/modules/modem/analog
${PROJECT_SOURCE_DIR}/src/audio
${PROJECT_SOURCE_DIR}/src/util
${PROJECT_SOURCE_DIR}/src/panel

View File

@ -67,28 +67,29 @@ AppFrame::AppFrame() :
gainSpacerItem->Show(false);
demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList);
demodModeSelector->addChoice(DEMOD_TYPE_FM, "FM");
demodModeSelector->addChoice(DEMOD_TYPE_AM, "AM");
demodModeSelector->addChoice(DEMOD_TYPE_LSB, "LSB");
demodModeSelector->addChoice(DEMOD_TYPE_USB, "USB");
demodModeSelector->addChoice(DEMOD_TYPE_DSB, "DSB");
demodModeSelector->addChoice(DEMOD_TYPE_RAW, "I/Q");
demodModeSelector->setSelection(DEMOD_TYPE_FM);
demodModeSelector->addChoice(0, "FM");
demodModeSelector->addChoice(1, "FMS");
demodModeSelector->addChoice(2, "AM");
demodModeSelector->addChoice(3, "LSB");
demodModeSelector->addChoice(4, "USB");
demodModeSelector->addChoice(5, "DSB");
demodModeSelector->addChoice(6, "I/Q");
demodModeSelector->setSelection("FM");
demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band.");
demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0);
#ifdef ENABLE_DIGITAL_LAB
demodModeSelectorAdv = new ModeSelectorCanvas(this, attribList);
demodModeSelectorAdv->addChoice(DEMOD_TYPE_ASK, "ASK");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_APSK, "APSK");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_BPSK, "BPSK");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_DPSK, "DPSK");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_PSK, "PSK");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_OOK, "OOK");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_ST, "ST");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_SQAM, "SQAM");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_QAM, "QAM");
demodModeSelectorAdv->addChoice(DEMOD_TYPE_QPSK, "QPSK");
demodModeSelectorAdv->addChoice(0, "ASK");
demodModeSelectorAdv->addChoice(1, "APSK");
demodModeSelectorAdv->addChoice(2, "BPSK");
demodModeSelectorAdv->addChoice(3, "DPSK");
demodModeSelectorAdv->addChoice(4, "PSK");
demodModeSelectorAdv->addChoice(5, "OOK");
demodModeSelectorAdv->addChoice(6, "ST");
demodModeSelectorAdv->addChoice(7, "SQAM");
demodModeSelectorAdv->addChoice(8, "QAM");
demodModeSelectorAdv->addChoice(9, "QPSK");
demodModeSelectorAdv->setHelpTip("Choose advanced modulation types.");
demodTray->Add(demodModeSelectorAdv, 3, wxEXPAND | wxALL, 0);
@ -638,10 +639,9 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
} else if (event.GetId() == wxID_RESET) {
wxGetApp().getDemodMgr().terminateAll();
wxGetApp().setFrequency(100000000);
wxGetApp().getDemodMgr().setLastDemodulatorType(DEMOD_TYPE_FM);
wxGetApp().getDemodMgr().setLastDemodulatorType("FM");
demodModeSelector->setSelection(1);
wxGetApp().getDemodMgr().setLastMuted(false);
wxGetApp().getDemodMgr().setLastStereo(false);
wxGetApp().getDemodMgr().setLastBandwidth(DEFAULT_DEMOD_BW);
wxGetApp().getDemodMgr().setLastGain(1.0);
wxGetApp().getDemodMgr().setLastSquelchLevel(0);
@ -855,7 +855,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
int outputDevice = demod->getOutputDevice();
scopeCanvas->setDeviceName(outputDevices[outputDevice].name);
outputDeviceMenuItems[outputDevice]->Check(true);
int dType = demod->getDemodulatorType();
std::string dType = demod->getDemodulatorType();
demodModeSelector->setSelection(dType);
#ifdef ENABLE_DIGITAL_LAB
int dCons = demod->getDemodulatorCons();
@ -868,12 +868,12 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
long long centerFreq = demod->getFrequency();
unsigned int demodBw = (unsigned int) ceil((float) demod->getBandwidth() * 2.25);
if (demod->getDemodulatorType() == DEMOD_TYPE_USB) {
if (demod->getDemodulatorType() == "USB") {
demodBw /= 2;
centerFreq += demod->getBandwidth() / 4;
}
if (demod->getDemodulatorType() == DEMOD_TYPE_LSB) {
if (demod->getDemodulatorType() == "LSB") {
demodBw /= 2;
centerFreq -= demod->getBandwidth() / 4;
}
@ -889,18 +889,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
demodWaterfallCanvas->setCenterFrequency(centerFreq);
demodSpectrumCanvas->setCenterFrequency(centerFreq);
}
int dSelection = demodModeSelector->getSelection();
std::string dSelection = demodModeSelector->getSelectionLabel();
#ifdef ENABLE_DIGITAL_LAB
int dSelectionadv = demodModeSelectorAdv->getSelection();
std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel();
int dSelectionCons = demodModeSelectorCons->getSelection();
// basic demodulators
if (dSelection != -1 && dSelection != demod->getDemodulatorType()) {
if (dSelection != "" && dSelection != demod->getDemodulatorType()) {
demod->setDemodulatorType(dSelection);
demodModeSelectorAdv->setSelection(-1);
}
// advanced demodulators
else if (dSelectionadv != -1 && dSelectionadv != demod->getDemodulatorType()) {
else if (dSelectionadv != "" && dSelectionadv != demod->getDemodulatorType()) {
demod->setDemodulatorType(dSelectionadv);
demodModeSelector->setSelection(-1);
}
@ -911,7 +911,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
}
#else
// basic demodulators
if (dSelection != -1 && dSelection != demod->getDemodulatorType()) {
if (dSelection != "" && dSelection != demod->getDemodulatorType()) {
demod->setDemodulatorType(dSelection);
}
#endif
@ -951,18 +951,18 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
} else {
DemodulatorMgr *mgr = &wxGetApp().getDemodMgr();
int dSelection = demodModeSelector->getSelection();
std::string dSelection = demodModeSelector->getSelectionLabel();
#ifdef ENABLE_DIGITAL_LAB
int dSelectionadv = demodModeSelectorAdv->getSelection();
std::string dSelectionadv = demodModeSelectorAdv->getSelectionLabel();
int dSelectionCons = demodModeSelectorCons->getSelection();
// basic demodulators
if (dSelection != -1 && dSelection != mgr->getLastDemodulatorType()) {
if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) {
mgr->setLastDemodulatorType(dSelection);
demodModeSelectorAdv->setSelection(-1);
}
// advanced demodulators
else if(dSelectionadv != -1 && dSelectionadv != mgr->getLastDemodulatorType()) {
else if(dSelectionadv != "" && dSelectionadv != mgr->getLastDemodulatorType()) {
mgr->setLastDemodulatorType(dSelectionadv);
demodModeSelector->setSelection(-1);
}
@ -973,7 +973,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
}
#else
// basic demodulators
if (dSelection != -1 && dSelection != mgr->getLastDemodulatorType()) {
if (dSelection != "" && dSelection != mgr->getLastDemodulatorType()) {
mgr->setLastDemodulatorType(dSelection);
}
#endif
@ -1128,7 +1128,6 @@ void AppFrame::saveSession(std::string fileName) {
*demod->newChild("type") = (*instance_i)->getDemodulatorType();
*demod->newChild("squelch_level") = (*instance_i)->getSquelchLevel();
*demod->newChild("squelch_enabled") = (*instance_i)->isSquelchEnabled() ? 1 : 0;
*demod->newChild("stereo") = (*instance_i)->isStereo() ? 1 : 0;
*demod->newChild("output_device") = outputDevices[(*instance_i)->getOutputDevice()].name;
*demod->newChild("gain") = (*instance_i)->getGain();
*demod->newChild("muted") = (*instance_i)->isMuted() ? 1 : 0;
@ -1175,14 +1174,32 @@ bool AppFrame::loadSession(std::string fileName) {
long bandwidth = *demod->getNext("bandwidth");
long long freq = *demod->getNext("frequency");
int type = demod->hasAnother("type") ? *demod->getNext("type") : DEMOD_TYPE_FM;
std::string type = demod->hasAnother("type") ? string(*demod->getNext("type")) : "FM";
float squelch_level = demod->hasAnother("squelch_level") ? (float) *demod->getNext("squelch_level") : 0;
int squelch_enabled = demod->hasAnother("squelch_enabled") ? (int) *demod->getNext("squelch_enabled") : 0;
int stereo = demod->hasAnother("stereo") ? (int) *demod->getNext("stereo") : 0;
int muted = demod->hasAnother("muted") ? (int) *demod->getNext("muted") : 0;
std::string output_device = demod->hasAnother("output_device") ? string(*(demod->getNext("output_device"))) : "";
float gain = demod->hasAnother("gain") ? (float) *demod->getNext("gain") : 1.0;
// TODO: Check if "type" is numeric and perform update to new values
//#define DEMOD_TYPE_NULL 0
//#define DEMOD_TYPE_FM 1
//#define DEMOD_TYPE_AM 2
//#define DEMOD_TYPE_LSB 3
//#define DEMOD_TYPE_USB 4
//#define DEMOD_TYPE_DSB 5
//#define DEMOD_TYPE_ASK 6
//#define DEMOD_TYPE_APSK 7
//#define DEMOD_TYPE_BPSK 8
//#define DEMOD_TYPE_DPSK 9
//#define DEMOD_TYPE_PSK 10
//#define DEMOD_TYPE_OOK 11
//#define DEMOD_TYPE_ST 12
//#define DEMOD_TYPE_SQAM 13
//#define DEMOD_TYPE_QAM 14
//#define DEMOD_TYPE_QPSK 15
//#define DEMOD_TYPE_RAW 16
DemodulatorInstance *newDemod = wxGetApp().getDemodMgr().newThread();
loadedDemod = newDemod;
numDemodulators++;
@ -1196,10 +1213,7 @@ bool AppFrame::loadSession(std::string fileName) {
newDemod->setSquelchEnabled(true);
newDemod->setSquelchLevel(squelch_level);
}
if (stereo) {
newDemod->setStereo(true);
}
bool found_device = false;
std::map<int, RtAudio::DeviceInfo>::iterator i;
for (i = outputDevices.begin(); i != outputDevices.end(); i++) {
@ -1221,7 +1235,6 @@ bool AppFrame::loadSession(std::string fileName) {
std::cout << "\t\tBandwidth: " << bandwidth << std::endl;
std::cout << "\t\tSquelch Level: " << squelch_level << std::endl;
std::cout << "\t\tSquelch Enabled: " << (squelch_enabled ? "true" : "false") << std::endl;
std::cout << "\t\tStereo: " << (stereo ? "true" : "false") << std::endl;
std::cout << "\t\tOutput Device: " << output_device << std::endl;
}

View File

@ -164,6 +164,25 @@ bool CubicSDR::OnInit() {
wxApp::SetAppName("CubicSDR");
Modem::addModemFactory(new ModemFM);
Modem::addModemFactory(new ModemFMStereo);
Modem::addModemFactory(new ModemAM);
Modem::addModemFactory(new ModemLSB);
Modem::addModemFactory(new ModemUSB);
Modem::addModemFactory(new ModemDSB);
Modem::addModemFactory(new ModemIQ);
Modem::addModemFactory(new ModemAPSK);
Modem::addModemFactory(new ModemASK);
Modem::addModemFactory(new ModemBPSK);
Modem::addModemFactory(new ModemDPSK);
Modem::addModemFactory(new ModemOOK);
Modem::addModemFactory(new ModemPSK);
Modem::addModemFactory(new ModemQAM);
Modem::addModemFactory(new ModemQPSK);
Modem::addModemFactory(new ModemSQAM);
Modem::addModemFactory(new ModemST);
frequency = wxGetApp().getConfig()->getCenterFreq();
offset = 0;
ppm = 0;

View File

@ -27,6 +27,26 @@
#include "SpectrumVisualProcessor.h"
#include "SpectrumVisualDataThread.h"
#include "SDRDevices.h"
#include "Modem.h"
#include "ModemFM.h"
#include "ModemFMStereo.h"
#include "ModemAM.h"
#include "ModemUSB.h"
#include "ModemLSB.h"
#include "ModemDSB.h"
#include "ModemIQ.h"
#include "ModemAPSK.h"
#include "ModemASK.h"
#include "ModemBPSK.h"
#include "ModemDPSK.h"
#include "ModemOOK.h"
#include "ModemPSK.h"
#include "ModemQAM.h"
#include "ModemQPSK.h"
#include "ModemSQAM.h"
#include "ModemST.h"
#include <wx/cmdline.h>

View File

@ -30,7 +30,7 @@ const char filePathSeparator =
#define DEFAULT_SAMPLE_RATE 2500000
#define DEFAULT_FFT_SIZE 2048
#define DEFAULT_DEMOD_TYPE 1
#define DEFAULT_DEMOD_TYPE "FM"
#define DEFAULT_DEMOD_BW 200000
#define DEFAULT_WATERFALL_LPS 30

View File

@ -7,24 +7,6 @@
#include <atomic>
#include <mutex>
#define DEMOD_TYPE_NULL 0
#define DEMOD_TYPE_FM 1
#define DEMOD_TYPE_AM 2
#define DEMOD_TYPE_LSB 3
#define DEMOD_TYPE_USB 4
#define DEMOD_TYPE_DSB 5
#define DEMOD_TYPE_ASK 6
#define DEMOD_TYPE_APSK 7
#define DEMOD_TYPE_BPSK 8
#define DEMOD_TYPE_DPSK 9
#define DEMOD_TYPE_PSK 10
#define DEMOD_TYPE_OOK 11
#define DEMOD_TYPE_ST 12
#define DEMOD_TYPE_SQAM 13
#define DEMOD_TYPE_QAM 14
#define DEMOD_TYPE_QPSK 15
#define DEMOD_TYPE_RAW 16
#include "IOThread.h"
class DemodulatorThread;
@ -62,11 +44,11 @@ public:
};
DemodulatorThreadControlCommand() :
cmd(DEMOD_THREAD_CMD_CTL_NULL), demodType(DEMOD_TYPE_NULL) {
cmd(DEMOD_THREAD_CMD_CTL_NULL), demodType("") {
}
DemodulatorThreadControlCommandEnum cmd;
int demodType;
std::string demodType;
};
class DemodulatorThreadIQData: public ReferenceCounter {
@ -93,21 +75,19 @@ public:
}
};
class Modem;
class ModemKit;
class DemodulatorThreadPostIQData: public ReferenceCounter {
public:
std::vector<liquid_float_complex> data;
long long sampleRate;
msresamp_rrrf audioResampler;
msresamp_rrrf stereoResampler;
double audioResampleRatio;
int audioSampleRate;
firfilt_rrrf firStereoLeft;
firfilt_rrrf firStereoRight;
iirfilt_crcf iirStereoPilot;
std::string modemType;
Modem *modem;
ModemKit *modemKit;
DemodulatorThreadPostIQData() :
sampleRate(0), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(0), audioSampleRate(0), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL) {
sampleRate(0), modem(nullptr), modemKit(nullptr) {
}
@ -116,6 +96,7 @@ public:
}
};
class DemodulatorThreadAudioData: public ReferenceCounter {
public:
long long frequency;
@ -151,11 +132,11 @@ public:
unsigned int bandwidth; // set equal to disable second stage re-sampling?
unsigned int audioSampleRate;
int demodType;
std::string demodType;
DemodulatorThreadParameters() :
frequency(0), sampleRate(DEFAULT_SAMPLE_RATE), bandwidth(200000), audioSampleRate(0),
demodType(DEMOD_TYPE_FM) {
demodType("FM") {
}

View File

@ -9,7 +9,6 @@ DemodulatorInstance::DemodulatorInstance() :
preDemodTerminated.store(true);
active.store(false);
squelch.store(false);
stereo.store(false);
muted.store(false);
tracking.store(false);
follow.store(false);
@ -34,7 +33,7 @@ DemodulatorInstance::DemodulatorInstance() :
pipeAudioData = new AudioThreadInputQueue;
threadQueueControl = new DemodulatorThreadControlCommandQueue;
demodulatorThread = new DemodulatorThread();
demodulatorThread = new DemodulatorThread(this);
demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData);
demodulatorThread->setInputQueue("ControlQueue",threadQueueControl);
demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
@ -44,8 +43,7 @@ DemodulatorInstance::DemodulatorInstance() :
audioThread->setInputQueue("AudioDataInput", pipeAudioData);
audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify);
currentDemodType = demodulatorThread->getDemodulatorType();
currentDemodCons = demodulatorThread->getDemodulatorCons();
currentDemodType = demodulatorPreThread->getParams().demodType;
}
DemodulatorInstance::~DemodulatorInstance() {
@ -74,10 +72,9 @@ void DemodulatorInstance::run() {
// }
currentFrequency = demodulatorPreThread->getParams().frequency;
currentDemodType = demodulatorThread->getDemodulatorType();
currentDemodCons = demodulatorThread->getDemodulatorCons();
currentAudioSampleRate = AudioThread::deviceSampleRate[getOutputDevice()];
demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate;
setDemodulatorType(demodulatorPreThread->getParams().demodType);
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
@ -103,6 +100,7 @@ void DemodulatorInstance::run() {
t_PreDemod = new std::thread(&DemodulatorPreThread::threadMain, demodulatorPreThread);
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
#endif
active = true;
audioTerminated = demodTerminated = preDemodTerminated = terminated = false;
@ -196,15 +194,6 @@ void DemodulatorInstance::setActive(bool state) {
active = state;
}
bool DemodulatorInstance::isStereo() {
return stereo;
}
void DemodulatorInstance::setStereo(bool state) {
stereo = state;
demodulatorThread->setStereo(state);
}
void DemodulatorInstance::squelchAuto() {
DemodulatorThreadControlCommand command;
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON;
@ -271,57 +260,69 @@ void DemodulatorInstance::checkBandwidth() {
// }
}
void DemodulatorInstance::setDemodulatorType(int demod_type_in) {
void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) {
currentDemodType = demod_type_in;
if (currentDemodType == DEMOD_TYPE_RAW) {
if (currentDemodType == "I/Q") {
if (currentAudioSampleRate) {
setBandwidth(currentAudioSampleRate);
} else {
setBandwidth(AudioThread::deviceSampleRate[getOutputDevice()]);
}
} else if (currentDemodType == DEMOD_TYPE_USB || currentDemodType == DEMOD_TYPE_LSB || currentDemodType == DEMOD_TYPE_DSB || currentDemodType == DEMOD_TYPE_AM) {
} else if (currentDemodType == "USB" || currentDemodType == "LSB" || currentDemodType == "DSB" || currentDemodType == "AM") {
demodulatorThread->setAGC(false);
} else {
demodulatorThread->setAGC(true);
}
setGain(getGain());
demodulatorPreThread->getParams().demodType = currentDemodType;
if (!active) {
checkBandwidth();
demodulatorPreThread->getParams().demodType = currentDemodType;
demodulatorThread->setDemodulatorType(currentDemodType);
demodulatorPreThread->setDemodType(currentDemodType);
} else if (demodulatorThread && threadQueueControl) {
DemodulatorThreadControlCommand command;
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE;
command.demodType = demod_type_in;
checkBandwidth();
threadQueueControl->push(command);
demodulatorPreThread->setDemodType(currentDemodType);
}
}
int DemodulatorInstance::getDemodulatorType() {
std::string DemodulatorInstance::getDemodulatorType() {
return currentDemodType;
}
void DemodulatorInstance::setDemodulatorLock(bool demod_lock_in) {
demodulatorThread->setDemodulatorLock(demod_lock_in);
Modem *cModem = demodulatorPreThread->getModem();
if (cModem && cModem->getType() == "digital") {
((ModemDigital *)cModem)->setDemodulatorLock(demod_lock_in);
}
}
int DemodulatorInstance::getDemodulatorLock() {
return demodulatorThread->getDemodulatorLock();
Modem *cModem = demodulatorPreThread->getModem();
if (cModem && cModem->getType() == "digital") {
return ((ModemDigital *)cModem)->getDemodulatorLock();
}
return 0;
}
void DemodulatorInstance::setDemodulatorCons(int demod_cons_in) {
demodulatorThread->setDemodulatorCons(demod_cons_in);
Modem *cModem = demodulatorPreThread->getModem();
if (cModem && cModem->getType() == "digital") {
((ModemDigital *)cModem)->setDemodulatorCons(demod_cons_in);
}
}
int DemodulatorInstance::getDemodulatorCons() {
return demodulatorThread->getDemodulatorCons();
Modem *cModem = demodulatorPreThread->getModem();
if (cModem && cModem->getType() == "digital") {
return ((ModemDigital *)cModem)->getDemodulatorCons();
}
return 0;
}
void DemodulatorInstance::setBandwidth(int bw) {
if (currentDemodType == DEMOD_TYPE_RAW) {
if (currentDemodType == "I/Q") {
if (currentAudioSampleRate) {
bw = currentAudioSampleRate;
} else {
@ -384,7 +385,7 @@ void DemodulatorInstance::setAudioSampleRate(int sampleRate) {
command.llong_value = sampleRate;
pipeDemodCommand->push(command);
}
if (currentDemodType == DEMOD_TYPE_RAW) {
if (currentDemodType == "I/Q") {
setBandwidth(currentAudioSampleRate);
}
}
@ -400,7 +401,7 @@ int DemodulatorInstance::getAudioSampleRate() {
void DemodulatorInstance::setGain(float gain_in) {
currentAudioGain = gain_in;
if (currentDemodType == DEMOD_TYPE_RAW) {
if (currentDemodType == "I/Q") {
if (gain_in < 0.25) {
audioThread->setGain(1.0);
demodulatorThread->setAGC(false);

View File

@ -7,6 +7,9 @@
#include "DemodulatorThread.h"
#include "DemodulatorPreThread.h"
#include "ModemDigital.h"
#include "ModemAnalog.h"
class DemodulatorInstance {
public:
@ -39,9 +42,6 @@ public:
bool isActive();
void setActive(bool state);
bool isStereo();
void setStereo(bool state);
void squelchAuto();
bool isSquelchEnabled();
void setSquelchEnabled(bool state);
@ -53,8 +53,8 @@ public:
void setOutputDevice(int device_id);
int getOutputDevice();
void setDemodulatorType(int demod_type_in);
int getDemodulatorType();
void setDemodulatorType(std::string demod_type_in);
std::string getDemodulatorType();
void setDemodulatorLock(bool demod_lock_in);
int getDemodulatorLock();
@ -98,7 +98,7 @@ protected:
private:
void checkBandwidth();
std::atomic<std::string *> label; //
std::atomic_bool terminated; //
std::atomic_bool demodTerminated; //
@ -106,13 +106,11 @@ private:
std::atomic_bool preDemodTerminated;
std::atomic_bool active;
std::atomic_bool squelch;
std::atomic_bool stereo;
std::atomic_bool muted;
std::atomic_llong currentFrequency;
std::atomic_int currentBandwidth;
std::atomic_int currentDemodType;
std::atomic_int currentDemodCons;
std::string currentDemodType;
std::atomic_int currentOutputDevice;
std::atomic_int currentAudioSampleRate;
std::atomic<float> currentAudioGain;

View File

@ -7,7 +7,7 @@
DemodulatorMgr::DemodulatorMgr() :
activeDemodulator(NULL), lastActiveDemodulator(NULL), activeVisualDemodulator(NULL), lastBandwidth(DEFAULT_DEMOD_BW), lastDemodType(
DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(0), lastGain(1.0), lastStereo(false), lastMuted(false) {
DEFAULT_DEMOD_TYPE), lastSquelchEnabled(false), lastSquelch(0), lastGain(1.0), lastMuted(false) {
}
@ -76,7 +76,7 @@ std::vector<DemodulatorInstance *> *DemodulatorMgr::getDemodulatorsAt(long long
long long halfBuffer = bandwidth / 2;
if ((freq <= (freqTest + ((testDemod->getDemodulatorType() != DEMOD_TYPE_LSB)?halfBandwidthTest:0) + halfBuffer)) && (freq >= (freqTest - ((testDemod->getDemodulatorType() != DEMOD_TYPE_USB)?halfBandwidthTest:0) - halfBuffer))) {
if ((freq <= (freqTest + ((testDemod->getDemodulatorType() != "LSB")?halfBandwidthTest:0) + halfBuffer)) && (freq >= (freqTest - ((testDemod->getDemodulatorType() != "USB")?halfBandwidthTest:0) - halfBuffer))) {
foundDemods->push_back(testDemod);
}
}
@ -166,7 +166,6 @@ void DemodulatorMgr::updateLastState() {
lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled();
lastSquelch = lastActiveDemodulator->getSquelchLevel();
lastGain = lastActiveDemodulator->getGain();
lastStereo = lastActiveDemodulator->isStereo();
}
}
@ -184,11 +183,11 @@ void DemodulatorMgr::setLastBandwidth(int lastBandwidth) {
this->lastBandwidth = lastBandwidth;
}
int DemodulatorMgr::getLastDemodulatorType() const {
std::string DemodulatorMgr::getLastDemodulatorType() const {
return lastDemodType;
}
void DemodulatorMgr::setLastDemodulatorType(int lastDemodType) {
void DemodulatorMgr::setLastDemodulatorType(std::string lastDemodType) {
this->lastDemodType = lastDemodType;
}
@ -224,15 +223,6 @@ void DemodulatorMgr::setLastSquelchEnabled(bool lastSquelchEnabled) {
this->lastSquelchEnabled = lastSquelchEnabled;
}
bool DemodulatorMgr::isLastStereo() const {
return lastStereo;
}
void DemodulatorMgr::setLastStereo(bool lastStereo) {
this->lastStereo = lastStereo;
}
bool DemodulatorMgr::isLastMuted() const {
return lastMuted;
}

View File

@ -25,8 +25,8 @@ public:
int getLastBandwidth() const;
void setLastBandwidth(int lastBandwidth);
int getLastDemodulatorType() const;
void setLastDemodulatorType(int lastDemodType);
std::string getLastDemodulatorType() const;
void setLastDemodulatorType(std::string lastDemodType);
int getLastDemodulatorCons() const;
void setLastDemodulatorCons(int lastDemodCons);
@ -39,10 +39,7 @@ public:
bool isLastSquelchEnabled() const;
void setLastSquelchEnabled(bool lastSquelchEnabled);
bool isLastStereo() const;
void setLastStereo(bool lastStereo);
bool isLastMuted() const;
void setLastMuted(bool lastMuted);
@ -57,11 +54,11 @@ private:
DemodulatorInstance *activeVisualDemodulator;
int lastBandwidth;
int lastDemodType;
std::string lastDemodType;
bool lastDemodLock;
int lastDemodCons;
bool lastSquelchEnabled;
float lastSquelch;
float lastGain;
bool lastStereo, lastMuted;
bool lastMuted;
};

View File

@ -8,7 +8,7 @@
#include "DemodulatorPreThread.h"
#include "CubicSDR.h"
DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(1), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL)
DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL), threadQueueNotify(NULL), commandQueue(NULL)
{
initialized.store(false);
@ -24,50 +24,14 @@ DemodulatorPreThread::DemodulatorPreThread() : IOThread(), iqResampler(NULL), iq
}
void DemodulatorPreThread::initialize() {
initialized = false;
iqResampleRatio = (double) (params.bandwidth) / (double) params.sampleRate;
audioResampleRatio = (double) (params.audioSampleRate) / (double) params.bandwidth;
float As = 120.0f; // stop-band attenuation [dB]
float As = 60.0f; // stop-band attenuation [dB]
iqResampler = msresamp_crcf_create(iqResampleRatio, As);
audioResampler = msresamp_rrrf_create(audioResampleRatio, As);
stereoResampler = msresamp_rrrf_create(audioResampleRatio, As);
// Stereo filters / shifters
double firStereoCutoff = ((double) 16000 / (double) params.audioSampleRate);
float ft = ((double) 1000 / (double) params.audioSampleRate); // filter transition
float mu = 0.0f; // fractional timing offset
if (firStereoCutoff < 0) {
firStereoCutoff = 0;
}
if (firStereoCutoff > 0.5) {
firStereoCutoff = 0.5;
}
unsigned int h_len = estimate_req_filter_len(ft, As);
float *h = new float[h_len];
liquid_firdes_kaiser(h_len, firStereoCutoff, As, mu, h);
firStereoLeft = firfilt_rrrf_create(h, h_len);
firStereoRight = firfilt_rrrf_create(h, h_len);
// stereo pilot filter
float bw = params.bandwidth;
if (bw < 100000.0) {
bw = 100000.0;
}
unsigned int order = 5; // filter order
float f0 = ((double) 19000 / bw);
float fc = ((double) 19500 / bw);
float Ap = 1.0f;
As = 60.0f;
iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As);
initialized = true;
initialized.store(true);
lastParams = params;
}
@ -88,8 +52,6 @@ void DemodulatorPreThread::run() {
std::cout << "Demodulator preprocessor thread started.." << std::endl;
t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread);
ReBuffer<DemodulatorThreadPostIQData> buffers;
iqInputQueue = (DemodulatorThreadInputQueue*)getInputQueue("IQDataInput");
@ -99,9 +61,10 @@ void DemodulatorPreThread::run() {
std::vector<liquid_float_complex> in_buf_data;
std::vector<liquid_float_complex> out_buf_data;
// liquid_float_complex carrySample; // Keep the stream count even to simplify some demod operations
// bool carrySampleFlag = false;
setDemodType(params.demodType);
t_Worker = new std::thread(&DemodulatorWorkerThread::threadMain, workerThread);
while (!terminated) {
DemodulatorThreadIQData *inp;
iqInputQueue->pop(inp);
@ -218,40 +181,11 @@ void DemodulatorPreThread::run() {
msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten);
resamp->setRefCount(1);
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
// bool uneven = (numWritten % 2 != 0);
// if (!carrySampleFlag && !uneven) {
// resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
// carrySampleFlag = false;
// } else if (!carrySampleFlag && uneven) {
// resamp->data.assign(resampledData.begin(), resampledData.begin() + (numWritten-1));
// carrySample = resampledData.back();
// carrySampleFlag = true;
// } else if (carrySampleFlag && uneven) {
// resamp->data.resize(numWritten+1);
// resamp->data[0] = carrySample;
// memcpy(&resamp->data[1],&resampledData[0],sizeof(liquid_float_complex)*numWritten);
// carrySampleFlag = false;
// } else if (carrySampleFlag && !uneven) {
// resamp->data.resize(numWritten);
// resamp->data[0] = carrySample;
// memcpy(&resamp->data[1],&resampledData[0],sizeof(liquid_float_complex)*(numWritten-1));
// carrySample = resampledData.back();
// carrySampleFlag = true;
// }
resamp->audioResampleRatio = audioResampleRatio;
resamp->audioResampler = audioResampler;
resamp->audioSampleRate = params.audioSampleRate;
resamp->stereoResampler = stereoResampler;
resamp->firStereoLeft = firStereoLeft;
resamp->firStereoRight = firStereoRight;
resamp->iirStereoPilot = iirStereoPilot;
resamp->modemType = demodType;
resamp->modem = cModem;
resamp->modemKit = cModemKit;
resamp->sampleRate = params.bandwidth;
iqOutputQueue->push(resamp);
@ -266,35 +200,23 @@ void DemodulatorPreThread::run() {
switch (result.cmd) {
case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS:
msresamp_crcf_destroy(iqResampler);
if (result.iqResampler) {
if (iqResampler) {
msresamp_crcf_destroy(iqResampler);
}
iqResampler = result.iqResampler;
iqResampleRatio = result.iqResampleRatio;
}
if (result.firStereoLeft) {
firStereoLeft = result.firStereoLeft;
}
if (result.firStereoRight) {
firStereoRight = result.firStereoRight;
}
if (result.iirStereoPilot) {
iirStereoPilot = result.iirStereoPilot;
if (result.modem != nullptr) {
cModem = result.modem;
}
if (result.audioResampler) {
audioResampler = result.audioResampler;
audioResampleRatio = result.audioResamplerRatio;
stereoResampler = result.stereoResampler;
if (result.modemKit != nullptr) {
cModemKit = result.modemKit;
}
if (result.audioSampleRate) {
params.audioSampleRate = result.audioSampleRate;
}
if (result.bandwidth) {
params.bandwidth = result.bandwidth;
}
@ -302,6 +224,12 @@ void DemodulatorPreThread::run() {
if (result.sampleRate) {
params.sampleRate = result.sampleRate;
}
if (result.modemType != "") {
demodType = result.modemType;
params.demodType = result.modemType;
demodTypeChanged.store(false);
}
break;
default:
break;
@ -318,6 +246,31 @@ void DemodulatorPreThread::run() {
std::cout << "Demodulator preprocessor thread done." << std::endl;
}
DemodulatorThreadParameters &DemodulatorPreThread::getParams() {
return params;
}
void DemodulatorPreThread::setParams(DemodulatorThreadParameters &params_in) {
params = params_in;
}
void DemodulatorPreThread::setDemodType(std::string demodType) {
this->newDemodType = demodType;
DemodulatorWorkerThreadCommand command(DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD);
command.demodType = demodType;
command.bandwidth = params.bandwidth;
command.audioSampleRate = params.audioSampleRate;
workerQueue->push(command);
demodTypeChanged.store(true);
}
std::string DemodulatorPreThread::getDemodType() {
if (demodTypeChanged.load()) {
return newDemodType;
}
return demodType;
}
void DemodulatorPreThread::terminate() {
terminated = true;
DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue
@ -331,3 +284,12 @@ void DemodulatorPreThread::terminate() {
delete workerResults;
delete workerQueue;
}
Modem *DemodulatorPreThread::getModem() {
return cModem;
}
ModemKit *DemodulatorPreThread::getModemKit() {
return cModemKit;
}

View File

@ -15,35 +15,25 @@ public:
void run();
DemodulatorThreadParameters &getParams() {
return params;
}
void setParams(DemodulatorThreadParameters &params_in) {
params = params_in;
}
DemodulatorThreadParameters &getParams();
void setParams(DemodulatorThreadParameters &params_in);
void setDemodType(std::string demodType);
std::string getDemodType();
void initialize();
void terminate();
#ifdef __APPLE__
static void *pthread_helper(void *context) {
return ((DemodulatorPreThread *) context)->threadMain();
}
#endif
Modem *getModem();
ModemKit *getModemKit();
protected:
msresamp_crcf iqResampler;
double iqResampleRatio;
std::vector<liquid_float_complex> resampledData;
msresamp_rrrf audioResampler;
msresamp_rrrf stereoResampler;
double audioResampleRatio;
firfilt_rrrf firStereoLeft;
firfilt_rrrf firStereoRight;
iirfilt_crcf iirStereoPilot;
Modem *cModem;
ModemKit *cModemKit;
DemodulatorThreadParameters params;
DemodulatorThreadParameters lastParams;
@ -52,6 +42,9 @@ protected:
int shiftFrequency;
std::atomic_bool initialized;
std::atomic_bool demodTypeChanged;
std::string demodType;
std::string newDemodType;
DemodulatorWorkerThread *workerThread;
std::thread *t_Worker;

File diff suppressed because it is too large Load Diff

View File

@ -5,25 +5,24 @@
#include "DemodDefs.h"
#include "AudioThread.h"
#include "Modem.h"
typedef ThreadQueue<AudioThreadInput *> DemodulatorThreadOutputQueue;
#define DEMOD_VIS_SIZE 2048
class DemodulatorInstance;
class DemodulatorThread : public IOThread {
public:
DemodulatorThread();
DemodulatorThread(DemodulatorInstance *parent);
~DemodulatorThread();
void onBindOutput(std::string name, ThreadQueueBase *threadQueue);
void run();
void terminate();
void setStereo(bool state);
bool isStereo();
void setAGC(bool state);
bool getAGC();
@ -34,126 +33,25 @@ public:
void setSquelchLevel(float signal_level_in);
float getSquelchLevel();
void setDemodulatorType(int demod_type_in);
int getDemodulatorType();
void setDemodulatorLock(bool demod_lock_in);
int getDemodulatorLock();
void setDemodulatorCons(int demod_cons_in);
int getDemodulatorCons();
#ifdef __APPLE__
static void *pthread_helper(void *context) {
return ((DemodulatorThread *) context)->threadMain();
}
#endif
protected:
DemodulatorInstance *demodInstance;
ReBuffer<AudioThreadInput> outputBuffers;
std::vector<liquid_float_complex> agcData;
std::vector<float> agcAMData;
std::vector<float> demodOutputData;
std::vector<float> demodStereoData;
std::vector<float> resampledOutputData;
std::vector<float> resampledStereoData;
std::vector<unsigned int> demodOutputDataDigital;
//std::vector<unsigned int> demodOutputDataDigitalTest;
//std::vector<unsigned char> demodOutputSoftbits;
//std::vector<unsigned char> demodOutputSoftbitsTest;
freqdem demodFM;
ampmodem demodAM;
ampmodem demodAM_DSB_CSP;
ampmodem demodAM_DSB;
ampmodem demodAM_LSB;
ampmodem demodAM_USB;
modem demodASK;
modem demodASK2;
modem demodASK4;
modem demodASK8;
modem demodASK16;
modem demodASK32;
modem demodASK64;
modem demodASK128;
modem demodASK256;
modem demodAPSK;
modem demodAPSK4;
modem demodAPSK8;
modem demodAPSK16;
modem demodAPSK32;
modem demodAPSK64;
modem demodAPSK128;
modem demodAPSK256;
modem demodBPSK;
modem demodDPSK;
modem demodDPSK2;
modem demodDPSK4;
modem demodDPSK8;
modem demodDPSK16;
modem demodDPSK32;
modem demodDPSK64;
modem demodDPSK128;
modem demodDPSK256;
modem demodPSK;
modem demodPSK2;
modem demodPSK4;
modem demodPSK8;
modem demodPSK16;
modem demodPSK32;
modem demodPSK64;
modem demodPSK128;
modem demodPSK256;
modem demodOOK;
modem demodSQAM;
modem demodSQAM32;
modem demodSQAM128;
modem demodST;
modem demodQAM;
modem demodQAM4;
modem demodQAM8;
modem demodQAM16;
modem demodQAM32;
modem demodQAM64;
modem demodQAM128;
modem demodQAM256;
modem demodQPSK;
agc_crcf iqAutoGain;
float amOutputCeil;
float amOutputCeilMA;
float amOutputCeilMAA;
std::atomic_bool stereo;
std::atomic_bool muted;
std::atomic_bool agcEnabled;
std::atomic_int demodulatorType;
std::atomic_int demodulatorCons;
int audioSampleRate;
std::atomic<float> squelchLevel;
std::atomic<float> signalLevel;
bool squelchEnabled;
bool currentDemodLock;
int currentDemodCons;
void updateDemodulatorCons(int Cons);
void updateDemodulatorLock(modem demod, float sensitivity);
Modem *cModem;
ModemKit *cModemKit;
DemodulatorThreadPostInputQueue* iqInputQueue;
AudioThreadInputQueue *audioOutputQueue;
DemodulatorThreadOutputQueue* audioVisOutputQueue;

View File

@ -3,7 +3,7 @@
#include <vector>
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
commandQueue(NULL), resultQueue(NULL) {
commandQueue(NULL), resultQueue(NULL), cModem(nullptr), cModemKit(nullptr) {
}
DemodulatorWorkerThread::~DemodulatorWorkerThread() {
@ -18,7 +18,8 @@ void DemodulatorWorkerThread::run() {
while (!terminated) {
bool filterChanged = false;
DemodulatorWorkerThreadCommand filterCommand;
bool makeDemod = false;
DemodulatorWorkerThreadCommand filterCommand, demodCommand;
DemodulatorWorkerThreadCommand command;
bool done = false;
@ -29,6 +30,10 @@ void DemodulatorWorkerThread::run() {
filterChanged = true;
filterCommand = command;
break;
case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD:
makeDemod = true;
demodCommand = command;
break;
default:
break;
}
@ -36,7 +41,7 @@ void DemodulatorWorkerThread::run() {
}
if (filterChanged && !terminated) {
if ((makeDemod || filterChanged) && !terminated) {
DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS);
float As = 60.0f; // stop-band attenuation [dB]
@ -46,45 +51,22 @@ void DemodulatorWorkerThread::run() {
result.iqResampler = msresamp_crcf_create(result.iqResampleRatio, As);
}
if (filterCommand.bandwidth && filterCommand.audioSampleRate) {
result.audioResamplerRatio = (double) (filterCommand.audioSampleRate) / (double) filterCommand.bandwidth;
result.audioResampler = msresamp_rrrf_create(result.audioResamplerRatio, As);
result.stereoResampler = msresamp_rrrf_create(result.audioResamplerRatio, As);
result.audioSampleRate = filterCommand.audioSampleRate;
// Stereo filters / shifters
double firStereoCutoff = ((double) 16000 / (double) filterCommand.audioSampleRate);
float ft = ((double) 1000 / (double) filterCommand.audioSampleRate); // filter transition
float mu = 0.0f; // fractional timing offset
if (firStereoCutoff < 0) {
firStereoCutoff = 0;
}
if (firStereoCutoff > 0.5) {
firStereoCutoff = 0.5;
}
unsigned int h_len = estimate_req_filter_len(ft, As);
float *h = new float[h_len];
liquid_firdes_kaiser(h_len, firStereoCutoff, As, mu, h);
result.firStereoLeft = firfilt_rrrf_create(h, h_len);
result.firStereoRight = firfilt_rrrf_create(h, h_len);
float bw = filterCommand.bandwidth;
if (bw < 100000.0) {
bw = 100000.0;
}
// stereo pilot filter
unsigned int order = 5; // filter order
float f0 = ((double) 19000 / bw);
float fc = ((double) 19500 / bw);
float Ap = 1.0f;
As = 60.0f;
result.iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As);
if (makeDemod) {
cModem = Modem::makeModem(demodCommand.demodType);
cModemType = demodCommand.demodType;
}
result.modem = cModem;
if (makeDemod && demodCommand.bandwidth && demodCommand.audioSampleRate) {
if (cModem != nullptr) {
cModemKit = cModem->buildKit(demodCommand.bandwidth, demodCommand.audioSampleRate);
} else {
cModemKit = nullptr;
}
} else if (makeDemod) {
cModemKit = nullptr;
}
result.modemKit = cModemKit;
if (filterCommand.bandwidth) {
result.bandwidth = filterCommand.bandwidth;
@ -94,6 +76,8 @@ void DemodulatorWorkerThread::run() {
result.sampleRate = filterCommand.sampleRate;
}
result.modemType = cModemType;
resultQueue->push(result);
}

View File

@ -7,6 +7,7 @@
#include "AudioThread.h"
#include "ThreadQueue.h"
#include "CubicSDRDefs.h"
#include "Modem.h"
class DemodulatorWorkerThreadResult {
public:
@ -15,8 +16,7 @@ public:
};
DemodulatorWorkerThreadResult() :
cmd(DEMOD_WORKER_THREAD_RESULT_NULL), iqResampler(NULL), iqResampleRatio(0), audioResampler(NULL), stereoResampler(NULL), audioResamplerRatio(
0), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL), sampleRate(0), bandwidth(0), audioSampleRate(0) {
cmd(DEMOD_WORKER_THREAD_RESULT_NULL), iqResampler(nullptr), iqResampleRatio(0), sampleRate(0), bandwidth(0), modemKit(nullptr), modemType("") {
}
@ -29,33 +29,29 @@ public:
msresamp_crcf iqResampler;
double iqResampleRatio;
msresamp_rrrf audioResampler;
msresamp_rrrf stereoResampler;
double audioResamplerRatio;
firfilt_rrrf firStereoLeft;
firfilt_rrrf firStereoRight;
iirfilt_crcf iirStereoPilot;
DemodulatorThread *demodThread;
long long sampleRate;
unsigned int bandwidth;
unsigned int audioSampleRate;
Modem *modem;
ModemKit *modemKit;
std::string modemType;
};
class DemodulatorWorkerThreadCommand {
public:
enum DemodulatorThreadCommandEnum {
DEMOD_WORKER_THREAD_CMD_NULL, DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS
DEMOD_WORKER_THREAD_CMD_NULL, DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS, DEMOD_WORKER_THREAD_CMD_MAKE_DEMOD
};
DemodulatorWorkerThreadCommand() :
cmd(DEMOD_WORKER_THREAD_CMD_NULL), frequency(0), sampleRate(0), bandwidth(0), audioSampleRate(0) {
cmd(DEMOD_WORKER_THREAD_CMD_NULL), frequency(0), sampleRate(0), bandwidth(0), audioSampleRate(0), demodType("") {
}
DemodulatorWorkerThreadCommand(DemodulatorThreadCommandEnum cmd) :
cmd(cmd), frequency(0), sampleRate(0), bandwidth(0), audioSampleRate(0) {
cmd(cmd), frequency(0), sampleRate(0), bandwidth(0), audioSampleRate(0), demodType("") {
}
@ -65,6 +61,7 @@ public:
long long sampleRate;
unsigned int bandwidth;
unsigned int audioSampleRate;
std::string demodType;
};
typedef ThreadQueue<DemodulatorWorkerThreadCommand> DemodulatorThreadWorkerCommandQueue;
@ -92,4 +89,7 @@ protected:
DemodulatorThreadWorkerCommandQueue *commandQueue;
DemodulatorThreadWorkerResultQueue *resultQueue;
Modem *cModem;
ModemKit *cModemKit;
std::string cModemType;
};

View File

@ -0,0 +1,27 @@
#include "Modem.h"
ModemFactoryList Modem::modemFactories;
void Modem::addModemFactory(Modem *factorySingle) {
modemFactories[factorySingle->getName()] = factorySingle;
}
ModemFactoryList Modem::getFactories() {
return modemFactories;
}
Modem *Modem::makeModem(std::string modemType) {
if (modemFactories.find(modemType) != modemFactories.end()) {
return modemFactories[modemType]->factory();
}
return nullptr;
}
Modem::Modem() {
}
Modem::~Modem() {
}

52
src/modules/modem/Modem.h Normal file
View File

@ -0,0 +1,52 @@
#pragma once
#include "liquid/liquid.h"
#include "IOThread.h"
#include "AudioThread.h"
#include <cmath>
class ModemKit {
public:
ModemKit() : sampleRate(0), audioSampleRate(0) {
}
long long sampleRate;
int audioSampleRate;
};
class ModemIQData: public ReferenceCounter {
public:
std::vector<liquid_float_complex> data;
long long sampleRate;
ModemIQData() : sampleRate(0) {
}
~ModemIQData() {
std::lock_guard < std::mutex > lock(m_mutex);
}
};
class Modem;
typedef std::map<std::string,Modem *> ModemFactoryList;
class Modem {
public:
static void addModemFactory(Modem *factorySingle);
static ModemFactoryList getFactories();
static Modem *makeModem(std::string modemType);
virtual std::string getType() = 0;
virtual std::string getName() = 0;
virtual Modem *factory() = 0;
Modem();
virtual ~Modem();
virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate) = 0;
virtual void disposeKit(ModemKit *kit) = 0;
virtual void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) = 0;
private:
static ModemFactoryList modemFactories;
};

View File

@ -0,0 +1,91 @@
#include "ModemAnalog.h"
ModemAnalog::ModemAnalog() : aOutputCeil(1), aOutputCeilMA(1), aOutputCeilMAA(1) {
}
std::string ModemAnalog::getType() {
return "analog";
}
ModemKit *ModemAnalog::buildKit(long long sampleRate, int audioSampleRate) {
ModemKitAnalog *akit = new ModemKitAnalog;
// stop-band attenuation [dB]
float As = 60.0f;
akit->sampleRate = sampleRate;
akit->audioSampleRate = audioSampleRate;
akit->audioResampleRatio = double(audioSampleRate) / double(sampleRate);
akit->audioResampler = msresamp_rrrf_create(akit->audioResampleRatio, As);
return akit;
}
void ModemAnalog::disposeKit(ModemKit *kit) {
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
msresamp_rrrf_destroy(akit->audioResampler);
delete akit;
}
void ModemAnalog::initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input) {
bufSize = input->data.size();
if (!bufSize) {
return;
}
double audio_resample_ratio = akit->audioResampleRatio;
int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
if (demodOutputData.size() != bufSize) {
if (demodOutputData.capacity() < bufSize) {
demodOutputData.reserve(bufSize);
}
demodOutputData.resize(bufSize);
}
if (resampledOutputData.size() != audio_out_size) {
if (resampledOutputData.capacity() < audio_out_size) {
resampledOutputData.reserve(audio_out_size);
}
resampledOutputData.resize(audio_out_size);
}
}
void ModemAnalog::buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain) {
unsigned int numAudioWritten;
if (autoGain) {
aOutputCeilMA = aOutputCeilMA + (aOutputCeil - aOutputCeilMA) * 0.025;
aOutputCeilMAA = aOutputCeilMAA + (aOutputCeilMA - aOutputCeilMAA) * 0.025;
aOutputCeil = 0;
for (int i = 0; i < bufSize; i++) {
if (demodOutputData[i] > aOutputCeil) {
aOutputCeil = demodOutputData[i];
}
}
float gain = 0.5 / aOutputCeilMAA;
for (int i = 0; i < bufSize; i++) {
demodOutputData[i] *= gain;
}
}
msresamp_rrrf_execute(akit->audioResampler, &demodOutputData[0], demodOutputData.size(), &resampledOutputData[0], &numAudioWritten);
audioOut->channels = 1;
audioOut->sampleRate = akit->audioSampleRate;
audioOut->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten);
}
std::vector<float> *ModemAnalog::getDemodOutputData() {
return &demodOutputData;
}
std::vector<float> *ModemAnalog::getResampledOutputData() {
return &resampledOutputData;
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "Modem.h"
class ModemKitAnalog : public ModemKit {
public:
ModemKitAnalog() : ModemKit(), audioResampler(nullptr), audioResampleRatio(0) {
};
msresamp_rrrf audioResampler;
double audioResampleRatio;
};
class ModemAnalog : public Modem {
public:
ModemAnalog();
std::string getType();
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
void disposeKit(ModemKit *kit);
void initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input);
void buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain);
std::vector<float> *getDemodOutputData();
std::vector<float> *getResampledOutputData();
protected:
int bufSize;
std::vector<float> demodOutputData;
std::vector<float> resampledOutputData;
float aOutputCeil;
float aOutputCeilMA;
float aOutputCeilMAA;
};

View File

@ -0,0 +1,71 @@
#include "ModemDigital.h"
ModemDigital::ModemDigital() {
}
std::string ModemDigital::getType() {
return "digital";
}
ModemKit *ModemDigital::buildKit(long long sampleRate, int audioSampleRate) {
ModemKitDigital *dkit = new ModemKitDigital;
dkit->sampleRate = sampleRate;
dkit->audioSampleRate = audioSampleRate;
return dkit;
}
void ModemDigital::disposeKit(ModemKit *kit) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
delete dkit;
}
void ModemDigital::setDemodulatorLock(bool demod_lock_in) {
currentDemodLock.store(demod_lock_in);
}
int ModemDigital::getDemodulatorLock() {
return currentDemodLock.load();
}
void ModemDigital::setDemodulatorCons(int demod_cons_in) {
demodulatorCons.store(demod_cons_in);
}
int ModemDigital::getDemodulatorCons() {
return currentDemodCons.load();
}
void ModemDigital::updateDemodulatorLock(modem mod, float sensitivity) {
setDemodulatorLock(modem_get_demodulator_evm(mod) <= sensitivity);
}
void ModemDigital::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
}
}
void ModemDigital::digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input) {
int bufSize = input->data.size();
if (demodOutputDataDigital.size() != bufSize) {
if (demodOutputDataDigital.capacity() < bufSize) {
demodOutputDataDigital.reserve(bufSize);
}
demodOutputDataDigital.resize(bufSize);
}
if (demodulatorCons.load() != currentDemodCons.load()) {
updateDemodulatorCons(demodulatorCons.load());
currentDemodLock.store(false);
}
}
void ModemDigital::digitalFinish(ModemKitDigital *kit, modem mod) {
demodOutputDataDigital.empty();
}

View File

@ -0,0 +1,39 @@
#pragma once
#include "Modem.h"
class ModemKitDigital : public ModemKit {
public:
ModemKitDigital() : ModemKit() {
};
};
class ModemDigital : public Modem {
public:
ModemDigital();
std::string getType();
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
void disposeKit(ModemKit *kit);
void digitalStart(ModemKitDigital *kit, modem mod, ModemIQData *input);
void digitalFinish(ModemKitDigital *kit, modem mod);
virtual void setDemodulatorLock(bool demod_lock_in);
virtual int getDemodulatorLock();
virtual void setDemodulatorCons(int demod_cons_in);
virtual int getDemodulatorCons();
virtual void updateDemodulatorCons(int cons);
virtual void updateDemodulatorLock(modem mod, float sensitivity);
protected:
std::vector<unsigned int> demodOutputDataDigital;
std::atomic_int demodulatorCons;
std::atomic_bool currentDemodLock;
std::atomic_int currentDemodCons;
// std::vector<unsigned int> demodOutputDataDigitalTest;
// std::vector<unsigned char> demodOutputSoftbits;
// std::vector<unsigned char> demodOutputSoftbitsTest;
};

View File

@ -0,0 +1,30 @@
#include "ModemAM.h"
ModemAM::ModemAM() {
demodAM = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
}
Modem *ModemAM::factory() {
return new ModemAM;
}
std::string ModemAM::getName() {
return "AM";
}
void ModemAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitAnalog *amkit = (ModemKitAnalog *)kit;
initOutputBuffers(amkit,input);
if (!bufSize) {
input->decRefCount();
return;
}
for (int i = 0; i < bufSize; i++) {
ampmodem_demodulate(demodAM, input->data[i], &demodOutputData[i]);
}
buildAudioOutput(amkit,audioOut,true);
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "Modem.h"
#include "ModemAnalog.h"
class ModemAM : public ModemAnalog {
public:
ModemAM();
std::string getName();
Modem *factory();
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
ampmodem demodAM;
};

View File

@ -0,0 +1,30 @@
#include "ModemDSB.h"
ModemDSB::ModemDSB() {
demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1);
}
Modem *ModemDSB::factory() {
return new ModemDSB;
}
std::string ModemDSB::getName() {
return "DSB";
}
void ModemDSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitAnalog *amkit = (ModemKitAnalog *)kit;
initOutputBuffers(amkit, input);
if (!bufSize) {
input->decRefCount();
return;
}
for (int i = 0; i < bufSize; i++) {
ampmodem_demodulate(demodAM_DSB, input->data[i], &demodOutputData[i]);
}
buildAudioOutput(amkit, audioOut, true);
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "Modem.h"
#include "ModemAnalog.h"
class ModemDSB : public ModemAnalog {
public:
ModemDSB();
std::string getName();
Modem *factory();
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
ampmodem demodAM_DSB;
};

View File

@ -0,0 +1,28 @@
#include "ModemFM.h"
ModemFM::ModemFM() {
demodFM = freqdem_create(0.5);
}
Modem *ModemFM::factory() {
return new ModemFM;
}
std::string ModemFM::getName() {
return "FM";
}
void ModemFM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitAnalog *fmkit = (ModemKitAnalog *)kit;
initOutputBuffers(fmkit, input);
if (!bufSize) {
input->decRefCount();
return;
}
freqdem_demodulate_block(demodFM, &input->data[0], bufSize, &demodOutputData[0]);
buildAudioOutput(fmkit, audioOut, false);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "Modem.h"
#include "ModemAnalog.h"
class ModemFM : public ModemAnalog {
public:
ModemFM();
std::string getName();
Modem *factory();
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
freqdem demodFM;
};

View File

@ -0,0 +1,186 @@
#include "ModemFMStereo.h"
ModemFMStereo::ModemFMStereo() {
demodFM = freqdem_create(0.5);
firStereoR2C = firhilbf_create(5, 60.0f);
firStereoC2R = firhilbf_create(5, 60.0f);
stereoPilot = nco_crcf_create(LIQUID_VCO);
nco_crcf_reset(stereoPilot);
nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f);
}
ModemFMStereo::~ModemFMStereo() {
firhilbf_destroy(firStereoR2C);
firhilbf_destroy(firStereoC2R);
nco_crcf_destroy(stereoPilot);
}
std::string ModemFMStereo::getType() {
return "analog";
}
std::string ModemFMStereo::getName() {
return "FMS";
}
Modem *ModemFMStereo::factory() {
return new ModemFMStereo;
}
ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) {
ModemKitFMStereo *kit = new ModemKitFMStereo;
kit->audioResampleRatio = double(audioSampleRate) / double(sampleRate);
float As = 60.0f; // stop-band attenuation [dB]
kit->audioResampler = msresamp_rrrf_create(kit->audioResampleRatio, As);
kit->stereoResampler = msresamp_rrrf_create(kit->audioResampleRatio, As);
// Stereo filters / shifters
double firStereoCutoff = 16000.0 / double(audioSampleRate);
// filter transition
float ft = 1000.0 / double(audioSampleRate);
// fractional timing offset
float mu = 0.0f;
if (firStereoCutoff < 0) {
firStereoCutoff = 0;
}
if (firStereoCutoff > 0.5) {
firStereoCutoff = 0.5;
}
unsigned int h_len = estimate_req_filter_len(ft, As);
float *h = new float[h_len];
liquid_firdes_kaiser(h_len, firStereoCutoff, As, mu, h);
kit->firStereoLeft = firfilt_rrrf_create(h, h_len);
kit->firStereoRight = firfilt_rrrf_create(h, h_len);
// stereo pilot filter
float bw = sampleRate;
if (bw < 100000.0) {
bw = 100000.0;
}
unsigned int order = 5; // filter order
float f0 = ((double) 19000 / bw);
float fc = ((double) 19500 / bw);
float Ap = 1.0f;
kit->iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As);
return kit;
}
void ModemFMStereo::disposeKit(ModemKit *kit) {
ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit;
msresamp_rrrf_destroy(fmkit->audioResampler);
msresamp_rrrf_destroy(fmkit->stereoResampler);
firfilt_rrrf_destroy(fmkit->firStereoLeft);
firfilt_rrrf_destroy(fmkit->firStereoRight);
}
void ModemFMStereo::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit;
int bufSize = input->data.size();
liquid_float_complex u, v, w, x, y;
double audio_resample_ratio = fmkit->audioResampleRatio;
if (demodOutputData.size() != bufSize) {
if (demodOutputData.capacity() < bufSize) {
demodOutputData.reserve(bufSize);
}
demodOutputData.resize(bufSize);
}
int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
freqdem_demodulate_block(demodFM, &input->data[0], bufSize, &demodOutputData[0]);
if (resampledOutputData.size() != audio_out_size) {
if (resampledOutputData.capacity() < audio_out_size) {
resampledOutputData.reserve(audio_out_size);
}
resampledOutputData.resize(audio_out_size);
}
unsigned int numAudioWritten;
msresamp_rrrf_execute(fmkit->audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten);
if (demodStereoData.size() != bufSize) {
if (demodStereoData.capacity() < bufSize) {
demodStereoData.reserve(bufSize);
}
demodStereoData.resize(bufSize);
}
float phase_error = 0;
for (int i = 0; i < bufSize; i++) {
// real -> complex
firhilbf_r2c_execute(firStereoR2C, demodOutputData[i], &x);
// 19khz pilot band-pass
iirfilt_crcf_execute(fmkit->iirStereoPilot, x, &v);
nco_crcf_cexpf(stereoPilot, &w);
w.imag = -w.imag; // conjf(w)
// multiply u = v * conjf(w)
u.real = v.real * w.real - v.imag * w.imag;
u.imag = v.real * w.imag + v.imag * w.real;
// cargf(u)
phase_error = atan2f(u.imag,u.real);
// step pll
nco_crcf_pll_step(stereoPilot, phase_error);
nco_crcf_step(stereoPilot);
// 38khz down-mix
nco_crcf_mix_down(stereoPilot, x, &y);
nco_crcf_mix_down(stereoPilot, y, &x);
// complex -> real
firhilbf_c2r_execute(firStereoC2R, x, &demodStereoData[i]);
}
// std::cout << "[PLL] phase error: " << phase_error;
// std::cout << " freq:" << (((nco_crcf_get_frequency(stereoPilot) / (2.0 * M_PI)) * inp->sampleRate)) << std::endl;
if (audio_out_size != resampledStereoData.size()) {
if (resampledStereoData.capacity() < audio_out_size) {
resampledStereoData.reserve(audio_out_size);
}
resampledStereoData.resize(audio_out_size);
}
msresamp_rrrf_execute(fmkit->stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
audioOut->channels = 2;
if (audioOut->data.capacity() < (numAudioWritten * 2)) {
audioOut->data.reserve(numAudioWritten * 2);
}
audioOut->data.resize(numAudioWritten * 2);
for (int i = 0; i < numAudioWritten; i++) {
float l, r;
firfilt_rrrf_push(fmkit->firStereoLeft, 0.568 * (resampledOutputData[i] - (resampledStereoData[i])));
firfilt_rrrf_execute(fmkit->firStereoLeft, &l);
firfilt_rrrf_push(fmkit->firStereoRight, 0.568 * (resampledOutputData[i] + (resampledStereoData[i])));
firfilt_rrrf_execute(fmkit->firStereoRight, &r);
audioOut->data[i * 2] = l;
audioOut->data[i * 2 + 1] = r;
}
}

View File

@ -0,0 +1,41 @@
#pragma once
#include "Modem.h"
class ModemKitFMStereo: public ModemKit {
public:
ModemKitFMStereo() : audioResampler(nullptr), stereoResampler(nullptr), audioResampleRatio(0), firStereoLeft(nullptr), firStereoRight(nullptr), iirStereoPilot(nullptr) {
}
msresamp_rrrf audioResampler;
msresamp_rrrf stereoResampler;
double audioResampleRatio;
firfilt_rrrf firStereoLeft;
firfilt_rrrf firStereoRight;
iirfilt_crcf iirStereoPilot;
};
class ModemFMStereo : public Modem {
public:
ModemFMStereo();
~ModemFMStereo();
std::string getType();
std::string getName();
Modem *factory();
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
void disposeKit(ModemKit *kit);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
std::vector<float> demodOutputData;
std::vector<float> demodStereoData;
std::vector<float> resampledOutputData;
std::vector<float> resampledStereoData;
freqdem demodFM;
firhilbf firStereoR2C;
firhilbf firStereoC2R;
nco_crcf stereoPilot;
};

View File

@ -0,0 +1,46 @@
#include "ModemIQ.h"
ModemIQ::ModemIQ() {
}
Modem *ModemIQ::factory() {
return new ModemIQ;
}
ModemKit *ModemIQ::buildKit(long long sampleRate, int audioSampleRate) {
ModemKit *kit = new ModemKit;
return kit;
}
std::string ModemIQ::getType() {
return "analog";
}
std::string ModemIQ::getName() {
return "I/Q";
}
void ModemIQ::disposeKit(ModemKit *kit) {
delete kit;
}
void ModemIQ::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
int bufSize = input->data.size();
if (!bufSize) {
input->decRefCount();
return;
}
audioOut->channels = 2;
if (audioOut->data.capacity() < (bufSize * 2)) {
audioOut->data.reserve(bufSize * 2);
}
audioOut->data.resize(bufSize * 2);
for (int i = 0; i < bufSize; i++) {
audioOut->data[i * 2] = input->data[i].imag;
audioOut->data[i * 2 + 1] = input->data[i].real;
}
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "Modem.h"
class ModemIQ : public Modem {
public:
ModemIQ();
std::string getType();
std::string getName();
Modem *factory();
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
void disposeKit(ModemKit *kit);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
};

View File

@ -0,0 +1,39 @@
#include "ModemLSB.h"
ModemLSB::ModemLSB() {
// half band filter used for side-band elimination
ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1);
}
Modem *ModemLSB::factory() {
return new ModemLSB;
}
std::string ModemLSB::getName() {
return "LSB";
}
ModemLSB::~ModemLSB() {
resamp2_crcf_destroy(ssbFilt);
ampmodem_destroy(demodAM_LSB);
}
void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
initOutputBuffers(akit,input);
if (!bufSize) {
input->decRefCount();
return;
}
liquid_float_complex x, y;
for (int i = 0; i < bufSize; i++) { // Reject upper band
resamp2_crcf_filter_execute(ssbFilt,input->data[i],&x,&y);
ampmodem_demodulate(demodAM_LSB, x, &demodOutputData[i]);
}
buildAudioOutput(akit, audioOut, true);
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "Modem.h"
#include "ModemAnalog.h"
class ModemLSB : public ModemAnalog {
public:
ModemLSB();
~ModemLSB();
std::string getName();
Modem *factory();
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
resamp2_crcf ssbFilt;
ampmodem demodAM_LSB;
};

View File

@ -0,0 +1,40 @@
#include "ModemUSB.h"
ModemUSB::ModemUSB() {
// half band filter used for side-band elimination
ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1);
}
Modem *ModemUSB::factory() {
return new ModemUSB;
}
std::string ModemUSB::getName() {
return "USB";
}
ModemUSB::~ModemUSB() {
resamp2_crcf_destroy(ssbFilt);
ampmodem_destroy(demodAM_USB);
}
void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
initOutputBuffers(akit,input);
if (!bufSize) {
input->decRefCount();
return;
}
liquid_float_complex x, y;
for (int i = 0; i < bufSize; i++) { // Reject lower band
resamp2_crcf_filter_execute(ssbFilt,input->data[i],&x,&y);
ampmodem_demodulate(demodAM_USB, y, &demodOutputData[i]);
}
buildAudioOutput(akit, audioOut, true);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "ModemAnalog.h"
class ModemUSB : public ModemAnalog {
public:
ModemUSB();
~ModemUSB();
std::string getName();
Modem *factory();
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
resamp2_crcf ssbFilt;
ampmodem demodAM_USB;
};

View File

@ -0,0 +1,89 @@
#include "ModemAPSK.h"
ModemAPSK::ModemAPSK() {
demodAPSK4 = modem_create(LIQUID_MODEM_APSK4);
demodAPSK8 = modem_create(LIQUID_MODEM_APSK8);
demodAPSK16 = modem_create(LIQUID_MODEM_APSK16);
demodAPSK32 = modem_create(LIQUID_MODEM_APSK32);
demodAPSK64 = modem_create(LIQUID_MODEM_APSK64);
demodAPSK128 = modem_create(LIQUID_MODEM_APSK128);
demodAPSK256 = modem_create(LIQUID_MODEM_APSK256);
demodulatorCons.store(4);
currentDemodCons.store(0);
updateDemodulatorCons(4);
}
Modem *ModemAPSK::factory() {
return new ModemAPSK;
}
ModemAPSK::~ModemAPSK() {
modem_destroy(demodAPSK4);
modem_destroy(demodAPSK8);
modem_destroy(demodAPSK16);
modem_destroy(demodAPSK32);
modem_destroy(demodAPSK64);
modem_destroy(demodAPSK128);
modem_destroy(demodAPSK256);
}
std::string ModemAPSK::getName() {
return "APSK";
}
void ModemAPSK::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
switch (demodulatorCons.load()) {
case 2:
demodAPSK = demodAPSK4;
updateDemodulatorCons(4);
break;
case 4:
demodAPSK = demodAPSK4;
updateDemodulatorCons(4);
break;
case 8:
demodAPSK = demodAPSK8;
updateDemodulatorCons(8);
break;
case 16:
demodAPSK = demodAPSK16;
updateDemodulatorCons(16);
break;
case 32:
demodAPSK = demodAPSK32;
updateDemodulatorCons(32);
break;
case 64:
demodAPSK = demodAPSK64;
updateDemodulatorCons(64);
break;
case 128:
demodAPSK = demodAPSK128;
updateDemodulatorCons(128);
break;
case 256:
demodAPSK = demodAPSK256;
updateDemodulatorCons(256);
break;
default:
demodAPSK = demodAPSK4;
break;
}
}
}
void ModemAPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodAPSK, input);
for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) {
modem_demodulate(demodAPSK, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodAPSK, 0.005f);
digitalFinish(dkit, demodAPSK);
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "ModemDigital.h"
class ModemAPSK : public ModemDigital {
public:
ModemAPSK();
~ModemAPSK();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodAPSK;
modem demodAPSK4;
modem demodAPSK8;
modem demodAPSK16;
modem demodAPSK32;
modem demodAPSK64;
modem demodAPSK128;
modem demodAPSK256;
};

View File

@ -0,0 +1,91 @@
#include "ModemASK.h"
ModemASK::ModemASK() {
demodASK2 = modem_create(LIQUID_MODEM_ASK2);
demodASK4 = modem_create(LIQUID_MODEM_ASK4);
demodASK8 = modem_create(LIQUID_MODEM_ASK8);
demodASK16 = modem_create(LIQUID_MODEM_ASK16);
demodASK32 = modem_create(LIQUID_MODEM_ASK32);
demodASK64 = modem_create(LIQUID_MODEM_ASK64);
demodASK128 = modem_create(LIQUID_MODEM_ASK128);
demodASK256 = modem_create(LIQUID_MODEM_ASK256);
demodASK = demodASK2;
demodulatorCons.store(2);
currentDemodCons.store(0);
updateDemodulatorCons(2);
}
Modem *ModemASK::factory() {
return new ModemASK;
}
ModemASK::~ModemASK() {
modem_destroy(demodASK4);
modem_destroy(demodASK8);
modem_destroy(demodASK16);
modem_destroy(demodASK32);
modem_destroy(demodASK64);
modem_destroy(demodASK128);
modem_destroy(demodASK256);
}
std::string ModemASK::getName() {
return "ASK";
}
void ModemASK::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
switch (demodulatorCons.load()) {
case 2:
demodASK = demodASK2;
updateDemodulatorCons(2);
break;
case 4:
demodASK = demodASK4;
updateDemodulatorCons(4);
break;
case 8:
demodASK = demodASK8;
updateDemodulatorCons(8);
break;
case 16:
demodASK = demodASK16;
updateDemodulatorCons(16);
break;
case 32:
demodASK = demodASK32;
updateDemodulatorCons(32);
break;
case 64:
demodASK = demodASK64;
updateDemodulatorCons(64);
break;
case 128:
demodASK = demodASK128;
updateDemodulatorCons(128);
break;
case 256:
demodASK = demodASK256;
updateDemodulatorCons(256);
break;
default:
demodASK = demodASK2;
break;
}
}
}
void ModemASK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodASK, input);
for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) {
modem_demodulate(demodASK, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodASK, 0.005f);
digitalFinish(dkit, demodASK);
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "ModemDigital.h"
class ModemASK : public ModemDigital {
public:
ModemASK();
~ModemASK();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodASK;
modem demodASK2;
modem demodASK4;
modem demodASK8;
modem demodASK16;
modem demodASK32;
modem demodASK64;
modem demodASK128;
modem demodASK256;
};

View File

@ -0,0 +1,35 @@
#include "ModemBPSK.h"
ModemBPSK::ModemBPSK() {
demodBPSK = modem_create(LIQUID_MODEM_BPSK);
}
Modem *ModemBPSK::factory() {
return new ModemBPSK;
}
ModemBPSK::~ModemBPSK() {
modem_destroy(demodBPSK);
}
std::string ModemBPSK::getName() {
return "BPSK";
}
void ModemBPSK::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
}
}
void ModemBPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodBPSK, input);
for (int i = 0, bufSize=input->data.size(); i < bufSize; i++) {
modem_demodulate(demodBPSK, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodBPSK, 0.005f);
digitalFinish(dkit, demodBPSK);
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "ModemDigital.h"
class ModemBPSK : public ModemDigital {
public:
ModemBPSK();
~ModemBPSK();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodBPSK;
};

View File

@ -0,0 +1,91 @@
#include "ModemDPSK.h"
ModemDPSK::ModemDPSK() {
demodDPSK2 = modem_create(LIQUID_MODEM_DPSK2);
demodDPSK4 = modem_create(LIQUID_MODEM_DPSK4);
demodDPSK8 = modem_create(LIQUID_MODEM_DPSK8);
demodDPSK16 = modem_create(LIQUID_MODEM_DPSK16);
demodDPSK32 = modem_create(LIQUID_MODEM_DPSK32);
demodDPSK64 = modem_create(LIQUID_MODEM_DPSK64);
demodDPSK128 = modem_create(LIQUID_MODEM_DPSK128);
demodDPSK256 = modem_create(LIQUID_MODEM_DPSK256);
demodulatorCons.store(2);
currentDemodCons.store(0);
updateDemodulatorCons(2);
}
Modem *ModemDPSK::factory() {
return new ModemDPSK;
}
std::string ModemDPSK::getName() {
return "DPSK";
}
ModemDPSK::~ModemDPSK() {
modem_destroy(demodDPSK2);
modem_destroy(demodDPSK4);
modem_destroy(demodDPSK8);
modem_destroy(demodDPSK16);
modem_destroy(demodDPSK32);
modem_destroy(demodDPSK64);
modem_destroy(demodDPSK128);
modem_destroy(demodDPSK256);
}
void ModemDPSK::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
switch (demodulatorCons.load()) {
case 2:
demodDPSK = demodDPSK2;
updateDemodulatorCons(2);
break;
case 4:
demodDPSK = demodDPSK4;
updateDemodulatorCons(4);
break;
case 8:
demodDPSK = demodDPSK8;
updateDemodulatorCons(8);
break;
case 16:
demodDPSK = demodDPSK16;
updateDemodulatorCons(16);
break;
case 32:
demodDPSK = demodDPSK32;
updateDemodulatorCons(32);
break;
case 64:
demodDPSK = demodDPSK64;
updateDemodulatorCons(64);
break;
case 128:
demodDPSK = demodDPSK128;
updateDemodulatorCons(128);
break;
case 256:
demodDPSK = demodDPSK256;
updateDemodulatorCons(256);
break;
default:
demodDPSK = demodDPSK2;
break;
}
}
}
void ModemDPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodDPSK, input);
for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) {
modem_demodulate(demodDPSK, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodDPSK, 0.005f);
digitalFinish(dkit, demodDPSK);
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "ModemDigital.h"
class ModemDPSK : public ModemDigital {
public:
ModemDPSK();
~ModemDPSK();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodDPSK;
modem demodDPSK2;
modem demodDPSK4;
modem demodDPSK8;
modem demodDPSK16;
modem demodDPSK32;
modem demodDPSK64;
modem demodDPSK128;
modem demodDPSK256;
};

View File

@ -0,0 +1,35 @@
#include "ModemOOK.h"
ModemOOK::ModemOOK() {
demodOOK = modem_create(LIQUID_MODEM_OOK);
}
Modem *ModemOOK::factory() {
return new ModemOOK;
}
ModemOOK::~ModemOOK() {
modem_destroy(demodOOK);
}
std::string ModemOOK::getName() {
return "OOK";
}
void ModemOOK::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
}
}
void ModemOOK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodOOK, input);
for (int i = 0, bufSize=input->data.size(); i < bufSize; i++) {
modem_demodulate(demodOOK, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodOOK, 0.005f);
digitalFinish(dkit, demodOOK);
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "ModemDigital.h"
class ModemOOK : public ModemDigital {
public:
ModemOOK();
~ModemOOK();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodOOK;
};

View File

@ -0,0 +1,91 @@
#include "ModemPSK.h"
ModemPSK::ModemPSK() {
demodPSK2 = modem_create(LIQUID_MODEM_PSK2);
demodPSK4 = modem_create(LIQUID_MODEM_PSK4);
demodPSK8 = modem_create(LIQUID_MODEM_PSK8);
demodPSK16 = modem_create(LIQUID_MODEM_PSK16);
demodPSK32 = modem_create(LIQUID_MODEM_PSK32);
demodPSK64 = modem_create(LIQUID_MODEM_PSK64);
demodPSK128 = modem_create(LIQUID_MODEM_PSK128);
demodPSK256 = modem_create(LIQUID_MODEM_PSK256);
demodulatorCons.store(2);
currentDemodCons.store(0);
updateDemodulatorCons(2);
}
Modem *ModemPSK::factory() {
return new ModemPSK;
}
std::string ModemPSK::getName() {
return "PSK";
}
ModemPSK::~ModemPSK() {
modem_destroy(demodPSK2);
modem_destroy(demodPSK4);
modem_destroy(demodPSK8);
modem_destroy(demodPSK16);
modem_destroy(demodPSK32);
modem_destroy(demodPSK64);
modem_destroy(demodPSK128);
modem_destroy(demodPSK256);
}
void ModemPSK::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
switch (demodulatorCons.load()) {
case 2:
demodPSK = demodPSK2;
updateDemodulatorCons(2);
break;
case 4:
demodPSK = demodPSK4;
updateDemodulatorCons(4);
break;
case 8:
demodPSK = demodPSK8;
updateDemodulatorCons(8);
break;
case 16:
demodPSK = demodPSK16;
updateDemodulatorCons(16);
break;
case 32:
demodPSK = demodPSK32;
updateDemodulatorCons(32);
break;
case 64:
demodPSK = demodPSK64;
updateDemodulatorCons(64);
break;
case 128:
demodPSK = demodPSK128;
updateDemodulatorCons(128);
break;
case 256:
demodPSK = demodPSK256;
updateDemodulatorCons(256);
break;
default:
demodPSK = demodPSK2;
break;
}
}
}
void ModemPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodPSK, input);
for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) {
modem_demodulate(demodPSK, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodPSK, 0.005f);
digitalFinish(dkit, demodPSK);
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "ModemDigital.h"
class ModemPSK : public ModemDigital {
public:
ModemPSK();
~ModemPSK();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodPSK;
modem demodPSK2;
modem demodPSK4;
modem demodPSK8;
modem demodPSK16;
modem demodPSK32;
modem demodPSK64;
modem demodPSK128;
modem demodPSK256;
};

View File

@ -0,0 +1,88 @@
#include "ModemQAM.h"
ModemQAM::ModemQAM() {
demodQAM4 = modem_create(LIQUID_MODEM_QAM4);
demodQAM8 = modem_create(LIQUID_MODEM_QAM8);
demodQAM16 = modem_create(LIQUID_MODEM_QAM16);
demodQAM32 = modem_create(LIQUID_MODEM_QAM32);
demodQAM64 = modem_create(LIQUID_MODEM_QAM64);
demodQAM128 = modem_create(LIQUID_MODEM_QAM128);
demodQAM256 = modem_create(LIQUID_MODEM_QAM256);
demodulatorCons.store(4);
currentDemodCons.store(0);
updateDemodulatorCons(4);
}
Modem *ModemQAM::factory() {
return new ModemQAM;
}
std::string ModemQAM::getName() {
return "QAM";
}
ModemQAM::~ModemQAM() {
modem_destroy(demodQAM4);
modem_destroy(demodQAM8);
modem_destroy(demodQAM16);
modem_destroy(demodQAM32);
modem_destroy(demodQAM64);
modem_destroy(demodQAM128);
modem_destroy(demodQAM256);
}
void ModemQAM::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
switch (demodulatorCons.load()) {
case 2:
demodQAM = demodQAM4;
updateDemodulatorCons(4);
break;
case 4:
demodQAM = demodQAM4;
updateDemodulatorCons(4);
break;
case 8:
demodQAM = demodQAM8;
updateDemodulatorCons(8);
break;
case 16:
demodQAM = demodQAM16;
updateDemodulatorCons(16);
break;
case 32:
demodQAM = demodQAM32;
updateDemodulatorCons(32);
break;
case 64:
demodQAM = demodQAM64;
updateDemodulatorCons(64);
break;
case 128:
demodQAM = demodQAM128;
updateDemodulatorCons(128);
break;
case 256:
demodQAM = demodQAM256;
updateDemodulatorCons(256);
break;
default:
demodQAM = demodQAM4;
break;
}
}
}
void ModemQAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodQAM, input);
for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) {
modem_demodulate(demodQAM, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodQAM, 0.5f);
digitalFinish(dkit, demodQAM);
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "ModemDigital.h"
class ModemQAM : public ModemDigital {
public:
ModemQAM();
~ModemQAM();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodQAM;
modem demodQAM4;
modem demodQAM8;
modem demodQAM16;
modem demodQAM32;
modem demodQAM64;
modem demodQAM128;
modem demodQAM256;
};

View File

@ -0,0 +1,35 @@
#include "ModemQPSK.h"
ModemQPSK::ModemQPSK() {
demodQPSK = modem_create(LIQUID_MODEM_QPSK);
}
Modem *ModemQPSK::factory() {
return new ModemQPSK;
}
ModemQPSK::~ModemQPSK() {
modem_destroy(demodQPSK);
}
std::string ModemQPSK::getName() {
return "QPSK";
}
void ModemQPSK::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
}
}
void ModemQPSK::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodQPSK, input);
for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) {
modem_demodulate(demodQPSK, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodQPSK, 0.8f);
digitalFinish(dkit, demodQPSK);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "ModemDigital.h"
class ModemQPSK : public ModemDigital {
public:
ModemQPSK();
~ModemQPSK();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodQPSK;
};

View File

@ -0,0 +1,79 @@
#include "ModemSQAM.h"
ModemSQAM::ModemSQAM() {
demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32);
demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128);
demodulatorCons.store(32);
currentDemodCons.store(0);
updateDemodulatorCons(32);
}
Modem *ModemSQAM::factory() {
return new ModemSQAM;
}
ModemSQAM::~ModemSQAM() {
modem_destroy(demodSQAM32);
modem_destroy(demodSQAM128);
}
std::string ModemSQAM::getName() {
return "SQAM";
}
void ModemSQAM::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
switch (demodulatorCons.load()) {
case 2:
demodSQAM = demodSQAM32;
updateDemodulatorCons(32);
break;
case 4:
demodSQAM = demodSQAM32;
updateDemodulatorCons(32);
break;
case 8:
demodSQAM = demodSQAM32;
updateDemodulatorCons(32);
break;
case 16:
demodSQAM = demodSQAM32;
updateDemodulatorCons(32);
break;
case 32:
demodSQAM = demodSQAM32;
updateDemodulatorCons(32);
break;
case 64:
demodSQAM = demodSQAM32;
updateDemodulatorCons(32);
break;
case 128:
demodSQAM = demodSQAM128;
updateDemodulatorCons(128);
break;
case 256:
demodSQAM = demodSQAM128;
updateDemodulatorCons(128);
break;
default:
demodSQAM = demodSQAM32;
break;
}
}
}
void ModemSQAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodSQAM, input);
for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) {
modem_demodulate(demodSQAM, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodSQAM, 0.005f);
digitalFinish(dkit, demodSQAM);
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "ModemDigital.h"
class ModemSQAM : public ModemDigital {
public:
ModemSQAM();
~ModemSQAM();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodSQAM;
modem demodSQAM32;
modem demodSQAM128;
};

View File

@ -0,0 +1,35 @@
#include "ModemST.h"
ModemST::ModemST() {
demodST = modem_create(LIQUID_MODEM_V29);
}
Modem *ModemST::factory() {
return new ModemST;
}
std::string ModemST::getName() {
return "ST";
}
ModemST::~ModemST() {
modem_destroy(demodST);
}
void ModemST::updateDemodulatorCons(int cons) {
if (currentDemodCons.load() != cons) {
currentDemodCons = cons;
}
}
void ModemST::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
ModemKitDigital *dkit = (ModemKitDigital *)kit;
digitalStart(dkit, demodST, input);
for (int i = 0, bufSize = input->data.size(); i < bufSize; i++) {
modem_demodulate(demodST, input->data[i], &demodOutputDataDigital[i]);
}
updateDemodulatorLock(demodST, 0.005f);
digitalFinish(dkit, demodST);
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "ModemDigital.h"
class ModemST : public ModemDigital {
public:
ModemST();
~ModemST();
std::string getName();
Modem *factory();
void updateDemodulatorCons(int cons);
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
private:
modem demodST;
};

View File

@ -1,6 +1,6 @@
#include "FFTDataDistributor.h"
FFTDataDistributor::FFTDataDistributor() : linesPerSecond(DEFAULT_WATERFALL_LPS), lineRateAccum(0.0), fftSize(DEFAULT_FFT_SIZE) {
FFTDataDistributor::FFTDataDistributor() : fftSize(DEFAULT_FFT_SIZE), linesPerSecond(DEFAULT_WATERFALL_LPS), lineRateAccum(0.0) {
bufferedItems = 0;
}

View File

@ -33,7 +33,7 @@ using namespace std;
#define STRINGIFY(A) #A
DataElement::DataElement() : data_type(DATA_NULL), data_val(NULL), data_size(0), unit_size(0) {
DataElement::DataElement() : data_type(DATA_NULL), data_size(0), unit_size(0), data_val(NULL) {
}
DataElement::~DataElement() {
@ -393,11 +393,11 @@ void DataElement::setSerialized(char *ser_str) {
/* DataNode class */
DataNode::DataNode(): ptr(0), parentNode(NULL) {
DataNode::DataNode(): parentNode(NULL), ptr(0) {
data_elem = new DataElement();
}
DataNode::DataNode(const char *name_in): ptr(0), parentNode(NULL) {
DataNode::DataNode(const char *name_in): parentNode(NULL), ptr(0) {
node_name = name_in;
data_elem = new DataElement();
}
@ -1528,7 +1528,7 @@ bool DataTree::SaveToFileXML(const std::string& filename) {
bool DataTree::SaveToFile(const std::string& filename, bool compress, int compress_level) {
long dataSize, compressedSize, headerSize;
char *serialized, *hdr_serialized, *compressed;
char *serialized = nullptr, *hdr_serialized = nullptr, *compressed = nullptr;
DataTree dtHeader;
dataSize = getSerialized(&serialized);
@ -1580,7 +1580,10 @@ bool DataTree::SaveToFile(const std::string& filename, bool compress, int compre
}
bool DataTree::LoadFromFile(const std::string& filename) {
char *compressed, *serialized, *hdr_serialized;
#if USE_FASTLZ
char *compressed;
#endif
char *serialized, *hdr_serialized;
long dataSize, headerSize, compressedSize;
ifstream fin(filename.c_str(), ios::binary);

View File

@ -155,6 +155,24 @@ void ModeSelectorCanvas::addChoice(int value, std::string label) {
numChoices = selections.size();
}
void ModeSelectorCanvas::setSelection(std::string label) {
for (int i = 0; i < numChoices; i++) {
if (selections[i].label == label) {
currentSelection = i;
return;
}
}
currentSelection = -1;
Refresh();
}
std::string ModeSelectorCanvas::getSelectionLabel() {
if (currentSelection == -1) {
return "";
}
return selections[currentSelection].label;
}
void ModeSelectorCanvas::setSelection(int value) {
for (int i = 0; i < numChoices; i++) {
if (selections[i].value == value) {

View File

@ -32,6 +32,8 @@ public:
void setHelpTip(std::string tip);
void addChoice(int value, std::string label);
void setSelection(std::string label);
std::string getSelectionLabel();
void setSelection(int value);
int getSelection();

View File

@ -87,7 +87,7 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, l
glColor4f(color.r, color.g, color.b, 0.6);
float ofs = ((float) demod->getBandwidth()) / (float) srate;
float ofsLeft = (demod->getDemodulatorType()!=DEMOD_TYPE_USB)?ofs:0, ofsRight = (demod->getDemodulatorType()!=DEMOD_TYPE_LSB)?ofs:0;
float ofsLeft = (demod->getDemodulatorType()!="USB")?ofs:0, ofsRight = (demod->getDemodulatorType()!="LSB")?ofs:0;
float labelHeight = 20.0 / viewHeight;
float hPos = -1.0 + labelHeight;
@ -139,9 +139,9 @@ void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, l
demodLabel = std::string("[M] ") + demodLabel;
}
if (demod->getDemodulatorType() == DEMOD_TYPE_USB) {
if (demod->getDemodulatorType() == "USB") {
GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodLabel, uxPos, hPos, 16, GLFont::GLFONT_ALIGN_LEFT, GLFont::GLFONT_ALIGN_CENTER);
} else if (demod->getDemodulatorType() == DEMOD_TYPE_LSB) {
} else if (demod->getDemodulatorType() == "LSB") {
GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodLabel, uxPos, hPos, 16, GLFont::GLFONT_ALIGN_RIGHT, GLFont::GLFONT_ALIGN_CENTER);
} else {
GLFont::getFont(GLFont::GLFONT_SIZE16).drawString(demodLabel, uxPos, hPos, 16, GLFont::GLFONT_ALIGN_CENTER, GLFont::GLFONT_ALIGN_CENTER);
@ -172,7 +172,7 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBA4f color, long
glColor4f(color.r, color.g, color.b, 0.6);
float ofs = ((float) demod->getBandwidth()) / (float) srate;
float ofsLeft = (demod->getDemodulatorType()!=DEMOD_TYPE_USB)?ofs:0, ofsRight = (demod->getDemodulatorType()!=DEMOD_TYPE_LSB)?ofs:0;
float ofsLeft = (demod->getDemodulatorType()!="USB")?ofs:0, ofsRight = (demod->getDemodulatorType()!="LSB")?ofs:0;
glBegin(GL_LINES);
glVertex3f((uxPos - 0.5) * 2.0, 1.0, 0.0);
@ -217,69 +217,20 @@ void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBA4f color, long
std::string demodStr = "";
GLFont::Align demodAlign = GLFont::GLFONT_ALIGN_CENTER;
switch (demod->getDemodulatorType()) {
case DEMOD_TYPE_FM:
demodStr = "FM";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_AM:
demodStr = "AM";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_LSB:
demodStr = "LSB";
demodStr = demod->getDemodulatorType();
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
if (demodStr == "LSB") {
demodAlign = GLFont::GLFONT_ALIGN_RIGHT;
uxPos -= xOfs;
break;
case DEMOD_TYPE_USB:
demodStr = "USB";
} else if (demodStr == "USB") {
demodAlign = GLFont::GLFONT_ALIGN_LEFT;
uxPos += xOfs;
break;
// advanced demodulators start here
case DEMOD_TYPE_ASK:
demodStr = "ASK";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_APSK:
demodStr = "APSK";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_BPSK:
demodStr = "BPSK";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_DPSK:
demodStr = "DPSK";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_PSK:
demodStr = "PSK";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_OOK:
demodStr = "OOK";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_SQAM:
demodStr = "SQAM";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_ST:
demodStr = "ST";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_QAM:
demodStr = "QAM";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
case DEMOD_TYPE_QPSK:
demodStr = "QPSK";
demodAlign = GLFont::GLFONT_ALIGN_CENTER;
break;
}
// advanced demodulators start here
if (demod->getDemodulatorCons() != NULL && demod->getDemodulatorCons() > 0) {
if (demod->getDemodulatorCons() > 0) {
demodStr = demodStr + std::to_string(demod->getDemodulatorCons());
}
@ -306,7 +257,7 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long
long long bw = 0;
int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
if (!demod) {
bw = wxGetApp().getDemodMgr().getLastBandwidth();
@ -337,12 +288,12 @@ void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long
ofs = ((float) bw) / (float) srate;
}
if (last_type != DEMOD_TYPE_USB) {
if (last_type != "USB") {
glVertex3f((uxPos - 0.5) * 2.0 - ofs, 1.0, 0.0);
glVertex3f((uxPos - 0.5) * 2.0 - ofs, -1.0, 0.0);
}
if (last_type != DEMOD_TYPE_LSB) {
if (last_type != "LSB") {
glVertex3f((uxPos - 0.5) * 2.0 + ofs, 1.0, 0.0);
glVertex3f((uxPos - 0.5) * 2.0 + ofs, -1.0, 0.0);
}
@ -359,7 +310,7 @@ void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f colo
uxPos1=temp;
}
int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
glDisable(GL_TEXTURE_2D);
@ -367,14 +318,14 @@ void PrimaryGLContext::DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f colo
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glColor4f(color.r, color.g, color.b, 0.6);
glLineWidth((last_type == DEMOD_TYPE_USB)?2.0:1.0);
glLineWidth((last_type == "USB")?2.0:1.0);
glBegin(GL_LINES);
glVertex3f((uxPos1 - 0.5) * 2.0, 1.0, 0.0);
glVertex3f((uxPos1 - 0.5) * 2.0, -1.0, 0.0);
glEnd();
glLineWidth((last_type == DEMOD_TYPE_LSB)?2.0:1.0);
glLineWidth((last_type == "LSB")?2.0:1.0);
glBegin(GL_LINES);
glVertex3f((uxPos2 - 0.5) * 2.0, 1.0, 0.0);

View File

@ -36,7 +36,7 @@ wxEND_EVENT_TABLE()
WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) :
InteractiveCanvas(parent, attribList), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), fft_size(0), waterfall_lines(0),
dragOfs(0), mouseZoom(1), zoom(1), freqMove(0.0), freqMoving(false), hoverAlpha(1.0) {
dragOfs(0), mouseZoom(1), zoom(1), freqMoving(false), freqMove(0.0), hoverAlpha(1.0) {
glContext = new PrimaryGLContext(this, &wxGetApp().GetContext(this));
linesPerSecond = 30;
@ -253,7 +253,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
long long currentCenterFreq = getCenterFrequency();
ColorTheme *currentTheme = ThemeMgr::mgr.currentTheme;
int last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
std::string last_type = wxGetApp().getDemodMgr().getLastDemodulatorType();
if (mouseTracker.mouseInView() || wxGetApp().getDemodMgr().getActiveDemodulator()) {
hoverAlpha += (1.0f-hoverAlpha)*0.1f;
@ -277,7 +277,7 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
glContext->DrawDemod(lastActiveDemodulator, isNew?currentTheme->waterfallHighlight:currentTheme->waterfallDestroy, currentCenterFreq, currentBandwidth);
if ((last_type == DEMOD_TYPE_LSB || last_type == DEMOD_TYPE_USB) && mouseTracker.mouseDown()) {
if ((last_type == "LSB" || last_type == "USB") && mouseTracker.mouseDown()) {
centerPos = mouseTracker.getMouseX();
glContext->DrawRangeSelector(centerPos, centerPos-width, isNew?currentTheme->waterfallNew:currentTheme->waterfallHover);
} else {
@ -416,16 +416,6 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
}
activeDemod->setMuted(!activeDemod->isMuted());
break;
case 'S':
if (!activeDemod) {
break;
}
if (activeDemod->isStereo()) {
activeDemod->setStereo(false);
} else {
activeDemod->setStereo(true);
}
break;
case 'B':
if (spectrumCanvas) {
spectrumCanvas->setShowDb(!spectrumCanvas->getShowDb());
@ -534,8 +524,8 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
double maxDist = ((double)halfBw + bufferBw);
if ((double)dist <= maxDist) {
if ((freqDiff > 0 && demod->getDemodulatorType() == DEMOD_TYPE_USB) ||
(freqDiff < 0 && demod->getDemodulatorType() == DEMOD_TYPE_LSB)) {
if ((freqDiff > 0 && demod->getDemodulatorType() == "USB") ||
(freqDiff < 0 && demod->getDemodulatorType() == "LSB")) {
continue;
}
@ -565,12 +555,12 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
if (abs(freqDiff) > (activeDemodulator->getBandwidth() / 3)) {
if (freqDiff > 0) {
if (activeDemodulator->getDemodulatorType() != DEMOD_TYPE_USB) {
if (activeDemodulator->getDemodulatorType() != "USB") {
nextDragState = WF_DRAG_BANDWIDTH_LEFT;
SetCursor(wxCURSOR_SIZEWE);
}
} else {
if (activeDemodulator->getDemodulatorType() != DEMOD_TYPE_LSB) {
if (activeDemodulator->getDemodulatorType() != "LSB") {
nextDragState = WF_DRAG_BANDWIDTH_RIGHT;
SetCursor(wxCURSOR_SIZEWE);
}
@ -578,14 +568,14 @@ void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
mouseTracker.setVertDragLock(true);
mouseTracker.setHorizDragLock(false);
setStatusText("Click and drag to change demodulator bandwidth. SPACE for direct frequency input. M for mute, D to delete, S for stereo.");
setStatusText("Click and drag to change demodulator bandwidth. SPACE for direct frequency input. M for mute, D to delete.");
} else {
SetCursor(wxCURSOR_SIZING);
nextDragState = WF_DRAG_FREQUENCY;
mouseTracker.setVertDragLock(true);
mouseTracker.setHorizDragLock(false);
setStatusText("Click and drag to change demodulator frequency; SPACE for direct input. M for mute, D to delete, S for stereo.");
setStatusText("Click and drag to change demodulator frequency; SPACE for direct input. M for mute, D to delete.");
}
} else {
SetCursor(wxCURSOR_CROSS);
@ -671,7 +661,6 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
demod->setBandwidth(mgr->getLastBandwidth());
demod->setSquelchLevel(mgr->getLastSquelchLevel());
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
demod->setStereo(mgr->isLastStereo());
demod->setGain(mgr->getLastGain());
demod->setMuted(mgr->isLastMuted());
@ -712,9 +701,9 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
float width = mouseTracker.getOriginDeltaMouseX();
float pos;
int last_type = mgr->getLastDemodulatorType();
std::string last_type = mgr->getLastDemodulatorType();
if (last_type == DEMOD_TYPE_LSB || last_type == DEMOD_TYPE_USB) {
if (last_type == "LSB" || last_type == "USB") {
float pos1 = mouseTracker.getOriginMouseX();
float pos2 = mouseTracker.getMouseX();
@ -724,7 +713,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
pos2 = tmp;
}
pos = (last_type == DEMOD_TYPE_LSB)?pos2:pos1;
pos = (last_type == "LSB")?pos2:pos1;
width *= 2;
} else {
pos = mouseTracker.getOriginMouseX() + width / 2.0;
@ -759,7 +748,6 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
demod->setBandwidth(bw);
demod->setSquelchLevel(mgr->getLastSquelchLevel());
demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
demod->setStereo(mgr->isLastStereo());
demod->setGain(mgr->getLastGain());
demod->run();