2014-12-16 18:27:32 -05:00
|
|
|
#include "CubicSDRDefs.h"
|
2015-02-22 01:01:28 -05:00
|
|
|
#include "DemodulatorThread.h"
|
2014-12-16 18:27:32 -05:00
|
|
|
#include <vector>
|
|
|
|
|
2015-02-22 01:01:28 -05:00
|
|
|
#include <cmath>
|
|
|
|
#ifndef M_PI
|
|
|
|
#define M_PI 3.14159265358979323846
|
|
|
|
#endif
|
|
|
|
|
2014-12-16 18:27:32 -05:00
|
|
|
#ifdef __APPLE__
|
|
|
|
#include <pthread.h>
|
|
|
|
#endif
|
|
|
|
|
2015-07-30 00:28:53 -04:00
|
|
|
DemodulatorThread::DemodulatorThread() : IOThread(), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA(1), audioSampleRate(0), squelchLevel(0), signalLevel(0), squelchEnabled(false), iqInputQueue(NULL), audioOutputQueue(NULL), audioVisOutputQueue(NULL), threadQueueControl(NULL), threadQueueNotify(NULL) {
|
2014-12-16 18:27:32 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// stereo.store(false);
|
2015-08-17 00:59:38 -04:00
|
|
|
muted.store(false);
|
2015-07-21 00:59:18 -04:00
|
|
|
agcEnabled.store(false);
|
2015-11-17 18:57:42 -05:00
|
|
|
demodulatorType = "FM";
|
2015-07-21 00:59:18 -04:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// demodFM = freqdem_create(0.5);
|
|
|
|
// demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1);
|
|
|
|
// demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1);
|
|
|
|
// demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1);
|
|
|
|
// demodAM_DSB_CSP = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
|
|
|
// demodAM = demodAM_DSB_CSP;
|
2015-06-03 05:23:16 -04:00
|
|
|
|
|
|
|
// advanced demodulators
|
2015-06-10 04:50:14 -04:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
/* demodulatorCons.store(2);
|
2015-06-10 13:39:08 -04:00
|
|
|
currentDemodCons = 0;
|
|
|
|
|
|
|
|
demodASK = demodASK2;
|
2015-06-10 04:50:14 -04:00
|
|
|
demodASK2 = modem_create(LIQUID_MODEM_ASK2);
|
|
|
|
demodASK4 = modem_create(LIQUID_MODEM_ASK4);
|
|
|
|
demodASK8 = modem_create(LIQUID_MODEM_ASK8);
|
|
|
|
demodASK16 = modem_create(LIQUID_MODEM_ASK16);
|
|
|
|
demodASK32 = modem_create(LIQUID_MODEM_ASK32);
|
|
|
|
demodASK64 = modem_create(LIQUID_MODEM_ASK64);
|
|
|
|
demodASK128 = modem_create(LIQUID_MODEM_ASK128);
|
|
|
|
demodASK256 = modem_create(LIQUID_MODEM_ASK256);
|
2015-06-10 13:39:08 -04:00
|
|
|
|
|
|
|
demodAPSK = demodAPSK4;
|
|
|
|
demodAPSK4 = modem_create(LIQUID_MODEM_APSK4);
|
|
|
|
demodAPSK8 = modem_create(LIQUID_MODEM_APSK8);
|
|
|
|
demodAPSK16 = modem_create(LIQUID_MODEM_APSK16);
|
|
|
|
demodAPSK32 = modem_create(LIQUID_MODEM_APSK32);
|
|
|
|
demodAPSK64 = modem_create(LIQUID_MODEM_APSK64);
|
|
|
|
demodAPSK128 = modem_create(LIQUID_MODEM_APSK128);
|
|
|
|
demodAPSK256 = modem_create(LIQUID_MODEM_APSK256);
|
2015-06-10 04:50:14 -04:00
|
|
|
|
2015-06-03 05:23:16 -04:00
|
|
|
demodBPSK = modem_create(LIQUID_MODEM_BPSK);
|
2015-06-10 13:39:08 -04:00
|
|
|
|
|
|
|
demodDPSK = demodDPSK2;
|
|
|
|
demodDPSK2 = modem_create(LIQUID_MODEM_DPSK2);
|
|
|
|
demodDPSK4 = modem_create(LIQUID_MODEM_DPSK4);
|
|
|
|
demodDPSK8 = modem_create(LIQUID_MODEM_DPSK8);
|
|
|
|
demodDPSK16 = modem_create(LIQUID_MODEM_DPSK16);
|
|
|
|
demodDPSK32 = modem_create(LIQUID_MODEM_DPSK32);
|
|
|
|
demodDPSK64 = modem_create(LIQUID_MODEM_DPSK64);
|
|
|
|
demodDPSK128 = modem_create(LIQUID_MODEM_DPSK128);
|
|
|
|
demodDPSK256 = modem_create(LIQUID_MODEM_DPSK256);
|
|
|
|
|
|
|
|
demodPSK = demodPSK2;
|
|
|
|
demodPSK2 = modem_create(LIQUID_MODEM_PSK2);
|
|
|
|
demodPSK4 = modem_create(LIQUID_MODEM_PSK4);
|
|
|
|
demodPSK8 = modem_create(LIQUID_MODEM_PSK8);
|
|
|
|
demodPSK16 = modem_create(LIQUID_MODEM_PSK16);
|
|
|
|
demodPSK32 = modem_create(LIQUID_MODEM_PSK32);
|
|
|
|
demodPSK64 = modem_create(LIQUID_MODEM_PSK64);
|
|
|
|
demodPSK128 = modem_create(LIQUID_MODEM_PSK128);
|
|
|
|
demodPSK256 = modem_create(LIQUID_MODEM_PSK256);
|
|
|
|
|
2015-06-03 05:23:16 -04:00
|
|
|
demodOOK = modem_create(LIQUID_MODEM_OOK);
|
2015-06-10 13:39:08 -04:00
|
|
|
|
|
|
|
demodSQAM = demodSQAM32;
|
|
|
|
demodSQAM32 = modem_create(LIQUID_MODEM_SQAM32);
|
|
|
|
demodSQAM128 = modem_create(LIQUID_MODEM_SQAM128);
|
|
|
|
|
2015-06-03 05:23:16 -04:00
|
|
|
demodST = modem_create(LIQUID_MODEM_V29);
|
2015-06-10 13:39:08 -04:00
|
|
|
|
|
|
|
demodQAM = demodQAM4;
|
|
|
|
demodQAM4 = modem_create(LIQUID_MODEM_QAM4);
|
|
|
|
demodQAM8 = modem_create(LIQUID_MODEM_QAM8);
|
|
|
|
demodQAM16 = modem_create(LIQUID_MODEM_QAM16);
|
|
|
|
demodQAM32 = modem_create(LIQUID_MODEM_QAM32);
|
|
|
|
demodQAM64 = modem_create(LIQUID_MODEM_QAM64);
|
|
|
|
demodQAM128 = modem_create(LIQUID_MODEM_QAM128);
|
|
|
|
demodQAM256 = modem_create(LIQUID_MODEM_QAM256);
|
|
|
|
|
2015-06-03 05:23:16 -04:00
|
|
|
demodQPSK = modem_create(LIQUID_MODEM_QPSK);
|
2015-06-09 11:00:05 -04:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
currentDemodLock = false; */
|
2015-06-09 11:00:05 -04:00
|
|
|
|
2014-12-16 18:27:32 -05:00
|
|
|
}
|
|
|
|
DemodulatorThread::~DemodulatorThread() {
|
|
|
|
}
|
|
|
|
|
2015-07-30 00:52:00 -04:00
|
|
|
void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) {
|
|
|
|
if (name == "AudioVisualOutput") {
|
|
|
|
audioVisOutputQueue = (DemodulatorThreadOutputQueue *)threadQueue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-29 20:57:02 -04:00
|
|
|
void DemodulatorThread::run() {
|
2014-12-16 20:33:44 -05:00
|
|
|
#ifdef __APPLE__
|
2014-12-18 20:11:25 -05:00
|
|
|
pthread_t tID = pthread_self(); // ID of this thread
|
|
|
|
int priority = sched_get_priority_max( SCHED_FIFO )-1;
|
2014-12-18 21:39:32 -05:00
|
|
|
sched_param prio = {priority}; // scheduling priority of thread
|
2014-12-18 20:11:25 -05:00
|
|
|
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
2014-12-16 20:33:44 -05:00
|
|
|
#endif
|
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// msresamp_rrrf audioResampler = NULL;
|
|
|
|
// msresamp_rrrf stereoResampler = NULL;
|
|
|
|
// firfilt_rrrf firStereoLeft = NULL;
|
|
|
|
// firfilt_rrrf firStereoRight = NULL;
|
|
|
|
// iirfilt_crcf iirStereoPilot = NULL;
|
2014-12-16 18:27:32 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// liquid_float_complex u, v, w, x, y;
|
2014-12-27 12:23:09 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// firhilbf firStereoR2C = firhilbf_create(5, 60.0f);
|
|
|
|
// firhilbf firStereoC2R = firhilbf_create(5, 60.0f);
|
2015-01-01 18:08:54 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// nco_crcf stereoPilot = nco_crcf_create(LIQUID_VCO);
|
|
|
|
// nco_crcf_reset(stereoPilot);
|
|
|
|
// nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f);
|
2015-06-05 00:28:32 -04:00
|
|
|
|
2015-02-19 23:51:24 -05:00
|
|
|
// half band filter used for side-band elimination
|
2015-11-16 23:49:54 -05:00
|
|
|
// resamp2_crcf ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
2015-01-25 01:27:37 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
// Automatic IQ gain
|
|
|
|
iqAutoGain = agc_crcf_create();
|
2015-07-17 19:14:39 -04:00
|
|
|
agc_crcf_set_bandwidth(iqAutoGain, 0.1);
|
2014-12-21 16:08:32 -05:00
|
|
|
|
2015-10-27 16:53:06 -04:00
|
|
|
ReBuffer<AudioThreadInput> audioVisBuffers;
|
2015-01-22 21:32:32 -05:00
|
|
|
|
2014-12-16 21:30:03 -05:00
|
|
|
std::cout << "Demodulator thread started.." << std::endl;
|
2014-12-24 01:28:33 -05:00
|
|
|
|
2015-07-30 00:28:53 -04:00
|
|
|
iqInputQueue = (DemodulatorThreadPostInputQueue*)getInputQueue("IQDataInput");
|
2015-07-30 19:30:46 -04:00
|
|
|
audioOutputQueue = (AudioThreadInputQueue*)getOutputQueue("AudioDataOutput");
|
2015-07-30 00:28:53 -04:00
|
|
|
threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue");
|
|
|
|
threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue");
|
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// switch (demodulatorType.load()) {
|
|
|
|
// case DEMOD_TYPE_FM:
|
|
|
|
// break;
|
|
|
|
// case DEMOD_TYPE_LSB:
|
|
|
|
// demodAM = demodAM_LSB;
|
|
|
|
// break;
|
|
|
|
// case DEMOD_TYPE_USB:
|
|
|
|
// demodAM = demodAM_USB;
|
|
|
|
// break;
|
|
|
|
// case DEMOD_TYPE_DSB:
|
|
|
|
// demodAM = demodAM_DSB;
|
|
|
|
// break;
|
|
|
|
// case DEMOD_TYPE_AM:
|
|
|
|
// demodAM = demodAM_DSB_CSP;
|
|
|
|
// break;
|
|
|
|
// }
|
2015-02-02 20:10:55 -05:00
|
|
|
|
2014-12-16 21:30:03 -05:00
|
|
|
while (!terminated) {
|
2014-12-23 01:12:14 -05:00
|
|
|
DemodulatorThreadPostIQData *inp;
|
2015-01-03 17:07:39 -05:00
|
|
|
iqInputQueue->pop(inp);
|
2015-08-12 21:45:02 -04:00
|
|
|
// std::lock_guard < std::mutex > lock(inp->m_mutex);
|
2014-12-16 18:27:32 -05:00
|
|
|
|
2014-12-23 01:12:14 -05:00
|
|
|
int bufSize = inp->data.size();
|
2014-12-16 18:27:32 -05:00
|
|
|
|
2014-12-16 21:30:03 -05:00
|
|
|
if (!bufSize) {
|
2014-12-24 01:28:33 -05:00
|
|
|
inp->decRefCount();
|
2014-12-16 21:30:03 -05:00
|
|
|
continue;
|
|
|
|
}
|
2014-12-16 18:27:32 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// if (audioResampler == NULL) {
|
|
|
|
// audioResampler = inp->audioResampler;
|
|
|
|
// stereoResampler = inp->stereoResampler;
|
|
|
|
// firStereoLeft = inp->firStereoLeft;
|
|
|
|
// firStereoRight = inp->firStereoRight;
|
|
|
|
// iirStereoPilot = inp->iirStereoPilot;
|
|
|
|
// audioSampleRate = inp->audioSampleRate;
|
|
|
|
// } else if (audioResampler != inp->audioResampler) {
|
|
|
|
// msresamp_rrrf_destroy(audioResampler);
|
|
|
|
// msresamp_rrrf_destroy(stereoResampler);
|
|
|
|
// audioResampler = inp->audioResampler;
|
|
|
|
// stereoResampler = inp->stereoResampler;
|
|
|
|
// audioSampleRate = inp->audioSampleRate;
|
|
|
|
//
|
|
|
|
// if (demodAM) {
|
|
|
|
// ampmodem_reset(demodAM);
|
|
|
|
// }
|
|
|
|
// freqdem_reset(demodFM);
|
|
|
|
// nco_crcf_reset(stereoPilot);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (firStereoLeft != inp->firStereoLeft) {
|
|
|
|
// if (firStereoLeft != NULL) {
|
|
|
|
// firfilt_rrrf_destroy(firStereoLeft);
|
|
|
|
// }
|
|
|
|
// firStereoLeft = inp->firStereoLeft;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (firStereoRight != inp->firStereoRight) {
|
|
|
|
// if (firStereoRight != NULL) {
|
|
|
|
// firfilt_rrrf_destroy(firStereoRight);
|
|
|
|
// }
|
|
|
|
// firStereoRight = inp->firStereoRight;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (iirStereoPilot != inp->iirStereoPilot) {
|
|
|
|
// if (iirStereoPilot != NULL) {
|
|
|
|
// iirfilt_crcf_destroy(iirStereoPilot);
|
|
|
|
// }
|
|
|
|
// iirStereoPilot = inp->iirStereoPilot;
|
|
|
|
// }
|
2015-06-05 00:28:32 -04:00
|
|
|
|
2015-01-04 13:20:31 -05:00
|
|
|
if (agcData.size() != bufSize) {
|
|
|
|
if (agcData.capacity() < bufSize) {
|
|
|
|
agcData.reserve(bufSize);
|
|
|
|
agcAMData.reserve(bufSize);
|
2014-12-24 03:03:34 -05:00
|
|
|
}
|
2015-01-04 13:20:31 -05:00
|
|
|
agcData.resize(bufSize);
|
|
|
|
agcAMData.resize(bufSize);
|
2014-12-24 03:03:34 -05:00
|
|
|
}
|
2014-12-16 21:30:03 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// double audio_resample_ratio = inp->audioResampleRatio;
|
2014-12-16 18:27:32 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// if (demodOutputData.size() != bufSize) {
|
|
|
|
// if (demodOutputData.capacity() < bufSize) {
|
|
|
|
// demodOutputData.reserve(bufSize);
|
|
|
|
// }
|
|
|
|
// demodOutputData.resize(bufSize);
|
|
|
|
// }
|
2014-12-24 03:03:34 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
/*
|
2015-06-29 15:55:21 -04:00
|
|
|
if (demodOutputDataDigital.size() != bufSize) {
|
|
|
|
if (demodOutputDataDigital.capacity() < bufSize) {
|
|
|
|
demodOutputDataDigital.reserve(bufSize);
|
|
|
|
}
|
|
|
|
demodOutputDataDigital.resize(bufSize);
|
|
|
|
}
|
2015-11-16 23:49:54 -05:00
|
|
|
*/
|
|
|
|
// int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
|
2014-12-27 12:45:21 -05:00
|
|
|
|
2015-01-04 13:20:31 -05:00
|
|
|
agc_crcf_execute_block(iqAutoGain, &(inp->data[0]), bufSize, &agcData[0]);
|
2015-01-01 03:48:32 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
float currentSignalLevel = 0;
|
2015-01-01 03:48:32 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
currentSignalLevel = ((60.0 / fabs(agc_crcf_get_rssi(iqAutoGain))) / 15.0 - signalLevel);
|
2015-01-01 03:48:32 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
if (agc_crcf_get_signal_level(iqAutoGain) > currentSignalLevel) {
|
|
|
|
currentSignalLevel = agc_crcf_get_signal_level(iqAutoGain);
|
2015-01-01 03:48:32 -05:00
|
|
|
}
|
|
|
|
|
2015-07-19 15:34:06 -04:00
|
|
|
std::vector<liquid_float_complex> *inputData;
|
|
|
|
|
|
|
|
if (agcEnabled) {
|
|
|
|
inputData = &agcData;
|
|
|
|
} else {
|
|
|
|
inputData = &inp->data;
|
|
|
|
}
|
|
|
|
|
2015-07-20 00:00:50 -04:00
|
|
|
// Reset demodulator Constellations & Lock
|
2015-11-16 23:49:54 -05:00
|
|
|
// updateDemodulatorCons(0);
|
|
|
|
/*
|
2015-01-01 18:08:54 -05:00
|
|
|
if (demodulatorType == DEMOD_TYPE_FM) {
|
2015-07-20 00:00:50 -04:00
|
|
|
currentDemodLock = false;
|
2015-07-19 15:34:06 -04:00
|
|
|
freqdem_demodulate_block(demodFM, &(*inputData)[0], bufSize, &demodOutputData[0]);
|
2015-06-27 23:23:43 -04:00
|
|
|
} else if (demodulatorType == DEMOD_TYPE_RAW) {
|
|
|
|
// do nothing here..
|
2015-01-01 18:08:54 -05:00
|
|
|
} else {
|
2015-01-03 19:03:16 -05:00
|
|
|
switch (demodulatorType.load()) {
|
2015-01-01 18:08:54 -05:00
|
|
|
case DEMOD_TYPE_LSB:
|
2015-06-10 13:39:08 -04:00
|
|
|
currentDemodLock = false;
|
2015-02-19 23:51:24 -05:00
|
|
|
for (int i = 0; i < bufSize; i++) { // Reject upper band
|
2015-10-18 12:26:07 -04:00
|
|
|
resamp2_crcf_filter_execute(ssbFilt,(*inputData)[i],&x,&y);
|
2015-02-19 23:51:24 -05:00
|
|
|
ampmodem_demodulate(demodAM, x, &demodOutputData[i]);
|
2015-02-12 22:46:45 -05:00
|
|
|
}
|
2015-01-01 18:08:54 -05:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_USB:
|
2015-06-10 13:39:08 -04:00
|
|
|
currentDemodLock = false;
|
2015-02-19 23:51:24 -05:00
|
|
|
for (int i = 0; i < bufSize; i++) { // Reject lower band
|
2015-10-18 12:26:07 -04:00
|
|
|
resamp2_crcf_filter_execute(ssbFilt,(*inputData)[i],&x,&y);
|
2015-02-19 23:51:24 -05:00
|
|
|
ampmodem_demodulate(demodAM, y, &demodOutputData[i]);
|
2015-02-12 22:46:45 -05:00
|
|
|
}
|
2015-01-01 18:08:54 -05:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_AM:
|
2015-01-07 20:23:15 -05:00
|
|
|
case DEMOD_TYPE_DSB:
|
2015-06-10 13:39:08 -04:00
|
|
|
currentDemodLock = false;
|
2015-02-12 02:14:22 -05:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-19 15:34:06 -04:00
|
|
|
ampmodem_demodulate(demodAM, (*inputData)[i], &demodOutputData[i]);
|
2015-02-12 02:14:22 -05:00
|
|
|
}
|
2015-01-01 18:08:54 -05:00
|
|
|
break;
|
2015-06-10 13:39:08 -04:00
|
|
|
// advanced demodulators
|
2015-06-04 16:38:43 -04:00
|
|
|
case DEMOD_TYPE_ASK:
|
2015-06-10 13:39:08 -04:00
|
|
|
|
2015-07-20 00:00:50 -04:00
|
|
|
switch (demodulatorCons.load()) {
|
2015-06-10 13:39:08 -04:00
|
|
|
case 2:
|
2015-06-10 04:50:14 -04:00
|
|
|
demodASK = demodASK2;
|
2015-06-10 13:39:08 -04:00
|
|
|
updateDemodulatorCons(2);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
demodASK = demodASK4;
|
|
|
|
updateDemodulatorCons(4);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
demodASK = demodASK8;
|
|
|
|
updateDemodulatorCons(8);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
demodASK = demodASK16;
|
|
|
|
updateDemodulatorCons(16);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
demodASK = demodASK32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
demodASK = demodASK64;
|
|
|
|
updateDemodulatorCons(64);
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
demodASK = demodASK128;
|
|
|
|
updateDemodulatorCons(128);
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
demodASK = demodASK256;
|
|
|
|
updateDemodulatorCons(256);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
demodASK = demodASK2;
|
|
|
|
break;
|
2015-06-10 04:50:14 -04:00
|
|
|
}
|
2015-06-10 13:39:08 -04:00
|
|
|
|
2015-06-04 16:38:43 -04:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-06-18 16:07:53 -04:00
|
|
|
modem_demodulate(demodASK, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-04 16:38:43 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodASK, 0.005f);
|
2015-06-04 16:38:43 -04:00
|
|
|
break;
|
2015-06-10 13:39:08 -04:00
|
|
|
case DEMOD_TYPE_APSK:
|
|
|
|
|
2015-07-20 00:00:50 -04:00
|
|
|
switch (demodulatorCons.load()) {
|
2015-06-10 13:39:08 -04:00
|
|
|
case 2:
|
|
|
|
demodAPSK = demodAPSK4;
|
|
|
|
updateDemodulatorCons(4);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
demodAPSK = demodAPSK4;
|
|
|
|
updateDemodulatorCons(4);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
demodAPSK = demodAPSK8;
|
|
|
|
updateDemodulatorCons(8);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
demodAPSK = demodAPSK16;
|
|
|
|
updateDemodulatorCons(16);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
demodAPSK = demodAPSK32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
demodAPSK = demodAPSK64;
|
|
|
|
updateDemodulatorCons(64);
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
demodAPSK = demodAPSK128;
|
|
|
|
updateDemodulatorCons(128);
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
demodAPSK = demodAPSK256;
|
|
|
|
updateDemodulatorCons(256);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
demodAPSK = demodAPSK4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-03 05:29:52 -04:00
|
|
|
modem_demodulate(demodAPSK, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-10 13:39:08 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodAPSK, 0.005f);
|
2015-06-10 13:39:08 -04:00
|
|
|
break;
|
2015-06-04 16:38:43 -04:00
|
|
|
case DEMOD_TYPE_BPSK:
|
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-03 05:29:52 -04:00
|
|
|
modem_demodulate(demodBPSK, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-04 16:38:43 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodBPSK, 0.005f);
|
2015-06-04 16:38:43 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_DPSK:
|
2015-06-10 13:39:08 -04:00
|
|
|
|
2015-07-20 00:00:50 -04:00
|
|
|
switch (demodulatorCons.load()) {
|
2015-06-10 13:39:08 -04:00
|
|
|
case 2:
|
|
|
|
demodDPSK = demodDPSK2;
|
|
|
|
updateDemodulatorCons(2);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
demodDPSK = demodDPSK4;
|
|
|
|
updateDemodulatorCons(4);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
demodDPSK = demodDPSK8;
|
|
|
|
updateDemodulatorCons(8);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
demodDPSK = demodDPSK16;
|
|
|
|
updateDemodulatorCons(16);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
demodDPSK = demodDPSK32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
demodDPSK = demodDPSK64;
|
|
|
|
updateDemodulatorCons(64);
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
demodDPSK = demodDPSK128;
|
|
|
|
updateDemodulatorCons(128);
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
demodDPSK = demodDPSK256;
|
|
|
|
updateDemodulatorCons(256);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
demodDPSK = demodDPSK2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-04 16:38:43 -04:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-03 05:29:52 -04:00
|
|
|
modem_demodulate(demodDPSK, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-04 16:38:43 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodDPSK, 0.005f);
|
2015-06-04 16:38:43 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_PSK:
|
2015-06-10 13:39:08 -04:00
|
|
|
|
2015-07-20 00:00:50 -04:00
|
|
|
switch (demodulatorCons.load()) {
|
2015-06-10 13:39:08 -04:00
|
|
|
case 2:
|
|
|
|
demodPSK = demodPSK2;
|
|
|
|
updateDemodulatorCons(2);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
demodPSK = demodPSK4;
|
|
|
|
updateDemodulatorCons(4);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
demodPSK = demodPSK8;
|
|
|
|
updateDemodulatorCons(8);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
demodPSK = demodPSK16;
|
|
|
|
updateDemodulatorCons(16);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
demodPSK = demodPSK32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
demodPSK = demodPSK64;
|
|
|
|
updateDemodulatorCons(64);
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
demodPSK = demodPSK128;
|
|
|
|
updateDemodulatorCons(128);
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
demodPSK = demodPSK256;
|
|
|
|
updateDemodulatorCons(256);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
demodPSK = demodPSK2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-04 16:38:43 -04:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-03 05:29:52 -04:00
|
|
|
modem_demodulate(demodPSK, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-04 16:38:43 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodPSK, 0.005f);
|
2015-06-04 16:38:43 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_OOK:
|
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-03 05:29:52 -04:00
|
|
|
modem_demodulate(demodOOK, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-04 16:38:43 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodOOK, 0.005f);
|
2015-06-04 16:38:43 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_SQAM:
|
2015-06-10 13:39:08 -04:00
|
|
|
|
2015-07-20 00:00:50 -04:00
|
|
|
switch (demodulatorCons.load()) {
|
2015-06-10 13:39:08 -04:00
|
|
|
case 2:
|
|
|
|
demodSQAM = demodSQAM32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
demodSQAM = demodSQAM32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
demodSQAM = demodSQAM32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
demodSQAM = demodSQAM32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
demodSQAM = demodSQAM32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
demodSQAM = demodSQAM32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
demodSQAM = demodSQAM128;
|
|
|
|
updateDemodulatorCons(128);
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
demodSQAM = demodSQAM128;
|
|
|
|
updateDemodulatorCons(128);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
demodSQAM = demodSQAM32;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-04 16:38:43 -04:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-03 05:29:52 -04:00
|
|
|
modem_demodulate(demodSQAM, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-04 16:38:43 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodSQAM, 0.005f);
|
2015-06-04 16:38:43 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_ST:
|
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-03 05:29:52 -04:00
|
|
|
modem_demodulate(demodST, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-04 16:38:43 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodST, 0.005f);
|
2015-06-04 16:38:43 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_QAM:
|
2015-06-10 13:39:08 -04:00
|
|
|
|
2015-07-20 00:00:50 -04:00
|
|
|
switch (demodulatorCons.load()) {
|
2015-06-10 13:39:08 -04:00
|
|
|
case 2:
|
|
|
|
demodQAM = demodQAM4;
|
|
|
|
updateDemodulatorCons(4);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
demodQAM = demodQAM4;
|
|
|
|
updateDemodulatorCons(4);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
demodQAM = demodQAM8;
|
|
|
|
updateDemodulatorCons(8);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
demodQAM = demodQAM16;
|
|
|
|
updateDemodulatorCons(16);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
demodQAM = demodQAM32;
|
|
|
|
updateDemodulatorCons(32);
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
demodQAM = demodQAM64;
|
|
|
|
updateDemodulatorCons(64);
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
demodQAM = demodQAM128;
|
|
|
|
updateDemodulatorCons(128);
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
demodQAM = demodQAM256;
|
|
|
|
updateDemodulatorCons(256);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
demodQAM = demodQAM4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-04 16:38:43 -04:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-07-03 05:29:52 -04:00
|
|
|
modem_demodulate(demodQAM, inp->data[i], &demodOutputDataDigital[i]);
|
2015-06-04 16:38:43 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodQAM, 0.5f);
|
2015-06-04 16:38:43 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_QPSK:
|
2015-06-29 15:55:21 -04:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-06-18 16:07:53 -04:00
|
|
|
modem_demodulate(demodQPSK, inp->data[i], &demodOutputDataDigital[i]);
|
2015-07-03 05:29:52 -04:00
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
updateDemodulatorLock(demodQPSK, 0.8f);
|
2015-01-01 18:08:54 -05:00
|
|
|
break;
|
2015-01-01 03:48:32 -05:00
|
|
|
}
|
|
|
|
|
2015-03-01 10:30:02 -05:00
|
|
|
amOutputCeilMA = amOutputCeilMA + (amOutputCeil - amOutputCeilMA) * 0.025;
|
|
|
|
amOutputCeilMAA = amOutputCeilMAA + (amOutputCeilMA - amOutputCeilMAA) * 0.025;
|
2015-01-01 03:48:32 -05:00
|
|
|
|
2015-02-12 02:14:22 -05:00
|
|
|
amOutputCeil = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < bufSize; i++) {
|
|
|
|
if (demodOutputData[i] > amOutputCeil) {
|
|
|
|
amOutputCeil = demodOutputData[i];
|
|
|
|
}
|
2015-06-18 16:07:53 -04:00
|
|
|
}
|
2015-02-12 02:14:22 -05:00
|
|
|
|
|
|
|
float gain = 0.5 / amOutputCeilMAA;
|
2015-01-01 03:48:32 -05:00
|
|
|
|
2015-01-04 13:20:31 -05:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-01-03 17:07:39 -05:00
|
|
|
demodOutputData[i] *= gain;
|
2015-01-01 03:48:32 -05:00
|
|
|
}
|
|
|
|
}
|
2014-12-16 18:27:32 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
if (audio_out_size != resampledOutputData.size()) {
|
|
|
|
if (resampledOutputData.capacity() < audio_out_size) {
|
|
|
|
resampledOutputData.reserve(audio_out_size);
|
2014-12-27 12:45:21 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
resampledOutputData.resize(audio_out_size);
|
2014-12-27 12:45:21 -05:00
|
|
|
}
|
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
unsigned int numAudioWritten;
|
2015-06-27 23:23:43 -04:00
|
|
|
|
|
|
|
if (demodulatorType == DEMOD_TYPE_RAW) {
|
|
|
|
numAudioWritten = bufSize;
|
|
|
|
} else {
|
2015-01-04 13:20:31 -05:00
|
|
|
msresamp_rrrf_execute(audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten);
|
2014-12-27 12:45:21 -05:00
|
|
|
|
2015-06-06 20:47:14 -04:00
|
|
|
if (stereo && inp->sampleRate >= 100000) {
|
2015-01-04 13:20:31 -05:00
|
|
|
if (demodStereoData.size() != bufSize) {
|
|
|
|
if (demodStereoData.capacity() < bufSize) {
|
|
|
|
demodStereoData.reserve(bufSize);
|
2014-12-27 12:45:21 -05:00
|
|
|
}
|
2015-01-04 13:20:31 -05:00
|
|
|
demodStereoData.resize(bufSize);
|
2014-12-27 12:45:21 -05:00
|
|
|
}
|
2014-12-26 20:58:42 -05:00
|
|
|
|
2015-06-05 20:58:10 -04:00
|
|
|
|
2015-06-05 00:28:32 -04:00
|
|
|
float phase_error = 0;
|
2015-06-05 20:58:10 -04:00
|
|
|
|
2015-01-04 13:20:31 -05:00
|
|
|
for (int i = 0; i < bufSize; i++) {
|
2015-06-05 20:58:10 -04:00
|
|
|
// real -> complex
|
2015-01-03 17:07:39 -05:00
|
|
|
firhilbf_r2c_execute(firStereoR2C, demodOutputData[i], &x);
|
2015-06-05 00:28:32 -04:00
|
|
|
|
2015-06-05 20:58:10 -04:00
|
|
|
// 19khz pilot band-pass
|
2015-06-05 00:28:32 -04:00
|
|
|
iirfilt_crcf_execute(iirStereoPilot, x, &v);
|
|
|
|
nco_crcf_cexpf(stereoPilot, &w);
|
2015-06-05 20:58:10 -04:00
|
|
|
|
|
|
|
w.imag = -w.imag; // conjf(w)
|
2015-06-05 00:28:32 -04:00
|
|
|
|
2015-06-05 20:58:10 -04:00
|
|
|
// multiply u = v * conjf(w)
|
|
|
|
u.real = v.real * w.real - v.imag * w.imag;
|
|
|
|
u.imag = v.real * w.imag + v.imag * w.real;
|
|
|
|
|
|
|
|
// cargf(u)
|
2015-06-05 00:28:32 -04:00
|
|
|
phase_error = atan2f(u.imag,u.real);
|
|
|
|
|
2015-06-05 20:58:10 -04:00
|
|
|
// step pll
|
2015-06-05 00:28:32 -04:00
|
|
|
nco_crcf_pll_step(stereoPilot, phase_error);
|
2015-06-05 20:58:10 -04:00
|
|
|
nco_crcf_step(stereoPilot);
|
|
|
|
|
|
|
|
// 38khz down-mix
|
|
|
|
nco_crcf_mix_down(stereoPilot, x, &y);
|
|
|
|
nco_crcf_mix_down(stereoPilot, y, &x);
|
|
|
|
|
|
|
|
// complex -> real
|
|
|
|
firhilbf_c2r_execute(firStereoC2R, x, &demodStereoData[i]);
|
2014-12-26 20:58:42 -05:00
|
|
|
}
|
2015-06-05 20:58:10 -04:00
|
|
|
|
2015-06-05 00:35:18 -04:00
|
|
|
// std::cout << "[PLL] phase error: " << phase_error;
|
|
|
|
// std::cout << " freq:" << (((nco_crcf_get_frequency(stereoPilot) / (2.0 * M_PI)) * inp->sampleRate)) << std::endl;
|
2015-06-05 00:28:32 -04:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
if (audio_out_size != resampledStereoData.size()) {
|
|
|
|
if (resampledStereoData.capacity() < audio_out_size) {
|
|
|
|
resampledStereoData.reserve(audio_out_size);
|
2014-12-27 12:45:21 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
resampledStereoData.resize(audio_out_size);
|
2014-12-24 03:03:34 -05:00
|
|
|
}
|
2014-12-16 18:27:32 -05:00
|
|
|
|
2015-01-04 13:20:31 -05:00
|
|
|
msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
|
2014-12-26 20:58:42 -05:00
|
|
|
}
|
2015-11-16 23:49:54 -05:00
|
|
|
}*/
|
2014-12-26 20:58:42 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
if (currentSignalLevel > signalLevel) {
|
|
|
|
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5;
|
2014-12-31 19:45:01 -05:00
|
|
|
} else {
|
2015-01-03 17:07:39 -05:00
|
|
|
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05;
|
2014-12-31 19:45:01 -05:00
|
|
|
}
|
|
|
|
|
2014-12-27 15:04:43 -05:00
|
|
|
AudioThreadInput *ati = NULL;
|
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
if (audioOutputQueue != NULL) {
|
|
|
|
if (!squelchEnabled || (signalLevel >= squelchLevel)) {
|
2015-07-28 21:56:39 -04:00
|
|
|
ati = outputBuffers.getBuffer();
|
2014-12-24 01:28:33 -05:00
|
|
|
|
2015-03-15 21:02:26 -04:00
|
|
|
ati->sampleRate = audioSampleRate;
|
2015-08-24 01:31:37 -04:00
|
|
|
ati->inputRate = inp->sampleRate;
|
2014-12-24 01:28:33 -05:00
|
|
|
ati->setRefCount(1);
|
2014-12-26 20:58:42 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
/*
|
|
|
|
|
2015-06-27 23:23:43 -04:00
|
|
|
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++) {
|
2015-08-28 19:55:25 -04:00
|
|
|
ati->data[i * 2] = (*inputData)[i].imag;
|
|
|
|
ati->data[i * 2 + 1] = (*inputData)[i].real;
|
2015-06-27 23:23:43 -04:00
|
|
|
}
|
|
|
|
} else if (stereo && inp->sampleRate >= 100000) {
|
2014-12-26 20:58:42 -05:00
|
|
|
ati->channels = 2;
|
2015-01-03 17:07:39 -05:00
|
|
|
if (ati->data.capacity() < (numAudioWritten * 2)) {
|
|
|
|
ati->data.reserve(numAudioWritten * 2);
|
2014-12-27 12:45:21 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
ati->data.resize(numAudioWritten * 2);
|
|
|
|
for (int i = 0; i < numAudioWritten; i++) {
|
2014-12-27 15:04:43 -05:00
|
|
|
float l, r;
|
|
|
|
|
2015-06-05 20:58:10 -04:00
|
|
|
firfilt_rrrf_push(firStereoLeft, 0.568 * (resampledOutputData[i] - (resampledStereoData[i])));
|
2015-01-03 17:07:39 -05:00
|
|
|
firfilt_rrrf_execute(firStereoLeft, &l);
|
2014-12-27 15:04:43 -05:00
|
|
|
|
2015-06-05 20:58:10 -04:00
|
|
|
firfilt_rrrf_push(firStereoRight, 0.568 * (resampledOutputData[i] + (resampledStereoData[i])));
|
2015-01-03 17:07:39 -05:00
|
|
|
firfilt_rrrf_execute(firStereoRight, &r);
|
2014-12-27 15:04:43 -05:00
|
|
|
|
|
|
|
ati->data[i * 2] = l;
|
|
|
|
ati->data[i * 2 + 1] = r;
|
2014-12-26 20:58:42 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ati->channels = 1;
|
2015-01-03 17:07:39 -05:00
|
|
|
ati->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten);
|
2014-12-26 20:58:42 -05:00
|
|
|
}
|
2015-11-16 23:49:54 -05:00
|
|
|
*/
|
2015-02-08 18:59:08 -05:00
|
|
|
std::vector<float>::iterator data_i;
|
|
|
|
ati->peak = 0;
|
|
|
|
for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) {
|
2015-02-12 02:14:22 -05:00
|
|
|
float p = fabs(*data_i);
|
|
|
|
if (p > ati->peak) {
|
2015-02-08 18:59:08 -05:00
|
|
|
ati->peak = p;
|
|
|
|
}
|
|
|
|
}
|
2014-12-21 16:08:32 -05:00
|
|
|
}
|
2014-12-16 21:30:03 -05:00
|
|
|
}
|
2015-11-16 23:49:54 -05:00
|
|
|
/*
|
2015-01-03 17:07:39 -05:00
|
|
|
if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) {
|
2015-10-27 16:53:06 -04:00
|
|
|
AudioThreadInput *ati_vis = audioVisBuffers.getBuffer();
|
|
|
|
ati_vis->setRefCount(1);
|
2015-08-24 01:31:37 -04:00
|
|
|
ati_vis->sampleRate = inp->sampleRate;
|
|
|
|
ati_vis->inputRate = inp->sampleRate;
|
|
|
|
|
2014-12-21 16:08:32 -05:00
|
|
|
int num_vis = DEMOD_VIS_SIZE;
|
2015-06-27 23:23:43 -04:00
|
|
|
if (demodulatorType == DEMOD_TYPE_RAW || (stereo && inp->sampleRate >= 100000)) {
|
2014-12-27 15:04:43 -05:00
|
|
|
ati_vis->channels = 2;
|
|
|
|
int stereoSize = ati->data.size();
|
2015-06-27 23:23:43 -04:00
|
|
|
if (stereoSize > DEMOD_VIS_SIZE * 2) {
|
|
|
|
stereoSize = DEMOD_VIS_SIZE * 2;
|
2014-12-26 22:20:50 -05:00
|
|
|
}
|
2015-01-22 21:32:32 -05:00
|
|
|
|
2014-12-26 22:20:50 -05:00
|
|
|
ati_vis->data.resize(stereoSize);
|
|
|
|
|
2015-06-27 23:23:43 -04:00
|
|
|
if (demodulatorType == DEMOD_TYPE_RAW) {
|
|
|
|
for (int i = 0; i < stereoSize / 2; i++) {
|
2015-07-19 15:34:06 -04:00
|
|
|
ati_vis->data[i] = agcData[i].real * 0.75;
|
|
|
|
ati_vis->data[i + stereoSize / 2] = agcData[i].imag * 0.75;
|
2015-06-27 23:23:43 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i < stereoSize / 2; i++) {
|
2015-08-24 01:31:37 -04:00
|
|
|
ati_vis->inputRate = audioSampleRate;
|
|
|
|
ati_vis->sampleRate = 36000;
|
2015-06-27 23:23:43 -04:00
|
|
|
ati_vis->data[i] = ati->data[i * 2];
|
|
|
|
ati_vis->data[i + stereoSize / 2] = ati->data[i * 2 + 1];
|
|
|
|
}
|
2014-12-21 16:08:32 -05:00
|
|
|
}
|
2014-12-18 21:39:32 -05:00
|
|
|
} else {
|
2015-11-16 23:49:54 -05:00
|
|
|
int numAudioWritten = ati->data.size();
|
2014-12-27 15:04:43 -05:00
|
|
|
ati_vis->channels = 1;
|
2015-01-04 13:20:31 -05:00
|
|
|
if (numAudioWritten > bufSize) {
|
2015-08-24 01:31:37 -04:00
|
|
|
ati_vis->inputRate = audioSampleRate;
|
2015-01-03 17:07:39 -05:00
|
|
|
if (num_vis > numAudioWritten) {
|
|
|
|
num_vis = numAudioWritten;
|
2014-12-26 22:20:50 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
ati_vis->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + num_vis);
|
2014-12-26 22:20:50 -05:00
|
|
|
} else {
|
2015-01-04 13:20:31 -05:00
|
|
|
if (num_vis > bufSize) {
|
|
|
|
num_vis = bufSize;
|
2014-12-26 22:20:50 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
ati_vis->data.assign(demodOutputData.begin(), demodOutputData.begin() + num_vis);
|
2014-12-21 16:08:32 -05:00
|
|
|
}
|
2014-12-26 22:20:50 -05:00
|
|
|
|
|
|
|
// std::cout << "Signal: " << agc_crcf_get_signal_level(agc) << " -- " << agc_crcf_get_rssi(agc) << "dB " << std::endl;
|
2014-12-21 16:08:32 -05:00
|
|
|
}
|
2014-12-21 17:37:41 -05:00
|
|
|
|
2015-08-24 01:31:37 -04:00
|
|
|
audioVisOutputQueue->push(ati_vis);
|
2014-12-21 16:08:32 -05:00
|
|
|
}
|
2015-11-16 23:49:54 -05:00
|
|
|
*/
|
|
|
|
|
2015-07-19 15:34:06 -04:00
|
|
|
if (ati != NULL) {
|
2015-08-17 00:59:38 -04:00
|
|
|
if (!muted.load()) {
|
|
|
|
audioOutputQueue->push(ati);
|
|
|
|
} else {
|
|
|
|
ati->setRefCount(0);
|
|
|
|
}
|
2015-07-19 15:34:06 -04:00
|
|
|
}
|
|
|
|
|
2014-12-21 16:08:32 -05:00
|
|
|
if (!threadQueueControl->empty()) {
|
2015-11-16 23:49:54 -05:00
|
|
|
// int newDemodType = DEMOD_TYPE_NULL;
|
2015-01-01 18:08:54 -05:00
|
|
|
|
2014-12-21 16:08:32 -05:00
|
|
|
while (!threadQueueControl->empty()) {
|
|
|
|
DemodulatorThreadControlCommand command;
|
|
|
|
threadQueueControl->pop(command);
|
|
|
|
|
|
|
|
switch (command.cmd) {
|
2015-01-03 17:07:39 -05:00
|
|
|
case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_ON:
|
|
|
|
squelchEnabled = true;
|
2014-12-21 16:08:32 -05:00
|
|
|
break;
|
|
|
|
case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF:
|
2015-01-03 17:07:39 -05:00
|
|
|
squelchEnabled = false;
|
2014-12-21 16:08:32 -05:00
|
|
|
break;
|
2015-11-16 23:49:54 -05:00
|
|
|
// case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE:
|
|
|
|
// newDemodType = command.demodType;
|
|
|
|
// break;
|
2014-12-21 16:08:32 -05:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2014-12-18 21:39:32 -05:00
|
|
|
}
|
2015-11-16 23:49:54 -05:00
|
|
|
/*
|
2015-01-01 18:08:54 -05:00
|
|
|
if (newDemodType != DEMOD_TYPE_NULL) {
|
|
|
|
switch (newDemodType) {
|
|
|
|
case DEMOD_TYPE_FM:
|
2015-01-07 21:25:35 -05:00
|
|
|
freqdem_reset(demodFM);
|
2015-01-01 18:08:54 -05:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_LSB:
|
2015-02-12 22:46:45 -05:00
|
|
|
demodAM = demodAM_LSB;
|
2015-01-07 21:25:35 -05:00
|
|
|
ampmodem_reset(demodAM);
|
2015-01-01 18:08:54 -05:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_USB:
|
2015-02-12 22:46:45 -05:00
|
|
|
demodAM = demodAM_USB;
|
2015-01-07 21:25:35 -05:00
|
|
|
ampmodem_reset(demodAM);
|
2015-01-01 18:08:54 -05:00
|
|
|
break;
|
2015-01-07 20:23:15 -05:00
|
|
|
case DEMOD_TYPE_DSB:
|
|
|
|
demodAM = demodAM_DSB;
|
2015-01-07 21:25:35 -05:00
|
|
|
ampmodem_reset(demodAM);
|
2015-01-07 20:23:15 -05:00
|
|
|
break;
|
2015-01-01 18:08:54 -05:00
|
|
|
case DEMOD_TYPE_AM:
|
2015-01-03 17:07:39 -05:00
|
|
|
demodAM = demodAM_DSB_CSP;
|
2015-01-07 21:25:35 -05:00
|
|
|
ampmodem_reset(demodAM);
|
2015-01-01 18:08:54 -05:00
|
|
|
break;
|
2015-06-18 16:07:53 -04:00
|
|
|
case DEMOD_TYPE_ASK:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodASK);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_APSK:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodAPSK);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_BPSK:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodBPSK);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_DPSK:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodDPSK);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_PSK:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodPSK);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_OOK:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodOOK);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_SQAM:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodSQAM);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_ST:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodST);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_QAM:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodQAM);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
|
|
|
case DEMOD_TYPE_QPSK:
|
2015-07-03 05:29:52 -04:00
|
|
|
//modem_reset(demodQPSK);
|
2015-06-18 16:07:53 -04:00
|
|
|
break;
|
2015-07-03 05:29:52 -04:00
|
|
|
default:
|
|
|
|
// empty default to prevent exceptions
|
|
|
|
break;
|
2015-01-01 18:08:54 -05:00
|
|
|
}
|
|
|
|
demodulatorType = newDemodType;
|
2015-11-16 23:49:54 -05:00
|
|
|
}*/
|
2014-12-16 21:30:03 -05:00
|
|
|
}
|
2014-12-21 16:08:32 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
// demodOutputDataDigital.empty();
|
2015-07-03 05:29:52 -04:00
|
|
|
|
2014-12-24 01:28:33 -05:00
|
|
|
inp->decRefCount();
|
2014-12-16 21:30:03 -05:00
|
|
|
}
|
2015-07-03 05:29:52 -04:00
|
|
|
// end while !terminated
|
2015-11-16 23:49:54 -05:00
|
|
|
/*
|
2015-01-03 17:07:39 -05:00
|
|
|
if (audioResampler != NULL) {
|
|
|
|
msresamp_rrrf_destroy(audioResampler);
|
2014-12-16 21:30:03 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
if (stereoResampler != NULL) {
|
|
|
|
msresamp_rrrf_destroy(stereoResampler);
|
2014-12-26 21:55:13 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
if (firStereoLeft != NULL) {
|
|
|
|
firfilt_rrrf_destroy(firStereoLeft);
|
2014-12-27 15:04:43 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
if (firStereoRight != NULL) {
|
|
|
|
firfilt_rrrf_destroy(firStereoRight);
|
2014-12-27 15:04:43 -05:00
|
|
|
}
|
2015-06-05 00:28:32 -04:00
|
|
|
if (iirStereoPilot != NULL) {
|
|
|
|
iirfilt_crcf_destroy(iirStereoPilot);
|
|
|
|
}
|
2014-12-16 20:33:44 -05:00
|
|
|
|
2015-01-03 17:07:39 -05:00
|
|
|
agc_crcf_destroy(iqAutoGain);
|
|
|
|
firhilbf_destroy(firStereoR2C);
|
|
|
|
firhilbf_destroy(firStereoC2R);
|
2015-06-05 00:28:32 -04:00
|
|
|
nco_crcf_destroy(stereoPilot);
|
2015-10-18 12:26:07 -04:00
|
|
|
resamp2_crcf_destroy(ssbFilt);
|
2015-11-16 23:49:54 -05:00
|
|
|
*/
|
2015-07-28 21:56:39 -04:00
|
|
|
outputBuffers.purge();
|
2014-12-24 01:28:33 -05:00
|
|
|
|
2015-01-22 23:41:33 -05:00
|
|
|
if (audioVisOutputQueue && !audioVisOutputQueue->empty()) {
|
|
|
|
AudioThreadInput *dummy_vis;
|
|
|
|
audioVisOutputQueue->pop(dummy_vis);
|
|
|
|
}
|
2015-10-27 16:53:06 -04:00
|
|
|
audioVisBuffers.purge();
|
2015-01-22 21:32:32 -05:00
|
|
|
|
2014-12-16 21:30:03 -05:00
|
|
|
DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED);
|
|
|
|
tCmd.context = this;
|
|
|
|
threadQueueNotify->push(tCmd);
|
2015-07-30 00:28:53 -04:00
|
|
|
|
2015-01-11 20:26:51 -05:00
|
|
|
std::cout << "Demodulator thread done." << std::endl;
|
2015-01-03 17:07:39 -05:00
|
|
|
}
|
|
|
|
|
2014-12-16 18:27:32 -05:00
|
|
|
void DemodulatorThread::terminate() {
|
2014-12-16 21:30:03 -05:00
|
|
|
terminated = true;
|
2014-12-23 01:12:14 -05:00
|
|
|
DemodulatorThreadPostIQData *inp = new DemodulatorThreadPostIQData; // push dummy to nudge queue
|
2015-01-03 17:07:39 -05:00
|
|
|
iqInputQueue->push(inp);
|
2014-12-16 18:27:32 -05:00
|
|
|
}
|
2014-12-26 20:58:42 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
//void DemodulatorThread::setStereo(bool state) {
|
|
|
|
// stereo.store(state);
|
|
|
|
// std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl;
|
|
|
|
//}
|
2014-12-26 20:58:42 -05:00
|
|
|
|
2015-11-16 23:49:54 -05:00
|
|
|
//bool DemodulatorThread::isStereo() {
|
|
|
|
// return stereo.load();
|
|
|
|
//}
|
2015-07-19 15:34:06 -04:00
|
|
|
|
2015-08-17 00:59:38 -04:00
|
|
|
bool DemodulatorThread::isMuted() {
|
|
|
|
return muted.load();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DemodulatorThread::setMuted(bool muted) {
|
|
|
|
this->muted.store(muted);
|
|
|
|
}
|
|
|
|
|
2015-07-19 15:34:06 -04:00
|
|
|
void DemodulatorThread::setAGC(bool state) {
|
|
|
|
agcEnabled.store(state);
|
2014-12-26 20:58:42 -05:00
|
|
|
}
|
2014-12-31 19:45:01 -05:00
|
|
|
|
2015-07-19 15:34:06 -04:00
|
|
|
bool DemodulatorThread::getAGC() {
|
|
|
|
return agcEnabled.load();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-31 19:45:01 -05:00
|
|
|
float DemodulatorThread::getSignalLevel() {
|
2015-07-19 15:34:06 -04:00
|
|
|
return signalLevel.load();
|
2014-12-31 19:45:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void DemodulatorThread::setSquelchLevel(float signal_level_in) {
|
2015-01-03 17:07:39 -05:00
|
|
|
if (!squelchEnabled) {
|
|
|
|
squelchEnabled = true;
|
2014-12-31 19:45:01 -05:00
|
|
|
}
|
2015-01-03 17:07:39 -05:00
|
|
|
squelchLevel = signal_level_in;
|
2014-12-31 19:45:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
float DemodulatorThread::getSquelchLevel() {
|
2015-01-03 17:07:39 -05:00
|
|
|
return squelchLevel;
|
2014-12-31 19:45:01 -05:00
|
|
|
}
|
2015-01-01 03:48:32 -05:00
|
|
|
|
2015-11-17 18:57:42 -05:00
|
|
|
void DemodulatorThread::setDemodulatorType(std::string demod_type_in) {
|
2015-01-01 03:48:32 -05:00
|
|
|
demodulatorType = demod_type_in;
|
|
|
|
}
|
|
|
|
|
2015-11-17 18:57:42 -05:00
|
|
|
std::string DemodulatorThread::getDemodulatorType() {
|
2015-01-01 03:48:32 -05:00
|
|
|
return demodulatorType;
|
|
|
|
}
|
2015-01-01 18:08:54 -05:00
|
|
|
|
2015-06-05 03:51:46 -04:00
|
|
|
void DemodulatorThread::setDemodulatorLock(bool demod_lock_in) {
|
2015-06-09 11:00:05 -04:00
|
|
|
demod_lock_in ? currentDemodLock = true : currentDemodLock = false;
|
2015-06-05 03:51:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int DemodulatorThread::getDemodulatorLock() {
|
|
|
|
return currentDemodLock;
|
|
|
|
}
|
|
|
|
|
2015-06-10 04:50:14 -04:00
|
|
|
void DemodulatorThread::setDemodulatorCons(int demod_cons_in) {
|
2015-07-20 00:00:50 -04:00
|
|
|
demodulatorCons.store(demod_cons_in);
|
2015-06-10 04:50:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int DemodulatorThread::getDemodulatorCons() {
|
2015-06-10 13:39:08 -04:00
|
|
|
return currentDemodCons;
|
2015-06-10 04:50:14 -04:00
|
|
|
}
|
|
|
|
|
2015-06-09 11:00:05 -04:00
|
|
|
void DemodulatorThread::updateDemodulatorLock(modem demod, float sensitivity) {
|
2015-06-18 16:07:53 -04:00
|
|
|
modem_get_demodulator_evm(demod) <= sensitivity ? setDemodulatorLock(true) : setDemodulatorLock(false);
|
2015-06-05 03:51:46 -04:00
|
|
|
}
|
|
|
|
|
2015-06-10 13:39:08 -04:00
|
|
|
void DemodulatorThread::updateDemodulatorCons(int Cons) {
|
|
|
|
if (currentDemodCons != Cons) {
|
|
|
|
currentDemodCons = Cons;
|
|
|
|
}
|
|
|
|
}
|