CubicSDR/src/demod/DemodulatorInstance.cpp

448 lines
14 KiB
C++
Raw Normal View History

#include "DemodulatorInstance.h"
DemodulatorInstance::DemodulatorInstance() :
t_PreDemod(NULL), t_Demod(NULL), t_Audio(NULL) {
2015-07-21 00:59:18 -04:00
terminated.store(true);
audioTerminated.store(true);
demodTerminated.store(true);
preDemodTerminated.store(true);
active.store(false);
squelch.store(false);
stereo.store(false);
muted.store(false);
2015-07-21 00:59:18 -04:00
tracking.store(false);
follow.store(false);
currentAudioSampleRate.store(0);
currentFrequency.store(0);
currentBandwidth.store(0);
currentOutputDevice.store(-1);
currentAudioGain.store(1.0);
2014-12-16 21:30:03 -05:00
label = new std::string("Unnamed");
pipeIQInputData = new DemodulatorThreadInputQueue;
pipeIQDemodData = new DemodulatorThreadPostInputQueue;
pipeDemodCommand = new DemodulatorThreadCommandQueue;
pipeDemodNotify = new DemodulatorThreadCommandQueue;
demodulatorPreThread = new DemodulatorPreThread();
demodulatorPreThread->setInputQueue("IQDataInput",pipeIQInputData);
demodulatorPreThread->setOutputQueue("IQDataOutput",pipeIQDemodData);
demodulatorPreThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
demodulatorPreThread->setInputQueue("CommandQueue",pipeDemodCommand);
2015-08-01 11:03:00 -04:00
pipeAudioData = new AudioThreadInputQueue;
threadQueueControl = new DemodulatorThreadControlCommandQueue;
demodulatorThread = new DemodulatorThread();
demodulatorThread->setInputQueue("IQDataInput",pipeIQDemodData);
demodulatorThread->setInputQueue("ControlQueue",threadQueueControl);
demodulatorThread->setOutputQueue("NotifyQueue",pipeDemodNotify);
2015-08-01 11:03:00 -04:00
demodulatorThread->setOutputQueue("AudioDataOutput", pipeAudioData);
audioThread = new AudioThread();
2015-08-01 11:03:00 -04:00
audioThread->setInputQueue("AudioDataInput", pipeAudioData);
audioThread->setOutputQueue("NotifyQueue", pipeDemodNotify);
2015-01-01 18:08:54 -05:00
currentDemodType = demodulatorThread->getDemodulatorType();
currentDemodCons = demodulatorThread->getDemodulatorCons();
}
DemodulatorInstance::~DemodulatorInstance() {
2014-12-16 21:30:03 -05:00
delete audioThread;
delete demodulatorThread;
2015-01-08 21:12:49 -05:00
delete demodulatorPreThread;
delete pipeIQInputData;
delete pipeIQDemodData;
delete pipeDemodCommand;
delete pipeDemodNotify;
2015-01-08 21:12:49 -05:00
delete threadQueueControl;
2015-08-01 11:03:00 -04:00
delete pipeAudioData;
}
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
demodulatorThread->setOutputQueue("AudioVisualOutput", tQueue);
}
void DemodulatorInstance::run() {
2015-01-08 21:12:49 -05:00
if (active) {
return;
}
// while (!isTerminated()) {
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
// }
currentFrequency = demodulatorPreThread->getParams().frequency;
2015-01-08 21:12:49 -05:00
currentDemodType = demodulatorThread->getDemodulatorType();
currentDemodCons = demodulatorThread->getDemodulatorCons();
currentAudioSampleRate = AudioThread::deviceSampleRate[getOutputDevice()];
demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate;
2014-12-16 21:30:03 -05:00
t_Audio = new std::thread(&AudioThread::threadMain, audioThread);
#ifdef __APPLE__ // Already using pthreads, might as well do some custom init..
2014-12-16 21:30:03 -05:00
pthread_attr_t attr;
size_t size;
2014-12-16 21:30:03 -05:00
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 2048000);
pthread_attr_getstacksize(&attr, &size);
pthread_create(&t_PreDemod, &attr, &DemodulatorPreThread::pthread_helper, demodulatorPreThread);
pthread_attr_destroy(&attr);
2014-12-16 21:30:03 -05:00
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 2048000);
pthread_attr_getstacksize(&attr, &size);
pthread_create(&t_Demod, &attr, &DemodulatorThread::pthread_helper, demodulatorThread);
pthread_attr_destroy(&attr);
2014-12-16 21:30:03 -05:00
std::cout << "Initialized demodulator stack size of " << size << std::endl;
#else
2014-12-16 21:30:03 -05:00
t_PreDemod = new std::thread(&DemodulatorPreThread::threadMain, demodulatorPreThread);
t_Demod = new std::thread(&DemodulatorThread::threadMain, demodulatorThread);
#endif
active = true;
2015-01-08 21:12:49 -05:00
audioTerminated = demodTerminated = preDemodTerminated = terminated = false;
}
void DemodulatorInstance::updateLabel(long long freq) {
2014-12-16 21:30:03 -05:00
std::stringstream newLabel;
newLabel.precision(3);
newLabel << std::fixed << ((long double) freq / 1000000.0);
2014-12-16 21:30:03 -05:00
setLabel(newLabel.str());
}
DemodulatorThreadCommandQueue *DemodulatorInstance::getCommandQueue() {
return pipeDemodCommand;
}
void DemodulatorInstance::terminate() {
2014-12-16 21:30:03 -05:00
std::cout << "Terminating demodulator audio thread.." << std::endl;
audioThread->terminate();
2014-12-24 01:28:33 -05:00
std::cout << "Terminating demodulator thread.." << std::endl;
demodulatorThread->terminate();
std::cout << "Terminating demodulator preprocessor thread.." << std::endl;
demodulatorPreThread->terminate();
}
std::string DemodulatorInstance::getLabel() {
2014-12-16 21:30:03 -05:00
return *(label.load());
}
void DemodulatorInstance::setLabel(std::string labelStr) {
2014-12-16 21:30:03 -05:00
std::string *newLabel = new std::string;
newLabel->append(labelStr);
std::string *oldLabel;
oldLabel = label;
label = newLabel;
delete oldLabel;
}
bool DemodulatorInstance::isTerminated() {
while (!pipeDemodNotify->empty()) {
2014-12-16 21:30:03 -05:00
DemodulatorThreadCommand cmd;
pipeDemodNotify->pop(cmd);
2014-12-16 21:30:03 -05:00
switch (cmd.cmd) {
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_AUDIO_TERMINATED:
t_Audio->join();
audioTerminated = true;
2015-01-22 23:41:33 -05:00
delete t_Audio;
2014-12-16 21:30:03 -05:00
break;
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED:
#ifdef __APPLE__
2014-12-16 21:30:03 -05:00
pthread_join(t_Demod, NULL);
#else
2014-12-16 21:30:03 -05:00
t_Demod->join();
2015-01-22 23:41:33 -05:00
delete t_Demod;
#endif
2014-12-16 21:30:03 -05:00
demodTerminated = true;
break;
case DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED:
#ifdef __APPLE__
2014-12-16 21:30:03 -05:00
pthread_join(t_PreDemod, NULL);
#else
2014-12-16 21:30:03 -05:00
t_PreDemod->join();
2015-01-22 23:41:33 -05:00
delete t_PreDemod;
#endif
2014-12-16 21:30:03 -05:00
preDemodTerminated = true;
break;
default:
break;
}
}
2014-12-16 21:30:03 -05:00
terminated = audioTerminated && demodTerminated && preDemodTerminated;
2014-12-16 21:30:03 -05:00
return terminated;
}
bool DemodulatorInstance::isActive() {
return active;
}
void DemodulatorInstance::setActive(bool state) {
2015-01-08 21:12:49 -05:00
if (active && !state) {
audioThread->setActive(state);
} else if (!active && state) {
audioThread->setActive(state);
}
if (!state) {
tracking = false;
}
active = state;
}
2014-12-26 20:58:42 -05:00
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;
threadQueueControl->push(command);
squelch = true;
}
bool DemodulatorInstance::isSquelchEnabled() {
2015-01-11 03:09:59 -05:00
return (demodulatorThread->getSquelchLevel() != 0.0);
}
void DemodulatorInstance::setSquelchEnabled(bool state) {
if (!state && squelch) {
DemodulatorThreadControlCommand command;
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF;
threadQueueControl->push(command);
} else if (state && !squelch) {
DemodulatorThreadControlCommand command;
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON;
threadQueueControl->push(command);
}
squelch = state;
}
2014-12-31 19:45:01 -05:00
float DemodulatorInstance::getSignalLevel() {
return demodulatorThread->getSignalLevel();
}
void DemodulatorInstance::setSquelchLevel(float signal_level_in) {
demodulatorThread->setSquelchLevel(signal_level_in);
}
float DemodulatorInstance::getSquelchLevel() {
return demodulatorThread->getSquelchLevel();
}
void DemodulatorInstance::setOutputDevice(int device_id) {
2015-01-10 12:27:03 -05:00
if (!active) {
audioThread->setInitOutputDevice(device_id);
} else if (audioThread) {
AudioThreadCommand command;
command.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE;
command.int_value = device_id;
audioThread->getCommandQueue()->push(command);
}
2015-06-27 23:23:43 -04:00
setAudioSampleRate(AudioThread::deviceSampleRate[device_id]);
currentOutputDevice = device_id;
}
int DemodulatorInstance::getOutputDevice() {
if (currentOutputDevice == -1) {
if (audioThread) {
currentOutputDevice = audioThread->getOutputDevice();
}
}
return currentOutputDevice;
}
2015-01-01 03:48:32 -05:00
void DemodulatorInstance::checkBandwidth() {
// if ((currentDemodType == DEMOD_TYPE_USB || currentDemodType == DEMOD_TYPE_LSB) && (getBandwidth() % 2)) {
// setBandwidth(getBandwidth()+1);
// }
}
2015-01-01 18:08:54 -05:00
void DemodulatorInstance::setDemodulatorType(int demod_type_in) {
2015-07-19 15:34:06 -04:00
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());
2015-01-10 12:27:03 -05:00
if (!active) {
checkBandwidth();
demodulatorPreThread->getParams().demodType = currentDemodType;
demodulatorThread->setDemodulatorType(currentDemodType);
} else if (demodulatorThread && threadQueueControl) {
2015-01-01 18:08:54 -05:00
DemodulatorThreadControlCommand command;
command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE;
command.demodType = demod_type_in;
checkBandwidth();
threadQueueControl->push(command);
}
2015-01-01 03:48:32 -05:00
}
2015-01-01 18:08:54 -05:00
int DemodulatorInstance::getDemodulatorType() {
return currentDemodType;
2015-01-01 03:48:32 -05:00
}
2015-06-05 03:51:46 -04:00
void DemodulatorInstance::setDemodulatorLock(bool demod_lock_in) {
demodulatorThread->setDemodulatorLock(demod_lock_in);
2015-06-05 03:51:46 -04:00
}
int DemodulatorInstance::getDemodulatorLock() {
return demodulatorThread->getDemodulatorLock();
2015-06-05 03:51:46 -04:00
}
void DemodulatorInstance::setDemodulatorCons(int demod_cons_in) {
demodulatorThread->setDemodulatorCons(demod_cons_in);
}
int DemodulatorInstance::getDemodulatorCons() {
return demodulatorThread->getDemodulatorCons();
}
void DemodulatorInstance::setBandwidth(int bw) {
2015-06-27 23:23:43 -04:00
if (currentDemodType == DEMOD_TYPE_RAW) {
if (currentAudioSampleRate) {
bw = currentAudioSampleRate;
} else {
bw = AudioThread::deviceSampleRate[getOutputDevice()];
}
}
if (!active && demodulatorPreThread != NULL) {
2015-01-10 12:27:03 -05:00
currentBandwidth = bw;
checkBandwidth();
demodulatorPreThread->getParams().bandwidth = currentBandwidth;
} else if (demodulatorPreThread && pipeDemodCommand) {
DemodulatorThreadCommand command;
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_BANDWIDTH;
currentBandwidth = bw;
checkBandwidth();
command.llong_value = currentBandwidth;
pipeDemodCommand->push(command);
}
}
int DemodulatorInstance::getBandwidth() {
if (!currentBandwidth) {
currentBandwidth = demodulatorPreThread->getParams().bandwidth;
}
return currentBandwidth;
}
void DemodulatorInstance::setFrequency(long long freq) {
2015-01-10 12:27:03 -05:00
if ((freq - getBandwidth() / 2) <= 0) {
freq = getBandwidth() / 2;
}
2015-01-10 12:27:03 -05:00
if (!active) {
currentFrequency = freq;
demodulatorPreThread->getParams().frequency = currentFrequency;
} else if (demodulatorPreThread && pipeDemodCommand) {
2015-01-10 12:27:03 -05:00
DemodulatorThreadCommand command;
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY;
currentFrequency = freq;
command.llong_value = freq;
pipeDemodCommand->push(command);
2015-01-10 12:27:03 -05:00
}
}
long long DemodulatorInstance::getFrequency() {
if (!currentFrequency) {
currentFrequency = demodulatorPreThread->getParams().frequency;
}
return currentFrequency;
}
2015-01-10 20:33:30 -05:00
void DemodulatorInstance::setAudioSampleRate(int sampleRate) {
if (terminated) {
currentAudioSampleRate = sampleRate;
demodulatorPreThread->getParams().audioSampleRate = sampleRate;
} else if (demodulatorPreThread && pipeDemodCommand) {
DemodulatorThreadCommand command;
command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE;
currentAudioSampleRate = sampleRate;
command.llong_value = sampleRate;
pipeDemodCommand->push(command);
}
2015-06-27 23:23:43 -04:00
if (currentDemodType == DEMOD_TYPE_RAW) {
setBandwidth(currentAudioSampleRate);
}
}
int DemodulatorInstance::getAudioSampleRate() {
if (!currentAudioSampleRate) {
currentAudioSampleRate = audioThread->getSampleRate();
}
return currentAudioSampleRate;
}
2015-01-10 20:33:30 -05:00
void DemodulatorInstance::setGain(float gain_in) {
2015-07-19 15:34:06 -04:00
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);
}
2015-01-10 20:33:30 -05:00
}
float DemodulatorInstance::getGain() {
2015-07-19 15:34:06 -04:00
return currentAudioGain;
2015-01-10 20:33:30 -05:00
}
2015-03-26 22:45:52 -04:00
bool DemodulatorInstance::isFollow() {
return follow;
}
void DemodulatorInstance::setFollow(bool follow) {
this->follow = follow;
}
bool DemodulatorInstance::isTracking() {
return tracking;
}
void DemodulatorInstance::setTracking(bool tracking) {
this->tracking = tracking;
}
bool DemodulatorInstance::isMuted() {
return demodulatorThread->isMuted();
}
void DemodulatorInstance::setMuted(bool muted) {
this->muted = muted;
demodulatorThread->setMuted(muted);
}
DemodulatorThreadInputQueue *DemodulatorInstance::getIQInputDataPipe() {
return pipeIQInputData;
}