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/DemodulatorWorkerThread.h
src/demod/DemodulatorMgr.h
src/demod/DemodDefs.h
src/audio/AudioThread.h
src/util/Gradient.h
src/util/Timer.h

View File

@ -1,9 +1,10 @@
#include "AudioThread.h"
#include "CubicSDRDefs.h"
#include <vector>
#include "DemodulatorThread.h"
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue) :
inputQueue(inputQueue), terminated(false), audio_queue_ptr(0), underflow_count(0) {
AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) :
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;
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED);
tCmd.context = this;
threadQueueNotify->push(tCmd);
}
void AudioThread::terminate() {

View File

@ -15,6 +15,7 @@
#include "AudioThread.h"
#include "ThreadQueue.h"
#include "RtAudio.h"
#include "DemodDefs.h"
class AudioThreadInput {
public:
@ -32,7 +33,7 @@ public:
std::atomic<unsigned int> audio_queue_ptr;
std::atomic<unsigned int> underflow_count;
AudioThread(AudioThreadInputQueue *inputQueue);
AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify);
~AudioThread();
void threadMain();
@ -42,5 +43,6 @@ private:
AudioThreadInputQueue *inputQueue;
RtAudio dac;
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"
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;
threadQueueCommand = new DemodulatorThreadCommandQueue;
demodulatorThread = new DemodulatorThread(threadQueueDemod);
threadQueueNotify = new DemodulatorThreadCommandQueue;
demodulatorThread = new DemodulatorThread(threadQueueDemod, threadQueueNotify);
demodulatorThread->setCommandQueue(threadQueueCommand);
audioInputQueue = new AudioThreadInputQueue;
audioThread = new AudioThread(audioInputQueue);
audioThread = new AudioThread(audioInputQueue, threadQueueNotify);
demodulatorThread->setAudioInputQueue(audioInputQueue);
}
DemodulatorInstance::~DemodulatorInstance() {
delete audioThread;
delete t_Audio;
delete demodulatorThread;
delete audioInputQueue;
delete threadQueueDemod;
delete demodulatorThread;
#ifndef __APPLE__
delete t_Demod;
// delete t_Demod;
#endif
// delete t_Audio;
}
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
@ -33,27 +34,6 @@ void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQu
}
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);
#ifdef __APPLE__ // Already using pthreads, might as well do some custom init..
@ -124,8 +104,7 @@ DemodulatorInstance *DemodulatorMgr::newThread() {
void DemodulatorMgr::terminateAll() {
while (demods.size()) {
DemodulatorInstance *d = demods.back();
demods.pop_back();
d->terminate();
deleteThread(d);
}
}
@ -136,7 +115,7 @@ std::vector<DemodulatorInstance *> &DemodulatorMgr::getDemodulators() {
void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
std::vector<DemodulatorInstance *>::iterator i;
i = std::find(demods.begin(),demods.end(),demod);
i = std::find(demods.begin(), demods.end(), demod);
if (activeDemodulator == demod) {
activeDemodulator = NULL;
@ -152,6 +131,10 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
demods.erase(i);
demod->terminate();
}
demods_deleted.push_back(demod);
garbageCollect();
}
std::vector<DemodulatorInstance *> *DemodulatorMgr::getDemodulatorsAt(int freq, int bandwidth) {
@ -197,8 +180,9 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo
activeVisualDemodulator = last;
}
activeDemodulator = demod;
garbageCollect();
}
DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() {
@ -212,3 +196,48 @@ DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() {
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;
DemodulatorThreadCommandQueue* threadQueueCommand;
DemodulatorThreadCommandQueue* threadQueueNotify;
DemodulatorThread *demodulatorThread;
#ifdef __APPLE__
pthread_t t_Demod;
@ -35,8 +36,13 @@ public:
std::string getLabel();
void setLabel(std::string labelStr);
bool isTerminated();
private:
std::string label;
bool terminated;
bool demodTerminated;
bool audioTerminated;
};
class DemodulatorMgr {
@ -56,8 +62,12 @@ public:
DemodulatorInstance *getLastActiveDemodulator();
private:
void garbageCollect();
std::vector<DemodulatorInstance *> demods;
std::vector<DemodulatorInstance *> demods_deleted;
DemodulatorInstance *activeDemodulator;
DemodulatorInstance *lastActiveDemodulator;
DemodulatorInstance *activeVisualDemodulator;
};

View File

@ -3,12 +3,12 @@
#include <vector>
#ifdef __APPLE__
#include <pthread.h>
#include <pthread.h>
#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(
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
fdem = freqdem_create(kf);
@ -249,6 +249,9 @@ void DemodulatorThread::threadMain() {
}
std::cout << "Demodulator thread done." << std::endl;
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED);
tCmd.context = this;
threadQueueNotify->push(tCmd);
}
void DemodulatorThread::terminate() {

View File

@ -11,116 +11,36 @@
#include "wx/thread.h"
#include "liquid/liquid.h"
#include "AudioThread.h"
#include "ThreadQueue.h"
#include "CubicSDRDefs.h"
#include "DemodulatorWorkerThread.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() {
}
};
#include "DemodDefs.h"
class DemodulatorThreadParameters {
public:
unsigned int frequency;
unsigned int inputRate;
unsigned int bandwidth; // set equal to disable second stage re-sampling?
unsigned int audioSampleRate;
unsigned int frequency;
unsigned int inputRate;
unsigned int bandwidth; // set equal to disable second stage re-sampling?
unsigned int audioSampleRate;
DemodulatorType demodType;
DemodulatorType demodType;
DemodulatorThreadParameters() :
frequency(0), inputRate(SRATE), bandwidth(200000), audioSampleRate(
AUDIO_FREQUENCY), demodType(DEMOD_TYPE_FM) {
DemodulatorThreadParameters() :
frequency(0), inputRate(SRATE), bandwidth(200000), audioSampleRate(
AUDIO_FREQUENCY), demodType(DEMOD_TYPE_FM) {
}
}
~DemodulatorThreadParameters() {
~DemodulatorThreadParameters() {
}
}
};
typedef ThreadQueue<DemodulatorThreadIQData> DemodulatorThreadInputQueue;
typedef ThreadQueue<AudioThreadInput> DemodulatorThreadOutputQueue;
typedef ThreadQueue<DemodulatorThreadCommand> DemodulatorThreadCommandQueue;
class DemodulatorThread {
public:
DemodulatorThread(DemodulatorThreadInputQueue* pQueue);
DemodulatorThread(DemodulatorThreadInputQueue* pQueue, DemodulatorThreadCommandQueue* threadQueueNotify);
~DemodulatorThread();
#ifdef __APPLE__
@ -184,4 +104,5 @@ protected:
DemodulatorThreadWorkerCommandQueue *workerQueue;
DemodulatorThreadWorkerResultQueue *workerResults;
DemodulatorThreadCommandQueue* threadQueueNotify;
};

View File

@ -4,13 +4,38 @@
#include "CubicSDR.h"
SDRPostThread::SDRPostThread() :
iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false) {
dev = NULL;
sample_rate = SRATE;
iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false), dcFilter(NULL), sample_rate(SRATE) {
}
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() {

View File

@ -5,47 +5,21 @@
class SDRPostThread {
public:
rtlsdr_dev_t *dev;
SDRPostThread();
~SDRPostThread();
int enumerate_rtl();
void bindDemodulator(DemodulatorInstance *demod);
void removeDemodulator(DemodulatorInstance *demod);
void bindDemodulator(DemodulatorInstance *demod) {
demodulators.push_back(demod);
}
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 setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue);
void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue);
void setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue);
void threadMain();
void setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue) {
iqDataInQueue = iqDataQueue;
}
void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue) {
iqDataOutQueue = iqDataQueue;
}
void setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue) {
iqVisualQueue = iqVisQueue;
}
void terminate();
protected:
uint32_t sample_rate;
protected:
uint32_t sample_rate;
std::atomic<SDRThreadIQDataQueue*> iqDataOutQueue;
std::atomic<SDRThreadIQDataQueue*> iqDataInQueue;