Merge pull request #112 from cjcliffe/raw_demod

I/Q raw demodulator
This commit is contained in:
Charles J. Cliffe 2015-07-19 23:40:37 -04:00
commit d3dee2b184
17 changed files with 175 additions and 66 deletions

View File

@ -121,6 +121,7 @@ AppConfig::AppConfig() {
winH.store(0); winH.store(0);
winMax.store(false); winMax.store(false);
themeId.store(0); themeId.store(0);
snap.store(1);
} }
@ -186,6 +187,15 @@ int AppConfig::getTheme() {
} }
void AppConfig::setSnap(long long snapVal) {
this->snap.store(snapVal);
}
long long AppConfig::getSnap() {
return snap.load();
}
bool AppConfig::save() { bool AppConfig::save() {
DataTree cfg; DataTree cfg;
@ -200,8 +210,8 @@ bool AppConfig::save() {
*window_node->newChild("h") = winH.load(); *window_node->newChild("h") = winH.load();
*window_node->newChild("max") = winMax.load(); *window_node->newChild("max") = winMax.load();
*window_node->newChild("theme") = themeId.load(); *window_node->newChild("theme") = themeId.load();
*window_node->newChild("snap") = snap.load();
} }
DataNode *devices_node = cfg.rootNode()->newChild("devices"); DataNode *devices_node = cfg.rootNode()->newChild("devices");
@ -275,6 +285,11 @@ bool AppConfig::load() {
themeId.store(theme); themeId.store(theme);
} }
if (win_node->hasAnother("snap")) {
long long snapVal;
win_node->getNext("snap")->element()->get(snapVal);
snap.store(snapVal);
}
} }
if (cfg.rootNode()->hasAnother("devices")) { if (cfg.rootNode()->hasAnother("devices")) {

View File

@ -55,7 +55,10 @@ public:
void setTheme(int themeId); void setTheme(int themeId);
int getTheme(); int getTheme();
void setSnap(long long snapVal);
long long getSnap();
bool save(); bool save();
bool load(); bool load();
bool reset(); bool reset();
@ -65,4 +68,5 @@ private:
std::atomic_int winX,winY,winW,winH; std::atomic_int winX,winY,winW,winH;
std::atomic_bool winMax; std::atomic_bool winMax;
std::atomic_int themeId; std::atomic_int themeId;
std::atomic_llong snap;
}; };

View File

@ -57,6 +57,7 @@ AppFrame::AppFrame() :
demodModeSelector->addChoice(DEMOD_TYPE_LSB, "LSB"); demodModeSelector->addChoice(DEMOD_TYPE_LSB, "LSB");
demodModeSelector->addChoice(DEMOD_TYPE_USB, "USB"); demodModeSelector->addChoice(DEMOD_TYPE_USB, "USB");
demodModeSelector->addChoice(DEMOD_TYPE_DSB, "DSB"); demodModeSelector->addChoice(DEMOD_TYPE_DSB, "DSB");
demodModeSelector->addChoice(DEMOD_TYPE_RAW, "I/Q");
demodModeSelector->setSelection(DEMOD_TYPE_FM); demodModeSelector->setSelection(DEMOD_TYPE_FM);
demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band."); demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation, Amplitude Modulation and Lower, Upper or Double Side-Band.");
demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0); demodTray->Add(demodModeSelector, 2, wxEXPAND | wxALL, 0);
@ -318,6 +319,9 @@ AppFrame::AppFrame() :
if (max) { if (max) {
this->Maximize(); this->Maximize();
} }
long long freqSnap = wxGetApp().getConfig()->getSnap();
wxGetApp().setFrequencySnap(freqSnap);
ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme()); ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme());
@ -372,16 +376,21 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
"Frequency Offset", wxGetApp().getOffset(), -2000000000, 2000000000, this); "Frequency Offset", wxGetApp().getOffset(), -2000000000, 2000000000, this);
if (ofs != -1) { if (ofs != -1) {
wxGetApp().setOffset(ofs); wxGetApp().setOffset(ofs);
wxGetApp().saveConfig();
} }
} else if (event.GetId() == wxID_SET_DS_OFF) { } else if (event.GetId() == wxID_SET_DS_OFF) {
wxGetApp().setDirectSampling(0); wxGetApp().setDirectSampling(0);
wxGetApp().saveConfig();
} else if (event.GetId() == wxID_SET_DS_I) { } else if (event.GetId() == wxID_SET_DS_I) {
wxGetApp().setDirectSampling(1); wxGetApp().setDirectSampling(1);
wxGetApp().saveConfig();
} else if (event.GetId() == wxID_SET_DS_Q) { } else if (event.GetId() == wxID_SET_DS_Q) {
wxGetApp().setDirectSampling(2); wxGetApp().setDirectSampling(2);
wxGetApp().saveConfig();
} else if (event.GetId() == wxID_SET_SWAP_IQ) { } else if (event.GetId() == wxID_SET_SWAP_IQ) {
bool swap_state = !wxGetApp().getSwapIQ(); bool swap_state = !wxGetApp().getSwapIQ();
wxGetApp().setSwapIQ(swap_state); wxGetApp().setSwapIQ(swap_state);
wxGetApp().saveConfig();
iqSwapMenuItem->Check(swap_state); iqSwapMenuItem->Check(swap_state);
} else if (event.GetId() == wxID_SET_PPM) { } else if (event.GetId() == wxID_SET_PPM) {
long ofs = wxGetNumberFromUser("Frequency correction for device in PPM.\ni.e. -51 for -51 PPM\n\nNote: you can adjust PPM interactively\nby holding ALT over the frequency tuning bar.\n", "Parts per million (PPM)", long ofs = wxGetNumberFromUser("Frequency correction for device in PPM.\ni.e. -51 for -51 PPM\n\nNote: you can adjust PPM interactively\nby holding ALT over the frequency tuning bar.\n", "Parts per million (PPM)",
@ -527,6 +536,7 @@ void AppFrame::OnClose(wxCloseEvent& event) {
wxGetApp().getConfig()->setWindow(this->GetPosition(), this->GetClientSize()); wxGetApp().getConfig()->setWindow(this->GetPosition(), this->GetClientSize());
wxGetApp().getConfig()->setWindowMaximized(this->IsMaximized()); wxGetApp().getConfig()->setWindowMaximized(this->IsMaximized());
wxGetApp().getConfig()->setTheme(ThemeMgr::mgr.getTheme()); wxGetApp().getConfig()->setTheme(ThemeMgr::mgr.getTheme());
wxGetApp().getConfig()->setSnap(wxGetApp().getFrequencySnap());
wxGetApp().getConfig()->save(); wxGetApp().getConfig()->save();
event.Skip(); event.Skip();
} }

View File

@ -193,7 +193,6 @@ void CubicSDR::setOffset(long long ofs) {
SDRDeviceInfo *dev = (*getDevices())[getDevice()]; SDRDeviceInfo *dev = (*getDevices())[getDevice()];
config.getDevice(dev->getDeviceId())->setOffset(ofs); config.getDevice(dev->getDeviceId())->setOffset(ofs);
config.save();
} }
void CubicSDR::setDirectSampling(int mode) { void CubicSDR::setDirectSampling(int mode) {
@ -204,7 +203,6 @@ void CubicSDR::setDirectSampling(int mode) {
SDRDeviceInfo *dev = (*getDevices())[getDevice()]; SDRDeviceInfo *dev = (*getDevices())[getDevice()];
config.getDevice(dev->getDeviceId())->setDirectSampling(mode); config.getDevice(dev->getDeviceId())->setDirectSampling(mode);
config.save();
} }
int CubicSDR::getDirectSampling() { int CubicSDR::getDirectSampling() {
@ -215,7 +213,6 @@ void CubicSDR::setSwapIQ(bool swapIQ) {
sdrPostThread->setSwapIQ(swapIQ); sdrPostThread->setSwapIQ(swapIQ);
SDRDeviceInfo *dev = (*getDevices())[getDevice()]; SDRDeviceInfo *dev = (*getDevices())[getDevice()];
config.getDevice(dev->getDeviceId())->setIQSwap(swapIQ); config.getDevice(dev->getDeviceId())->setIQSwap(swapIQ);
config.save();
} }
bool CubicSDR::getSwapIQ() { bool CubicSDR::getSwapIQ() {
@ -309,7 +306,6 @@ void CubicSDR::setPPM(int ppm_in) {
SDRDeviceInfo *dev = (*getDevices())[getDevice()]; SDRDeviceInfo *dev = (*getDevices())[getDevice()];
config.getDevice(dev->getDeviceId())->setPPM(ppm_in); config.getDevice(dev->getDeviceId())->setPPM(ppm_in);
config.save();
} }
int CubicSDR::getPPM() { int CubicSDR::getPPM() {

View File

@ -22,7 +22,7 @@
class CubicSDR: public wxApp { class CubicSDR: public wxApp {
public: public:
CubicSDR() : CubicSDR() :
m_glContext(NULL), frequency(DEFAULT_FREQ), sdrThread(NULL), sdrPostThread(NULL), threadCmdQueueSDR(NULL), iqVisualQueue(NULL), iqPostDataQueue(NULL), audioVisualQueue(NULL), t_SDR(NULL), t_PostSDR(NULL), sampleRate(DEFAULT_SAMPLE_RATE), offset(0), snap(1) { appframe(NULL), m_glContext(NULL), frequency(DEFAULT_FREQ), sdrThread(NULL), sdrPostThread(NULL), threadCmdQueueSDR(NULL), iqVisualQueue(NULL), iqPostDataQueue(NULL), audioVisualQueue(NULL), t_SDR(NULL), t_PostSDR(NULL), sampleRate(DEFAULT_SAMPLE_RATE), offset(0), snap(1), directSamplingMode(0), ppm(0) {
} }

View File

@ -53,5 +53,5 @@ public:
return refCount.load(); return refCount.load();
} }
protected: protected:
std::atomic<int> refCount; std::atomic_int refCount;
}; };

View File

@ -52,12 +52,12 @@ public:
AudioThreadInput *currentInput; AudioThreadInput *currentInput;
AudioThreadInputQueue *inputQueue; AudioThreadInputQueue *inputQueue;
std::atomic<unsigned int> audioQueuePtr; std::atomic_uint audioQueuePtr;
std::atomic<unsigned int> underflowCount; std::atomic_uint underflowCount;
std::atomic<bool> terminated; std::atomic_bool terminated;
std::atomic<bool> initialized; std::atomic_bool initialized;
std::atomic<bool> active; std::atomic_bool active;
std::atomic<int> outputDevice; std::atomic_int outputDevice;
std::atomic<float> gain; std::atomic<float> gain;
AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify); AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify);

View File

@ -13,6 +13,8 @@
#define DEMOD_TYPE_LSB 3 #define DEMOD_TYPE_LSB 3
#define DEMOD_TYPE_USB 4 #define DEMOD_TYPE_USB 4
#define DEMOD_TYPE_DSB 5 #define DEMOD_TYPE_DSB 5
#define DEMOD_TYPE_RAW 6
class DemodulatorThread; class DemodulatorThread;
class DemodulatorThreadCommand { class DemodulatorThreadCommand {

View File

@ -2,7 +2,7 @@
DemodulatorInstance::DemodulatorInstance() : DemodulatorInstance::DemodulatorInstance() :
t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(true), audioTerminated(true), demodTerminated( t_Demod(NULL), t_PreDemod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(true), audioTerminated(true), demodTerminated(
true), preDemodTerminated(true), active(false), squelch(false), stereo(false), currentFrequency(0), currentBandwidth(0), currentOutputDevice(-1) { true), preDemodTerminated(true), active(false), squelch(false), stereo(false), tracking(false), follow(false), currentAudioSampleRate(0), currentFrequency(0), currentBandwidth(0), currentOutputDevice(-1), currentAudioGain(1.0) {
label = new std::string("Unnamed"); label = new std::string("Unnamed");
threadQueueDemod = new DemodulatorThreadInputQueue; threadQueueDemod = new DemodulatorThreadInputQueue;
@ -220,13 +220,12 @@ void DemodulatorInstance::setOutputDevice(int device_id) {
if (!active) { if (!active) {
audioThread->setInitOutputDevice(device_id); audioThread->setInitOutputDevice(device_id);
} else if (audioThread) { } else if (audioThread) {
setAudioSampleRate(AudioThread::deviceSampleRate[device_id]);
AudioThreadCommand command; AudioThreadCommand command;
command.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE; command.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE;
command.int_value = device_id; command.int_value = device_id;
audioThread->getCommandQueue()->push(command); audioThread->getCommandQueue()->push(command);
} }
setAudioSampleRate(AudioThread::deviceSampleRate[device_id]);
currentOutputDevice = device_id; currentOutputDevice = device_id;
} }
@ -245,15 +244,28 @@ void DemodulatorInstance::checkBandwidth() {
} }
void DemodulatorInstance::setDemodulatorType(int demod_type_in) { void DemodulatorInstance::setDemodulatorType(int demod_type_in) {
currentDemodType = demod_type_in;
if (currentDemodType == DEMOD_TYPE_RAW) {
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) {
demodulatorThread->setAGC(false);
} else {
demodulatorThread->setAGC(true);
}
setGain(getGain());
if (!active) { if (!active) {
currentDemodType = demod_type_in;
checkBandwidth(); checkBandwidth();
demodulatorPreThread->getParams().demodType = currentDemodType; demodulatorPreThread->getParams().demodType = currentDemodType;
demodulatorThread->setDemodulatorType(currentDemodType); demodulatorThread->setDemodulatorType(currentDemodType);
} else if (demodulatorThread && threadQueueControl) { } else if (demodulatorThread && threadQueueControl) {
DemodulatorThreadControlCommand command; DemodulatorThreadControlCommand command;
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE; command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE;
currentDemodType = demod_type_in;
command.demodType = demod_type_in; command.demodType = demod_type_in;
checkBandwidth(); checkBandwidth();
threadQueueControl->push(command); threadQueueControl->push(command);
@ -265,6 +277,13 @@ int DemodulatorInstance::getDemodulatorType() {
} }
void DemodulatorInstance::setBandwidth(int bw) { void DemodulatorInstance::setBandwidth(int bw) {
if (currentDemodType == DEMOD_TYPE_RAW) {
if (currentAudioSampleRate) {
bw = currentAudioSampleRate;
} else {
bw = AudioThread::deviceSampleRate[getOutputDevice()];
}
}
if (!active) { if (!active) {
currentBandwidth = bw; currentBandwidth = bw;
checkBandwidth(); checkBandwidth();
@ -321,6 +340,9 @@ void DemodulatorInstance::setAudioSampleRate(int sampleRate) {
command.llong_value = sampleRate; command.llong_value = sampleRate;
threadQueueCommand->push(command); threadQueueCommand->push(command);
} }
if (currentDemodType == DEMOD_TYPE_RAW) {
setBandwidth(currentAudioSampleRate);
}
} }
int DemodulatorInstance::getAudioSampleRate() { int DemodulatorInstance::getAudioSampleRate() {
@ -332,11 +354,23 @@ int DemodulatorInstance::getAudioSampleRate() {
void DemodulatorInstance::setGain(float gain_in) { void DemodulatorInstance::setGain(float gain_in) {
audioThread->setGain(gain_in); currentAudioGain = gain_in;
if (currentDemodType == DEMOD_TYPE_RAW) {
if (gain_in < 0.25) {
audioThread->setGain(1.0);
demodulatorThread->setAGC(false);
} else {
audioThread->setGain(gain_in);
demodulatorThread->setAGC(true);
}
} else {
audioThread->setGain(gain_in);
}
} }
float DemodulatorInstance::getGain() { float DemodulatorInstance::getGain() {
return audioThread->getGain(); return currentAudioGain;
} }
bool DemodulatorInstance::isFollow() { bool DemodulatorInstance::isFollow() {

View File

@ -87,18 +87,19 @@ private:
void checkBandwidth(); void checkBandwidth();
std::atomic<std::string *> label; // std::atomic<std::string *> label; //
bool terminated; // std::atomic_bool terminated; //
bool demodTerminated; // std::atomic_bool demodTerminated; //
bool audioTerminated; // std::atomic_bool audioTerminated; //
bool preDemodTerminated; std::atomic_bool preDemodTerminated;
std::atomic<bool> active; std::atomic_bool active;
std::atomic<bool> squelch; std::atomic_bool squelch;
std::atomic<bool> stereo; std::atomic_bool stereo;
long long currentFrequency; std::atomic_llong currentFrequency;
int currentBandwidth; std::atomic_int currentBandwidth;
int currentDemodType; std::atomic_int currentDemodType;
int currentOutputDevice; std::atomic_int currentOutputDevice;
int currentAudioSampleRate; std::atomic_int currentAudioSampleRate;
bool follow, tracking; std::atomic<float> currentAudioGain;
std::atomic_bool follow, tracking;
}; };

View File

@ -68,8 +68,8 @@ protected:
nco_crcf freqShifter; nco_crcf freqShifter;
int shiftFrequency; int shiftFrequency;
std::atomic<bool> terminated; std::atomic_bool terminated;
std::atomic<bool> initialized; std::atomic_bool initialized;
DemodulatorWorkerThread *workerThread; DemodulatorWorkerThread *workerThread;
std::thread *t_Worker; std::thread *t_Worker;

View File

@ -14,7 +14,7 @@
DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQueue, DemodulatorThreadControlCommandQueue *threadQueueControl,
DemodulatorThreadCommandQueue* threadQueueNotify) : DemodulatorThreadCommandQueue* threadQueueNotify) :
iqInputQueue(iqInputQueue), audioVisOutputQueue(NULL), audioOutputQueue(NULL), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA( iqInputQueue(iqInputQueue), audioVisOutputQueue(NULL), audioOutputQueue(NULL), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA(
1), stereo(false), terminated( 1), stereo(false), agcEnabled(true), terminated(
false), demodulatorType(DEMOD_TYPE_FM), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl), squelchLevel(0), signalLevel( false), demodulatorType(DEMOD_TYPE_FM), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl), squelchLevel(0), signalLevel(
0), squelchEnabled(false), audioSampleRate(0) { 0), squelchEnabled(false), audioSampleRate(0) {
@ -61,7 +61,7 @@ void DemodulatorThread::threadMain() {
// Automatic IQ gain // Automatic IQ gain
iqAutoGain = agc_crcf_create(); iqAutoGain = agc_crcf_create();
agc_crcf_set_bandwidth(iqAutoGain, 0.9); agc_crcf_set_bandwidth(iqAutoGain, 0.1);
AudioThreadInput *ati_vis = new AudioThreadInput; AudioThreadInput *ati_vis = new AudioThreadInput;
ati_vis->data.reserve(DEMOD_VIS_SIZE); ati_vis->data.reserve(DEMOD_VIS_SIZE);
@ -171,27 +171,37 @@ void DemodulatorThread::threadMain() {
currentSignalLevel = agc_crcf_get_signal_level(iqAutoGain); currentSignalLevel = agc_crcf_get_signal_level(iqAutoGain);
} }
std::vector<liquid_float_complex> *inputData;
if (agcEnabled) {
inputData = &agcData;
} else {
inputData = &inp->data;
}
if (demodulatorType == DEMOD_TYPE_FM) { if (demodulatorType == DEMOD_TYPE_FM) {
freqdem_demodulate_block(demodFM, &agcData[0], bufSize, &demodOutputData[0]); freqdem_demodulate_block(demodFM, &(*inputData)[0], bufSize, &demodOutputData[0]);
} else if (demodulatorType == DEMOD_TYPE_RAW) {
// do nothing here..
} else { } else {
float p; float p;
switch (demodulatorType.load()) { switch (demodulatorType.load()) {
case DEMOD_TYPE_LSB: case DEMOD_TYPE_LSB:
for (int i = 0; i < bufSize; i++) { // Reject upper band for (int i = 0; i < bufSize; i++) { // Reject upper band
resamp2_cccf_filter_execute(ssbFilt,inp->data[i],&x,&y); resamp2_cccf_filter_execute(ssbFilt,(*inputData)[i],&x,&y);
ampmodem_demodulate(demodAM, x, &demodOutputData[i]); ampmodem_demodulate(demodAM, x, &demodOutputData[i]);
} }
break; break;
case DEMOD_TYPE_USB: case DEMOD_TYPE_USB:
for (int i = 0; i < bufSize; i++) { // Reject lower band for (int i = 0; i < bufSize; i++) { // Reject lower band
resamp2_cccf_filter_execute(ssbFilt,inp->data[i],&x,&y); resamp2_cccf_filter_execute(ssbFilt,(*inputData)[i],&x,&y);
ampmodem_demodulate(demodAM, y, &demodOutputData[i]); ampmodem_demodulate(demodAM, y, &demodOutputData[i]);
} }
break; break;
case DEMOD_TYPE_AM: case DEMOD_TYPE_AM:
case DEMOD_TYPE_DSB: case DEMOD_TYPE_DSB:
for (int i = 0; i < bufSize; i++) { for (int i = 0; i < bufSize; i++) {
ampmodem_demodulate(demodAM, inp->data[i], &demodOutputData[i]); ampmodem_demodulate(demodAM, (*inputData)[i], &demodOutputData[i]);
} }
break; break;
} }
@ -222,6 +232,10 @@ void DemodulatorThread::threadMain() {
} }
unsigned int numAudioWritten; unsigned int numAudioWritten;
if (demodulatorType == DEMOD_TYPE_RAW) {
numAudioWritten = bufSize;
} else {
msresamp_rrrf_execute(audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten); msresamp_rrrf_execute(audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten);
if (stereo && inp->sampleRate >= 100000) { if (stereo && inp->sampleRate >= 100000) {
@ -276,6 +290,7 @@ void DemodulatorThread::threadMain() {
msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten); msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
} }
}
if (currentSignalLevel > signalLevel) { if (currentSignalLevel > signalLevel) {
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5; signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5;
@ -303,7 +318,17 @@ void DemodulatorThread::threadMain() {
ati->sampleRate = audioSampleRate; ati->sampleRate = audioSampleRate;
ati->setRefCount(1); ati->setRefCount(1);
if (stereo && inp->sampleRate >= 100000) { if (demodulatorType == DEMOD_TYPE_RAW) {
ati->channels = 2;
if (ati->data.capacity() < (numAudioWritten * 2)) {
ati->data.reserve(numAudioWritten * 2);
}
ati->data.resize(numAudioWritten * 2);
for (int i = 0; i < numAudioWritten; i++) {
ati->data[i * 2] = (*inputData)[i].real;
ati->data[i * 2 + 1] = (*inputData)[i].imag;
}
} else if (stereo && inp->sampleRate >= 100000) {
ati->channels = 2; ati->channels = 2;
if (ati->data.capacity() < (numAudioWritten * 2)) { if (ati->data.capacity() < (numAudioWritten * 2)) {
ati->data.reserve(numAudioWritten * 2); ati->data.reserve(numAudioWritten * 2);
@ -334,8 +359,6 @@ void DemodulatorThread::threadMain() {
ati->peak = p; ati->peak = p;
} }
} }
audioOutputQueue->push(ati);
} }
} }
@ -344,18 +367,25 @@ void DemodulatorThread::threadMain() {
ati_vis->busy_update.lock(); ati_vis->busy_update.lock();
int num_vis = DEMOD_VIS_SIZE; int num_vis = DEMOD_VIS_SIZE;
if (stereo && inp->sampleRate >= 100000) { if (demodulatorType == DEMOD_TYPE_RAW || (stereo && inp->sampleRate >= 100000)) {
ati_vis->channels = 2; ati_vis->channels = 2;
int stereoSize = ati->data.size(); int stereoSize = ati->data.size();
if (stereoSize > DEMOD_VIS_SIZE) { if (stereoSize > DEMOD_VIS_SIZE * 2) {
stereoSize = DEMOD_VIS_SIZE; stereoSize = DEMOD_VIS_SIZE * 2;
} }
ati_vis->data.resize(stereoSize); ati_vis->data.resize(stereoSize);
for (int i = 0; i < stereoSize / 2; i++) { if (demodulatorType == DEMOD_TYPE_RAW) {
ati_vis->data[i] = ati->data[i * 2]; for (int i = 0; i < stereoSize / 2; i++) {
ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1]; ati_vis->data[i] = agcData[i].real * 0.75;
ati_vis->data[i + stereoSize / 2] = agcData[i].imag * 0.75;
}
} else {
for (int i = 0; i < stereoSize / 2; i++) {
ati_vis->data[i] = ati->data[i * 2];
ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1];
}
} }
} else { } else {
ati_vis->channels = 1; ati_vis->channels = 1;
@ -379,6 +409,11 @@ void DemodulatorThread::threadMain() {
ati_vis->busy_update.unlock(); ati_vis->busy_update.unlock();
} }
if (ati != NULL) {
audioOutputQueue->push(ati);
}
if (!threadQueueControl->empty()) { if (!threadQueueControl->empty()) {
int newDemodType = DEMOD_TYPE_NULL; int newDemodType = DEMOD_TYPE_NULL;
@ -489,16 +524,25 @@ void DemodulatorThread::terminate() {
} }
void DemodulatorThread::setStereo(bool state) { void DemodulatorThread::setStereo(bool state) {
stereo = state; stereo.store(state);
std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl; std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl;
} }
bool DemodulatorThread::isStereo() { bool DemodulatorThread::isStereo() {
return stereo; return stereo.load();
} }
void DemodulatorThread::setAGC(bool state) {
agcEnabled.store(state);
}
bool DemodulatorThread::getAGC() {
return agcEnabled.load();
}
float DemodulatorThread::getSignalLevel() { float DemodulatorThread::getSignalLevel() {
return signalLevel; return signalLevel.load();
} }
void DemodulatorThread::setSquelchLevel(float signal_level_in) { void DemodulatorThread::setSquelchLevel(float signal_level_in) {

View File

@ -31,6 +31,9 @@ public:
void setStereo(bool state); void setStereo(bool state);
bool isStereo(); bool isStereo();
void setAGC(bool state);
bool getAGC();
float getSignalLevel(); float getSignalLevel();
void setSquelchLevel(float signal_level_in); void setSquelchLevel(float signal_level_in);
float getSquelchLevel(); float getSquelchLevel();
@ -72,9 +75,10 @@ protected:
float amOutputCeilMA; float amOutputCeilMA;
float amOutputCeilMAA; float amOutputCeilMAA;
std::atomic<bool> stereo; std::atomic_bool stereo;
std::atomic<bool> terminated; std::atomic_bool agcEnabled;
std::atomic<int> demodulatorType; std::atomic_bool terminated;
std::atomic_int demodulatorType;
int audioSampleRate; int audioSampleRate;
DemodulatorThreadCommandQueue* threadQueueNotify; DemodulatorThreadCommandQueue* threadQueueNotify;

View File

@ -93,5 +93,5 @@ protected:
DemodulatorThreadWorkerCommandQueue *commandQueue; DemodulatorThreadWorkerCommandQueue *commandQueue;
DemodulatorThreadWorkerResultQueue *resultQueue; DemodulatorThreadWorkerResultQueue *resultQueue;
std::atomic<bool> terminated; std::atomic_bool terminated;
}; };

View File

@ -31,10 +31,10 @@ protected:
std::mutex busy_demod; std::mutex busy_demod;
std::vector<DemodulatorInstance *> demodulators; std::vector<DemodulatorInstance *> demodulators;
std::atomic<bool> terminated; std::atomic_bool terminated;
iirfilt_crcf dcFilter; iirfilt_crcf dcFilter;
int num_vis_samples; int num_vis_samples;
std::atomic<bool> swapIQ; std::atomic_bool swapIQ;
private: private:
std::vector<liquid_float_complex> _lut; std::vector<liquid_float_complex> _lut;

View File

@ -149,10 +149,10 @@ public:
protected: protected:
std::atomic<uint32_t> sampleRate; std::atomic<uint32_t> sampleRate;
std::atomic<long long> offset; std::atomic_llong offset;
std::atomic<SDRThreadCommandQueue*> commandQueue; std::atomic<SDRThreadCommandQueue*> commandQueue;
std::atomic<SDRThreadIQDataQueue*> iqDataOutQueue; std::atomic<SDRThreadIQDataQueue*> iqDataOutQueue;
std::atomic<bool> terminated; std::atomic_bool terminated;
std::atomic<int> deviceId; std::atomic_int deviceId;
}; };

View File

@ -820,8 +820,8 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
demod = wxGetApp().getDemodMgr().newThread(); demod = wxGetApp().getDemodMgr().newThread();
demod->setFrequency(freq); demod->setFrequency(freq);
demod->setBandwidth(mgr->getLastBandwidth());
demod->setDemodulatorType(mgr->getLastDemodulatorType()); demod->setDemodulatorType(mgr->getLastDemodulatorType());
demod->setBandwidth(mgr->getLastBandwidth());
demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchLevel(mgr->getLastSquelchLevel());
demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
demod->setStereo(mgr->isLastStereo()); demod->setStereo(mgr->isLastStereo());
@ -907,9 +907,8 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
} else { } else {
demod = wxGetApp().getDemodMgr().newThread(); demod = wxGetApp().getDemodMgr().newThread();
demod->setFrequency(freq); demod->setFrequency(freq);
demod->setBandwidth(bw);
demod->setDemodulatorType(mgr->getLastDemodulatorType()); demod->setDemodulatorType(mgr->getLastDemodulatorType());
demod->setBandwidth(bw);
demod->setSquelchLevel(mgr->getLastSquelchLevel()); demod->setSquelchLevel(mgr->getLastSquelchLevel());
demod->setSquelchEnabled(mgr->isLastSquelchEnabled()); demod->setSquelchEnabled(mgr->isLastSquelchEnabled());
demod->setStereo(mgr->isLastStereo()); demod->setStereo(mgr->isLastStereo());