2014-11-30 23:33:55 -05:00
|
|
|
#include "DemodulatorWorkerThread.h"
|
|
|
|
#include "CubicSDRDefs.h"
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
DemodulatorWorkerThread::DemodulatorWorkerThread(DemodulatorThreadWorkerCommandQueue* in, DemodulatorThreadWorkerResultQueue* out) :
|
|
|
|
terminated(false), commandQueue(in), resultQueue(out) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
DemodulatorWorkerThread::~DemodulatorWorkerThread() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void DemodulatorWorkerThread::threadMain() {
|
|
|
|
|
|
|
|
std::cout << "Demodulator worker thread started.." << std::endl;
|
|
|
|
|
|
|
|
while (!terminated) {
|
|
|
|
bool filterChanged = false;
|
|
|
|
DemodulatorWorkerThreadCommand filterCommand;
|
|
|
|
DemodulatorWorkerThreadCommand command;
|
|
|
|
|
|
|
|
bool done = false;
|
|
|
|
while (!done) {
|
|
|
|
commandQueue->pop(command);
|
|
|
|
switch (command.cmd) {
|
|
|
|
case DemodulatorWorkerThreadCommand::DEMOD_WORKER_THREAD_CMD_BUILD_FILTERS:
|
|
|
|
filterChanged = true;
|
|
|
|
filterCommand = command;
|
|
|
|
break;
|
2015-01-20 19:13:49 -05:00
|
|
|
default:
|
|
|
|
break;
|
2014-11-30 23:33:55 -05:00
|
|
|
}
|
|
|
|
done = commandQueue->empty();
|
|
|
|
}
|
2015-01-22 23:41:33 -05:00
|
|
|
|
2014-11-30 23:33:55 -05:00
|
|
|
|
2015-01-11 20:26:51 -05:00
|
|
|
if (filterChanged && !terminated) {
|
2014-12-01 02:10:36 -05:00
|
|
|
DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS);
|
2014-11-30 23:33:55 -05:00
|
|
|
|
|
|
|
float As = 60.0f; // stop-band attenuation [dB]
|
|
|
|
|
2015-01-23 02:09:37 -05:00
|
|
|
if (filterCommand.sampleRate && filterCommand.bandwidth) {
|
|
|
|
result.iqResampleRatio = (double) (filterCommand.bandwidth) / (double) filterCommand.sampleRate;
|
|
|
|
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;
|
2015-03-15 21:02:26 -04:00
|
|
|
|
|
|
|
// Stereo filters / shifters
|
2015-06-05 20:58:10 -04:00
|
|
|
double firStereoCutoff = ((double) 16000 / (double) filterCommand.audioSampleRate);
|
|
|
|
float ft = ((double) 1000 / (double) filterCommand.audioSampleRate); // filter transition
|
2015-03-15 21:02:26 -04:00
|
|
|
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);
|
2015-06-05 00:28:32 -04:00
|
|
|
|
2015-06-05 20:58:10 -04:00
|
|
|
// stereo pilot filter
|
|
|
|
unsigned int order = 5; // filter order
|
2015-06-05 00:28:32 -04:00
|
|
|
float f0 = ((double) 19000 / (double) filterCommand.bandwidth);
|
2015-06-05 20:58:10 -04:00
|
|
|
float fc = ((double) 19500 / (double) filterCommand.bandwidth);
|
2015-06-05 00:28:32 -04:00
|
|
|
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);
|
2015-01-23 02:09:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (filterCommand.bandwidth) {
|
|
|
|
result.bandwidth = filterCommand.bandwidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (filterCommand.sampleRate) {
|
|
|
|
result.sampleRate = filterCommand.sampleRate;
|
|
|
|
}
|
2014-12-01 02:10:36 -05:00
|
|
|
|
2014-11-30 23:33:55 -05:00
|
|
|
resultQueue->push(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << "Demodulator worker thread done." << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DemodulatorWorkerThread::terminate() {
|
|
|
|
terminated = true;
|
|
|
|
DemodulatorWorkerThreadCommand inp; // push dummy to nudge queue
|
|
|
|
commandQueue->push(inp);
|
|
|
|
}
|