Demodulator garbage collection

This commit is contained in:
Charles J. Cliffe 2014-12-11 19:07:21 -05:00
parent 4d35075655
commit f04ec72394
10 changed files with 225 additions and 168 deletions

View File

@ -153,6 +153,7 @@ SET (cubicsdr_headers
src/demod/DemodulatorThread.h src/demod/DemodulatorThread.h
src/demod/DemodulatorWorkerThread.h src/demod/DemodulatorWorkerThread.h
src/demod/DemodulatorMgr.h src/demod/DemodulatorMgr.h
src/demod/DemodDefs.h
src/audio/AudioThread.h src/audio/AudioThread.h
src/util/Gradient.h src/util/Gradient.h
src/util/Timer.h src/util/Timer.h

View File

@ -1,9 +1,10 @@
#include "AudioThread.h" #include "AudioThread.h"
#include "CubicSDRDefs.h" #include "CubicSDRDefs.h"
#include <vector> #include <vector>
#include "DemodulatorThread.h"
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue) : AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) :
inputQueue(inputQueue), terminated(false), audio_queue_ptr(0), underflow_count(0) { inputQueue(inputQueue), terminated(false), audio_queue_ptr(0), underflow_count(0), threadQueueNotify(threadQueueNotify) {
} }
@ -135,6 +136,10 @@ void AudioThread::threadMain() {
} }
std::cout << "Audio thread done." << std::endl; std::cout << "Audio thread done." << std::endl;
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED);
tCmd.context = this;
threadQueueNotify->push(tCmd);
} }
void AudioThread::terminate() { void AudioThread::terminate() {

View File

@ -15,6 +15,7 @@
#include "AudioThread.h" #include "AudioThread.h"
#include "ThreadQueue.h" #include "ThreadQueue.h"
#include "RtAudio.h" #include "RtAudio.h"
#include "DemodDefs.h"
class AudioThreadInput { class AudioThreadInput {
public: public:
@ -32,7 +33,7 @@ public:
std::atomic<unsigned int> audio_queue_ptr; std::atomic<unsigned int> audio_queue_ptr;
std::atomic<unsigned int> underflow_count; std::atomic<unsigned int> underflow_count;
AudioThread(AudioThreadInputQueue *inputQueue); AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify);
~AudioThread(); ~AudioThread();
void threadMain(); void threadMain();
@ -42,5 +43,6 @@ private:
AudioThreadInputQueue *inputQueue; AudioThreadInputQueue *inputQueue;
RtAudio dac; RtAudio dac;
std::atomic<bool> terminated; std::atomic<bool> terminated;
DemodulatorThreadCommandQueue* threadQueueNotify;
}; };

87
src/demod/DemodDefs.h Normal file
View File

@ -0,0 +1,87 @@
#pragma once
#include "ThreadQueue.h"
enum DemodulatorType {
DEMOD_TYPE_NULL,
DEMOD_TYPE_AM,
DEMOD_TYPE_FM,
DEMOD_TYPE_LSB,
DEMOD_TYPE_USB
};
class DemodulatorThread;
class DemodulatorThreadCommand {
public:
enum DemodulatorThreadCommandEnum {
DEMOD_THREAD_CMD_NULL,
DEMOD_THREAD_CMD_SET_BANDWIDTH,
DEMOD_THREAD_CMD_SET_FREQUENCY,
DEMOD_THREAD_CMD_DEMOD_TERMINATED,
DEMOD_THREAD_CMD_AUDIO_TERMINATED
};
DemodulatorThreadCommand() :
cmd(DEMOD_THREAD_CMD_NULL), int_value(0), context(NULL) {
}
DemodulatorThreadCommand(DemodulatorThreadCommandEnum cmd) :
cmd(cmd), int_value(0), context(NULL) {
}
DemodulatorThreadCommandEnum cmd;
void *context;
int int_value;
};
class DemodulatorThreadIQData {
public:
unsigned int frequency;
unsigned int bandwidth;
std::vector<signed char> data;
DemodulatorThreadIQData() :
frequency(0), bandwidth(0) {
}
DemodulatorThreadIQData(unsigned int bandwidth, unsigned int frequency,
std::vector<signed char> data) :
data(data), frequency(frequency), bandwidth(bandwidth) {
}
~DemodulatorThreadIQData() {
}
};
class DemodulatorThreadAudioData {
public:
unsigned int frequency;
unsigned int sampleRate;
unsigned char channels;
std::vector<float> data;
DemodulatorThreadAudioData() :
sampleRate(0), frequency(0), channels(0) {
}
DemodulatorThreadAudioData(unsigned int frequency, unsigned int sampleRate,
std::vector<float> data) :
data(data), sampleRate(sampleRate), frequency(frequency), channels(
1) {
}
~DemodulatorThreadAudioData() {
}
};
typedef ThreadQueue<DemodulatorThreadIQData> DemodulatorThreadInputQueue;
typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue;

View File

@ -4,28 +4,29 @@
#include "CubicSDR.h" #include "CubicSDR.h"
DemodulatorInstance::DemodulatorInstance() : DemodulatorInstance::DemodulatorInstance() :
t_Demod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL) { t_Demod(NULL), t_Audio(NULL), threadQueueDemod(NULL), demodulatorThread(NULL), terminated(false), audioTerminated(false), demodTerminated(
false) {
threadQueueDemod = new DemodulatorThreadInputQueue; threadQueueDemod = new DemodulatorThreadInputQueue;
threadQueueCommand = new DemodulatorThreadCommandQueue; threadQueueCommand = new DemodulatorThreadCommandQueue;
demodulatorThread = new DemodulatorThread(threadQueueDemod); threadQueueNotify = new DemodulatorThreadCommandQueue;
demodulatorThread = new DemodulatorThread(threadQueueDemod, threadQueueNotify);
demodulatorThread->setCommandQueue(threadQueueCommand); demodulatorThread->setCommandQueue(threadQueueCommand);
audioInputQueue = new AudioThreadInputQueue; audioInputQueue = new AudioThreadInputQueue;
audioThread = new AudioThread(audioInputQueue); audioThread = new AudioThread(audioInputQueue, threadQueueNotify);
demodulatorThread->setAudioInputQueue(audioInputQueue); demodulatorThread->setAudioInputQueue(audioInputQueue);
} }
DemodulatorInstance::~DemodulatorInstance() { DemodulatorInstance::~DemodulatorInstance() {
delete audioThread; delete audioThread;
delete t_Audio; delete demodulatorThread;
delete audioInputQueue; delete audioInputQueue;
delete threadQueueDemod; delete threadQueueDemod;
delete demodulatorThread;
#ifndef __APPLE__ #ifndef __APPLE__
delete t_Demod; // delete t_Demod;
#endif #endif
// delete t_Audio;
} }
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) { void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
@ -33,27 +34,6 @@ void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQu
} }
void DemodulatorInstance::run() { void DemodulatorInstance::run() {
if (t_Demod) {
terminate();
delete threadQueueDemod;
delete demodulatorThread;
delete t_Demod;
delete audioThread;
delete audioInputQueue;
delete t_Audio;
threadQueueDemod = new DemodulatorThreadInputQueue;
threadQueueCommand = new DemodulatorThreadCommandQueue;
demodulatorThread = new DemodulatorThread(threadQueueDemod);
demodulatorThread->setCommandQueue(threadQueueCommand);
audioInputQueue = new AudioThreadInputQueue;
audioThread = new AudioThread(audioInputQueue);
demodulatorThread->setAudioInputQueue(audioInputQueue);
}
t_Audio = new std::thread(&AudioThread::threadMain, audioThread); t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
#ifdef __APPLE__ // Already using pthreads, might as well do some custom init.. #ifdef __APPLE__ // Already using pthreads, might as well do some custom init..
@ -124,8 +104,7 @@ DemodulatorInstance *DemodulatorMgr::newThread() {
void DemodulatorMgr::terminateAll() { void DemodulatorMgr::terminateAll() {
while (demods.size()) { while (demods.size()) {
DemodulatorInstance *d = demods.back(); DemodulatorInstance *d = demods.back();
demods.pop_back(); deleteThread(d);
d->terminate();
} }
} }
@ -136,7 +115,7 @@ std::vector<DemodulatorInstance *> &DemodulatorMgr::getDemodulators() {
void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) { void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
std::vector<DemodulatorInstance *>::iterator i; std::vector<DemodulatorInstance *>::iterator i;
i = std::find(demods.begin(),demods.end(),demod); i = std::find(demods.begin(), demods.end(), demod);
if (activeDemodulator == demod) { if (activeDemodulator == demod) {
activeDemodulator = NULL; activeDemodulator = NULL;
@ -152,6 +131,10 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
demods.erase(i); demods.erase(i);
demod->terminate(); demod->terminate();
} }
demods_deleted.push_back(demod);
garbageCollect();
} }
std::vector<DemodulatorInstance *> *DemodulatorMgr::getDemodulatorsAt(int freq, int bandwidth) { std::vector<DemodulatorInstance *> *DemodulatorMgr::getDemodulatorsAt(int freq, int bandwidth) {
@ -197,8 +180,9 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo
activeVisualDemodulator = last; activeVisualDemodulator = last;
} }
activeDemodulator = demod; activeDemodulator = demod;
garbageCollect();
} }
DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() { DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() {
@ -212,3 +196,48 @@ DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() {
return lastActiveDemodulator; return lastActiveDemodulator;
} }
void DemodulatorMgr::garbageCollect() {
if (demods_deleted.size()) {
std::vector<DemodulatorInstance *>::iterator i;
for (i = demods_deleted.begin(); i != demods_deleted.end(); i++) {
if ((*i)->isTerminated()) {
DemodulatorInstance *deleted = (*i);
demods_deleted.erase(i);
std::cout << "Garbage collected demodulator instance " << deleted->getLabel() << std::endl;
delete deleted;
return;
}
}
}
}
bool DemodulatorInstance::isTerminated() {
while (!threadQueueNotify->empty()) {
DemodulatorThreadCommand cmd;
threadQueueNotify->pop(cmd);
switch (cmd.cmd) {
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED:
audioThread = NULL;
t_Audio->join();
audioTerminated = true;
break;
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED:
demodulatorThread = NULL;
t_Demod->join();
demodTerminated = true;
break;
default:
break;
}
}
terminated = audioTerminated && demodTerminated;
return terminated;
}

View File

@ -11,6 +11,7 @@ public:
DemodulatorThreadInputQueue* threadQueueDemod; DemodulatorThreadInputQueue* threadQueueDemod;
DemodulatorThreadCommandQueue* threadQueueCommand; DemodulatorThreadCommandQueue* threadQueueCommand;
DemodulatorThreadCommandQueue* threadQueueNotify;
DemodulatorThread *demodulatorThread; DemodulatorThread *demodulatorThread;
#ifdef __APPLE__ #ifdef __APPLE__
pthread_t t_Demod; pthread_t t_Demod;
@ -35,8 +36,13 @@ public:
std::string getLabel(); std::string getLabel();
void setLabel(std::string labelStr); void setLabel(std::string labelStr);
bool isTerminated();
private: private:
std::string label; std::string label;
bool terminated;
bool demodTerminated;
bool audioTerminated;
}; };
class DemodulatorMgr { class DemodulatorMgr {
@ -56,8 +62,12 @@ public:
DemodulatorInstance *getLastActiveDemodulator(); DemodulatorInstance *getLastActiveDemodulator();
private: private:
void garbageCollect();
std::vector<DemodulatorInstance *> demods; std::vector<DemodulatorInstance *> demods;
std::vector<DemodulatorInstance *> demods_deleted;
DemodulatorInstance *activeDemodulator; DemodulatorInstance *activeDemodulator;
DemodulatorInstance *lastActiveDemodulator; DemodulatorInstance *lastActiveDemodulator;
DemodulatorInstance *activeVisualDemodulator; DemodulatorInstance *activeVisualDemodulator;
}; };

View File

@ -3,12 +3,12 @@
#include <vector> #include <vector>
#ifdef __APPLE__ #ifdef __APPLE__
#include <pthread.h> #include <pthread.h>
#endif #endif
DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue) : DemodulatorThread::DemodulatorThread(DemodulatorThreadInputQueue* pQueue, DemodulatorThreadCommandQueue* threadQueueNotify) :
inputQueue(pQueue), visOutQueue(NULL), terminated(false), initialized(false), audio_resampler(NULL), resample_ratio(1), audio_resample_ratio( inputQueue(pQueue), visOutQueue(NULL), terminated(false), initialized(false), audio_resampler(NULL), resample_ratio(1), audio_resample_ratio(
1), resampler(NULL), commandQueue(NULL), fir_filter(NULL), audioInputQueue(NULL) { 1), resampler(NULL), commandQueue(NULL), fir_filter(NULL), audioInputQueue(NULL), threadQueueNotify(threadQueueNotify) {
float kf = 0.5; // modulation factor float kf = 0.5; // modulation factor
fdem = freqdem_create(kf); fdem = freqdem_create(kf);
@ -249,6 +249,9 @@ void DemodulatorThread::threadMain() {
} }
std::cout << "Demodulator thread done." << std::endl; std::cout << "Demodulator thread done." << std::endl;
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED);
tCmd.context = this;
threadQueueNotify->push(tCmd);
} }
void DemodulatorThread::terminate() { void DemodulatorThread::terminate() {

View File

@ -11,116 +11,36 @@
#include "wx/thread.h" #include "wx/thread.h"
#include "liquid/liquid.h" #include "liquid/liquid.h"
#include "AudioThread.h"
#include "ThreadQueue.h"
#include "CubicSDRDefs.h" #include "CubicSDRDefs.h"
#include "DemodulatorWorkerThread.h" #include "DemodulatorWorkerThread.h"
#include "DemodDefs.h"
enum DemodulatorType {
DEMOD_TYPE_NULL,
DEMOD_TYPE_AM,
DEMOD_TYPE_FM,
DEMOD_TYPE_LSB,
DEMOD_TYPE_USB
};
class DemodulatorThreadCommand {
public:
enum DemodulatorThreadCommandEnum {
DEMOD_THREAD_CMD_NULL,
DEMOD_THREAD_CMD_SET_BANDWIDTH,
DEMOD_THREAD_CMD_SET_FREQUENCY
};
DemodulatorThreadCommand() :
cmd(DEMOD_THREAD_CMD_NULL), int_value(0) {
}
DemodulatorThreadCommand(DemodulatorThreadCommandEnum cmd) :
cmd(cmd), int_value(0) {
}
DemodulatorThreadCommandEnum cmd;
int int_value;
};
class DemodulatorThreadIQData {
public:
unsigned int frequency;
unsigned int bandwidth;
std::vector<signed char> data;
DemodulatorThreadIQData() :
frequency(0), bandwidth(0) {
}
DemodulatorThreadIQData(unsigned int bandwidth, unsigned int frequency,
std::vector<signed char> data) :
data(data), frequency(frequency), bandwidth(bandwidth) {
}
~DemodulatorThreadIQData() {
}
};
class DemodulatorThreadAudioData {
public:
unsigned int frequency;
unsigned int sampleRate;
unsigned char channels;
std::vector<float> data;
DemodulatorThreadAudioData() :
sampleRate(0), frequency(0), channels(0) {
}
DemodulatorThreadAudioData(unsigned int frequency, unsigned int sampleRate,
std::vector<float> data) :
data(data), sampleRate(sampleRate), frequency(frequency), channels(
1) {
}
~DemodulatorThreadAudioData() {
}
};
class DemodulatorThreadParameters { class DemodulatorThreadParameters {
public: public:
unsigned int frequency; unsigned int frequency;
unsigned int inputRate; unsigned int inputRate;
unsigned int bandwidth; // set equal to disable second stage re-sampling? unsigned int bandwidth; // set equal to disable second stage re-sampling?
unsigned int audioSampleRate; unsigned int audioSampleRate;
DemodulatorType demodType; DemodulatorType demodType;
DemodulatorThreadParameters() : DemodulatorThreadParameters() :
frequency(0), inputRate(SRATE), bandwidth(200000), audioSampleRate( frequency(0), inputRate(SRATE), bandwidth(200000), audioSampleRate(
AUDIO_FREQUENCY), demodType(DEMOD_TYPE_FM) { AUDIO_FREQUENCY), demodType(DEMOD_TYPE_FM) {
} }
~DemodulatorThreadParameters() { ~DemodulatorThreadParameters() {
} }
}; };
typedef ThreadQueue<DemodulatorThreadIQData> DemodulatorThreadInputQueue;
typedef ThreadQueue<AudioThreadInput> DemodulatorThreadOutputQueue; typedef ThreadQueue<AudioThreadInput> DemodulatorThreadOutputQueue;
typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue;
class DemodulatorThread { class DemodulatorThread {
public: public:
DemodulatorThread(DemodulatorThreadInputQueue* pQueue); DemodulatorThread(DemodulatorThreadInputQueue* pQueue, DemodulatorThreadCommandQueue* threadQueueNotify);
~DemodulatorThread(); ~DemodulatorThread();
#ifdef __APPLE__ #ifdef __APPLE__
@ -184,4 +104,5 @@ protected:
DemodulatorThreadWorkerCommandQueue *workerQueue; DemodulatorThreadWorkerCommandQueue *workerQueue;
DemodulatorThreadWorkerResultQueue *workerResults; DemodulatorThreadWorkerResultQueue *workerResults;
DemodulatorThreadCommandQueue* threadQueueNotify;
}; };

View File

@ -4,13 +4,38 @@
#include "CubicSDR.h" #include "CubicSDR.h"
SDRPostThread::SDRPostThread() : SDRPostThread::SDRPostThread() :
iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false) { iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false), dcFilter(NULL), sample_rate(SRATE) {
dev = NULL;
sample_rate = SRATE;
} }
SDRPostThread::~SDRPostThread() { SDRPostThread::~SDRPostThread() {
rtlsdr_close(dev); }
void SDRPostThread::bindDemodulator(DemodulatorInstance *demod) {
demodulators.push_back(demod);
}
void SDRPostThread::removeDemodulator(DemodulatorInstance *demod) {
if (!demod) {
return;
}
std::vector<DemodulatorInstance *>::iterator i;
i = std::find(demodulators.begin(), demodulators.end(), demod);
if (i != demodulators.end()) {
demodulators.erase(i);
}
}
void SDRPostThread::setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue) {
iqDataInQueue = iqDataQueue;
}
void SDRPostThread::setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue) {
iqDataOutQueue = iqDataQueue;
}
void SDRPostThread::setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue) {
iqVisualQueue = iqVisQueue;
} }
void SDRPostThread::threadMain() { void SDRPostThread::threadMain() {

View File

@ -5,47 +5,21 @@
class SDRPostThread { class SDRPostThread {
public: public:
rtlsdr_dev_t *dev;
SDRPostThread(); SDRPostThread();
~SDRPostThread(); ~SDRPostThread();
int enumerate_rtl(); void bindDemodulator(DemodulatorInstance *demod);
void removeDemodulator(DemodulatorInstance *demod);
void bindDemodulator(DemodulatorInstance *demod) { void setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue);
demodulators.push_back(demod); void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue);
} void setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue);
void removeDemodulator(DemodulatorInstance *demod) {
if (!demod) {
return;
}
std::vector<DemodulatorInstance *>::iterator i;
i = std::find(demodulators.begin(), demodulators.end(), demod);
if (i != demodulators.end()) {
demodulators.erase(i);
}
}
void threadMain(); void threadMain();
void setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue) {
iqDataInQueue = iqDataQueue;
}
void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue) {
iqDataOutQueue = iqDataQueue;
}
void setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue) {
iqVisualQueue = iqVisQueue;
}
void terminate(); void terminate();
protected:
uint32_t sample_rate; protected:
uint32_t sample_rate;
std::atomic<SDRThreadIQDataQueue*> iqDataOutQueue; std::atomic<SDRThreadIQDataQueue*> iqDataOutQueue;
std::atomic<SDRThreadIQDataQueue*> iqDataInQueue; std::atomic<SDRThreadIQDataQueue*> iqDataInQueue;