mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-09-03 13:47:53 -04:00
Modem, ModemKit and initial ModemAnalog refactor
This commit is contained in:
parent
f1f2cb91eb
commit
a1a6a467e8
@ -234,6 +234,25 @@ SET (cubicsdr_sources
|
|||||||
src/demod/DemodulatorWorkerThread.cpp
|
src/demod/DemodulatorWorkerThread.cpp
|
||||||
src/demod/DemodulatorInstance.cpp
|
src/demod/DemodulatorInstance.cpp
|
||||||
src/demod/DemodulatorMgr.cpp
|
src/demod/DemodulatorMgr.cpp
|
||||||
|
src/modules/modem/Modem.cpp
|
||||||
|
src/modules/modem/ModemAnalog.cpp
|
||||||
|
src/modules/modem/digital/ModemASK.cpp
|
||||||
|
src/modules/modem/digital/ModemAPSK.cpp
|
||||||
|
src/modules/modem/digital/ModemBPSK.cpp
|
||||||
|
src/modules/modem/digital/ModemDPSK.cpp
|
||||||
|
src/modules/modem/digital/ModemPSK.cpp
|
||||||
|
src/modules/modem/digital/ModemOOK.cpp
|
||||||
|
src/modules/modem/digital/ModemST.cpp
|
||||||
|
src/modules/modem/digital/ModemSQAM.cpp
|
||||||
|
src/modules/modem/digital/ModemQAM.cpp
|
||||||
|
src/modules/modem/digital/ModemQPSK.cpp
|
||||||
|
src/modules/modem/analog/ModemAM.cpp
|
||||||
|
src/modules/modem/analog/ModemDSB.cpp
|
||||||
|
src/modules/modem/analog/ModemFM.cpp
|
||||||
|
src/modules/modem/analog/ModemFMStereo.cpp
|
||||||
|
src/modules/modem/analog/ModemIQ.cpp
|
||||||
|
src/modules/modem/analog/ModemLSB.cpp
|
||||||
|
src/modules/modem/analog/ModemUSB.cpp
|
||||||
src/audio/AudioThread.cpp
|
src/audio/AudioThread.cpp
|
||||||
src/util/Gradient.cpp
|
src/util/Gradient.cpp
|
||||||
src/util/Timer.cpp
|
src/util/Timer.cpp
|
||||||
@ -293,6 +312,25 @@ SET (cubicsdr_headers
|
|||||||
src/demod/DemodulatorInstance.h
|
src/demod/DemodulatorInstance.h
|
||||||
src/demod/DemodulatorMgr.h
|
src/demod/DemodulatorMgr.h
|
||||||
src/demod/DemodDefs.h
|
src/demod/DemodDefs.h
|
||||||
|
src/modules/modem/Modem.h
|
||||||
|
src/modules/modem/ModemAnalog.h
|
||||||
|
src/modules/modem/digital/ModemASK.h
|
||||||
|
src/modules/modem/digital/ModemAPSK.h
|
||||||
|
src/modules/modem/digital/ModemBPSK.h
|
||||||
|
src/modules/modem/digital/ModemDPSK.h
|
||||||
|
src/modules/modem/digital/ModemPSK.h
|
||||||
|
src/modules/modem/digital/ModemOOK.h
|
||||||
|
src/modules/modem/digital/ModemST.h
|
||||||
|
src/modules/modem/digital/ModemSQAM.h
|
||||||
|
src/modules/modem/digital/ModemQAM.h
|
||||||
|
src/modules/modem/digital/ModemQPSK.h
|
||||||
|
src/modules/modem/analog/ModemAM.h
|
||||||
|
src/modules/modem/analog/ModemDSB.h
|
||||||
|
src/modules/modem/analog/ModemFM.h
|
||||||
|
src/modules/modem/analog/ModemFMStereo.h
|
||||||
|
src/modules/modem/analog/ModemIQ.h
|
||||||
|
src/modules/modem/analog/ModemLSB.h
|
||||||
|
src/modules/modem/analog/ModemUSB.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
|
||||||
@ -372,6 +410,9 @@ SOURCE_GROUP("Base" REGULAR_EXPRESSION "src/${REG_EXT}")
|
|||||||
SOURCE_GROUP("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_EXT}")
|
SOURCE_GROUP("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_EXT}")
|
||||||
SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}")
|
SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}")
|
||||||
SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION "src/demod/${REG_EXT}")
|
SOURCE_GROUP("Demodulator" REGULAR_EXPRESSION "src/demod/${REG_EXT}")
|
||||||
|
SOURCE_GROUP("Modem" REGULAR_EXPRESSION "src/modules/modem/${REG_EXT}")
|
||||||
|
SOURCE_GROUP("Modem-Analog" REGULAR_EXPRESSION "src/modules/modem/analog/${REG_EXT}")
|
||||||
|
SOURCE_GROUP("Modem-Digital" REGULAR_EXPRESSION "src/modules/modem/digital/${REG_EXT}")
|
||||||
SOURCE_GROUP("Audio" REGULAR_EXPRESSION "src/audio/${REG_EXT}")
|
SOURCE_GROUP("Audio" REGULAR_EXPRESSION "src/audio/${REG_EXT}")
|
||||||
SOURCE_GROUP("Utility" REGULAR_EXPRESSION "src/util/${REG_EXT}")
|
SOURCE_GROUP("Utility" REGULAR_EXPRESSION "src/util/${REG_EXT}")
|
||||||
SOURCE_GROUP("Visual" REGULAR_EXPRESSION "src/visual/${REG_EXT}")
|
SOURCE_GROUP("Visual" REGULAR_EXPRESSION "src/visual/${REG_EXT}")
|
||||||
@ -387,6 +428,10 @@ include_directories (
|
|||||||
${PROJECT_SOURCE_DIR}/src/forms/SDRDevices
|
${PROJECT_SOURCE_DIR}/src/forms/SDRDevices
|
||||||
${PROJECT_SOURCE_DIR}/src/sdr
|
${PROJECT_SOURCE_DIR}/src/sdr
|
||||||
${PROJECT_SOURCE_DIR}/src/demod
|
${PROJECT_SOURCE_DIR}/src/demod
|
||||||
|
${PROJECT_SOURCE_DIR}/src/modules
|
||||||
|
${PROJECT_SOURCE_DIR}/src/modules/modem
|
||||||
|
${PROJECT_SOURCE_DIR}/src/modules/modem/digital
|
||||||
|
${PROJECT_SOURCE_DIR}/src/modules/modem/analog
|
||||||
${PROJECT_SOURCE_DIR}/src/audio
|
${PROJECT_SOURCE_DIR}/src/audio
|
||||||
${PROJECT_SOURCE_DIR}/src/util
|
${PROJECT_SOURCE_DIR}/src/util
|
||||||
${PROJECT_SOURCE_DIR}/src/panel
|
${PROJECT_SOURCE_DIR}/src/panel
|
||||||
|
@ -93,21 +93,14 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DemodulatorThreadPostIQData: public ReferenceCounter {
|
class DemodulatorThreadPostIQData: public ReferenceCounter {
|
||||||
public:
|
public:
|
||||||
std::vector<liquid_float_complex> data;
|
std::vector<liquid_float_complex> data;
|
||||||
long long sampleRate;
|
long long sampleRate;
|
||||||
msresamp_rrrf audioResampler;
|
|
||||||
msresamp_rrrf stereoResampler;
|
|
||||||
double audioResampleRatio;
|
|
||||||
int audioSampleRate;
|
|
||||||
|
|
||||||
firfilt_rrrf firStereoLeft;
|
|
||||||
firfilt_rrrf firStereoRight;
|
|
||||||
iirfilt_crcf iirStereoPilot;
|
|
||||||
|
|
||||||
DemodulatorThreadPostIQData() :
|
DemodulatorThreadPostIQData() :
|
||||||
sampleRate(0), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(0), audioSampleRate(0), firStereoLeft(NULL), firStereoRight(NULL), iirStereoPilot(NULL) {
|
sampleRate(0) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +109,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DemodulatorThreadAudioData: public ReferenceCounter {
|
class DemodulatorThreadAudioData: public ReferenceCounter {
|
||||||
public:
|
public:
|
||||||
long long frequency;
|
long long frequency;
|
||||||
|
@ -202,7 +202,7 @@ bool DemodulatorInstance::isStereo() {
|
|||||||
|
|
||||||
void DemodulatorInstance::setStereo(bool state) {
|
void DemodulatorInstance::setStereo(bool state) {
|
||||||
stereo = state;
|
stereo = state;
|
||||||
demodulatorThread->setStereo(state);
|
// demodulatorThread->setStereo(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::squelchAuto() {
|
void DemodulatorInstance::squelchAuto() {
|
||||||
|
@ -27,45 +27,45 @@ void DemodulatorPreThread::initialize() {
|
|||||||
initialized = false;
|
initialized = false;
|
||||||
|
|
||||||
iqResampleRatio = (double) (params.bandwidth) / (double) params.sampleRate;
|
iqResampleRatio = (double) (params.bandwidth) / (double) params.sampleRate;
|
||||||
audioResampleRatio = (double) (params.audioSampleRate) / (double) params.bandwidth;
|
// audioResampleRatio = (double) (params.audioSampleRate) / (double) params.bandwidth;
|
||||||
|
|
||||||
float As = 120.0f; // stop-band attenuation [dB]
|
float As = 60.0f; // stop-band attenuation [dB]
|
||||||
|
|
||||||
iqResampler = msresamp_crcf_create(iqResampleRatio, As);
|
iqResampler = msresamp_crcf_create(iqResampleRatio, As);
|
||||||
audioResampler = msresamp_rrrf_create(audioResampleRatio, As);
|
// audioResampler = msresamp_rrrf_create(audioResampleRatio, As);
|
||||||
stereoResampler = msresamp_rrrf_create(audioResampleRatio, As);
|
// stereoResampler = msresamp_rrrf_create(audioResampleRatio, As);
|
||||||
|
|
||||||
// Stereo filters / shifters
|
// Stereo filters / shifters
|
||||||
double firStereoCutoff = ((double) 16000 / (double) params.audioSampleRate);
|
// double firStereoCutoff = ((double) 16000 / (double) params.audioSampleRate);
|
||||||
float ft = ((double) 1000 / (double) params.audioSampleRate); // filter transition
|
// float ft = ((double) 1000 / (double) params.audioSampleRate); // filter transition
|
||||||
float mu = 0.0f; // fractional timing offset
|
// float mu = 0.0f; // fractional timing offset
|
||||||
|
//
|
||||||
|
// if (firStereoCutoff < 0) {
|
||||||
|
// firStereoCutoff = 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (firStereoCutoff > 0.5) {
|
||||||
|
// firStereoCutoff = 0.5;
|
||||||
|
// }
|
||||||
|
|
||||||
if (firStereoCutoff < 0) {
|
// unsigned int h_len = estimate_req_filter_len(ft, As);
|
||||||
firStereoCutoff = 0;
|
// float *h = new float[h_len];
|
||||||
}
|
// liquid_firdes_kaiser(h_len, firStereoCutoff, As, mu, h);
|
||||||
|
//
|
||||||
if (firStereoCutoff > 0.5) {
|
// firStereoLeft = firfilt_rrrf_create(h, h_len);
|
||||||
firStereoCutoff = 0.5;
|
// firStereoRight = firfilt_rrrf_create(h, h_len);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
firStereoLeft = firfilt_rrrf_create(h, h_len);
|
|
||||||
firStereoRight = firfilt_rrrf_create(h, h_len);
|
|
||||||
|
|
||||||
// stereo pilot filter
|
// stereo pilot filter
|
||||||
float bw = params.bandwidth;
|
// float bw = params.bandwidth;
|
||||||
if (bw < 100000.0) {
|
// if (bw < 100000.0) {
|
||||||
bw = 100000.0;
|
// bw = 100000.0;
|
||||||
}
|
// }
|
||||||
unsigned int order = 5; // filter order
|
// unsigned int order = 5; // filter order
|
||||||
float f0 = ((double) 19000 / bw);
|
// float f0 = ((double) 19000 / bw);
|
||||||
float fc = ((double) 19500 / bw);
|
// float fc = ((double) 19500 / bw);
|
||||||
float Ap = 1.0f;
|
// float Ap = 1.0f;
|
||||||
As = 60.0f;
|
// As = 60.0f;
|
||||||
iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As);
|
// iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As);
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
lastParams = params;
|
lastParams = params;
|
||||||
@ -218,7 +218,6 @@ void DemodulatorPreThread::run() {
|
|||||||
msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten);
|
msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten);
|
||||||
|
|
||||||
resamp->setRefCount(1);
|
resamp->setRefCount(1);
|
||||||
|
|
||||||
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
|
resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten);
|
||||||
|
|
||||||
// bool uneven = (numWritten % 2 != 0);
|
// bool uneven = (numWritten % 2 != 0);
|
||||||
@ -245,13 +244,13 @@ void DemodulatorPreThread::run() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
resamp->audioResampleRatio = audioResampleRatio;
|
// resamp->audioResampleRatio = audioResampleRatio;
|
||||||
resamp->audioResampler = audioResampler;
|
// resamp->audioResampler = audioResampler;
|
||||||
resamp->audioSampleRate = params.audioSampleRate;
|
// resamp->audioSampleRate = params.audioSampleRate;
|
||||||
resamp->stereoResampler = stereoResampler;
|
// resamp->stereoResampler = stereoResampler;
|
||||||
resamp->firStereoLeft = firStereoLeft;
|
// resamp->firStereoLeft = firStereoLeft;
|
||||||
resamp->firStereoRight = firStereoRight;
|
// resamp->firStereoRight = firStereoRight;
|
||||||
resamp->iirStereoPilot = iirStereoPilot;
|
// resamp->iirStereoPilot = iirStereoPilot;
|
||||||
resamp->sampleRate = params.bandwidth;
|
resamp->sampleRate = params.bandwidth;
|
||||||
|
|
||||||
iqOutputQueue->push(resamp);
|
iqOutputQueue->push(resamp);
|
||||||
|
@ -13,21 +13,21 @@
|
|||||||
|
|
||||||
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) {
|
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) {
|
||||||
|
|
||||||
stereo.store(false);
|
// stereo.store(false);
|
||||||
muted.store(false);
|
muted.store(false);
|
||||||
agcEnabled.store(false);
|
agcEnabled.store(false);
|
||||||
demodulatorType.store(DEMOD_TYPE_FM);
|
demodulatorType.store(DEMOD_TYPE_FM);
|
||||||
|
|
||||||
demodFM = freqdem_create(0.5);
|
// demodFM = freqdem_create(0.5);
|
||||||
demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1);
|
// 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_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 = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1);
|
||||||
demodAM_DSB_CSP = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
// demodAM_DSB_CSP = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
||||||
demodAM = demodAM_DSB_CSP;
|
// demodAM = demodAM_DSB_CSP;
|
||||||
|
|
||||||
// advanced demodulators
|
// advanced demodulators
|
||||||
|
|
||||||
demodulatorCons.store(2);
|
/* demodulatorCons.store(2);
|
||||||
currentDemodCons = 0;
|
currentDemodCons = 0;
|
||||||
|
|
||||||
demodASK = demodASK2;
|
demodASK = demodASK2;
|
||||||
@ -90,7 +90,7 @@ DemodulatorThread::DemodulatorThread() : IOThread(), iqAutoGain(NULL), amOutputC
|
|||||||
|
|
||||||
demodQPSK = modem_create(LIQUID_MODEM_QPSK);
|
demodQPSK = modem_create(LIQUID_MODEM_QPSK);
|
||||||
|
|
||||||
currentDemodLock = false;
|
currentDemodLock = false; */
|
||||||
|
|
||||||
}
|
}
|
||||||
DemodulatorThread::~DemodulatorThread() {
|
DemodulatorThread::~DemodulatorThread() {
|
||||||
@ -110,23 +110,23 @@ void DemodulatorThread::run() {
|
|||||||
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
pthread_setschedparam(tID, SCHED_FIFO, &prio);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
msresamp_rrrf audioResampler = NULL;
|
// msresamp_rrrf audioResampler = NULL;
|
||||||
msresamp_rrrf stereoResampler = NULL;
|
// msresamp_rrrf stereoResampler = NULL;
|
||||||
firfilt_rrrf firStereoLeft = NULL;
|
// firfilt_rrrf firStereoLeft = NULL;
|
||||||
firfilt_rrrf firStereoRight = NULL;
|
// firfilt_rrrf firStereoRight = NULL;
|
||||||
iirfilt_crcf iirStereoPilot = NULL;
|
// iirfilt_crcf iirStereoPilot = NULL;
|
||||||
|
|
||||||
liquid_float_complex u, v, w, x, y;
|
// liquid_float_complex u, v, w, x, y;
|
||||||
|
|
||||||
firhilbf firStereoR2C = firhilbf_create(5, 60.0f);
|
// firhilbf firStereoR2C = firhilbf_create(5, 60.0f);
|
||||||
firhilbf firStereoC2R = firhilbf_create(5, 60.0f);
|
// firhilbf firStereoC2R = firhilbf_create(5, 60.0f);
|
||||||
|
|
||||||
nco_crcf stereoPilot = nco_crcf_create(LIQUID_VCO);
|
// nco_crcf stereoPilot = nco_crcf_create(LIQUID_VCO);
|
||||||
nco_crcf_reset(stereoPilot);
|
// nco_crcf_reset(stereoPilot);
|
||||||
nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f);
|
// nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f);
|
||||||
|
|
||||||
// half band filter used for side-band elimination
|
// half band filter used for side-band elimination
|
||||||
resamp2_crcf ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
// resamp2_crcf ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
||||||
|
|
||||||
// Automatic IQ gain
|
// Automatic IQ gain
|
||||||
iqAutoGain = agc_crcf_create();
|
iqAutoGain = agc_crcf_create();
|
||||||
@ -141,22 +141,22 @@ void DemodulatorThread::run() {
|
|||||||
threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue");
|
threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue");
|
||||||
threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue");
|
threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue");
|
||||||
|
|
||||||
switch (demodulatorType.load()) {
|
// switch (demodulatorType.load()) {
|
||||||
case DEMOD_TYPE_FM:
|
// case DEMOD_TYPE_FM:
|
||||||
break;
|
// break;
|
||||||
case DEMOD_TYPE_LSB:
|
// case DEMOD_TYPE_LSB:
|
||||||
demodAM = demodAM_LSB;
|
// demodAM = demodAM_LSB;
|
||||||
break;
|
// break;
|
||||||
case DEMOD_TYPE_USB:
|
// case DEMOD_TYPE_USB:
|
||||||
demodAM = demodAM_USB;
|
// demodAM = demodAM_USB;
|
||||||
break;
|
// break;
|
||||||
case DEMOD_TYPE_DSB:
|
// case DEMOD_TYPE_DSB:
|
||||||
demodAM = demodAM_DSB;
|
// demodAM = demodAM_DSB;
|
||||||
break;
|
// break;
|
||||||
case DEMOD_TYPE_AM:
|
// case DEMOD_TYPE_AM:
|
||||||
demodAM = demodAM_DSB_CSP;
|
// demodAM = demodAM_DSB_CSP;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
DemodulatorThreadPostIQData *inp;
|
DemodulatorThreadPostIQData *inp;
|
||||||
@ -170,47 +170,47 @@ void DemodulatorThread::run() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioResampler == NULL) {
|
// if (audioResampler == NULL) {
|
||||||
audioResampler = inp->audioResampler;
|
// audioResampler = inp->audioResampler;
|
||||||
stereoResampler = inp->stereoResampler;
|
// stereoResampler = inp->stereoResampler;
|
||||||
firStereoLeft = inp->firStereoLeft;
|
// firStereoLeft = inp->firStereoLeft;
|
||||||
firStereoRight = inp->firStereoRight;
|
// firStereoRight = inp->firStereoRight;
|
||||||
iirStereoPilot = inp->iirStereoPilot;
|
// iirStereoPilot = inp->iirStereoPilot;
|
||||||
audioSampleRate = inp->audioSampleRate;
|
// audioSampleRate = inp->audioSampleRate;
|
||||||
} else if (audioResampler != inp->audioResampler) {
|
// } else if (audioResampler != inp->audioResampler) {
|
||||||
msresamp_rrrf_destroy(audioResampler);
|
// msresamp_rrrf_destroy(audioResampler);
|
||||||
msresamp_rrrf_destroy(stereoResampler);
|
// msresamp_rrrf_destroy(stereoResampler);
|
||||||
audioResampler = inp->audioResampler;
|
// audioResampler = inp->audioResampler;
|
||||||
stereoResampler = inp->stereoResampler;
|
// stereoResampler = inp->stereoResampler;
|
||||||
audioSampleRate = inp->audioSampleRate;
|
// audioSampleRate = inp->audioSampleRate;
|
||||||
|
//
|
||||||
if (demodAM) {
|
// if (demodAM) {
|
||||||
ampmodem_reset(demodAM);
|
// ampmodem_reset(demodAM);
|
||||||
}
|
// }
|
||||||
freqdem_reset(demodFM);
|
// freqdem_reset(demodFM);
|
||||||
nco_crcf_reset(stereoPilot);
|
// nco_crcf_reset(stereoPilot);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (firStereoLeft != inp->firStereoLeft) {
|
// if (firStereoLeft != inp->firStereoLeft) {
|
||||||
if (firStereoLeft != NULL) {
|
// if (firStereoLeft != NULL) {
|
||||||
firfilt_rrrf_destroy(firStereoLeft);
|
// firfilt_rrrf_destroy(firStereoLeft);
|
||||||
}
|
// }
|
||||||
firStereoLeft = inp->firStereoLeft;
|
// firStereoLeft = inp->firStereoLeft;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (firStereoRight != inp->firStereoRight) {
|
// if (firStereoRight != inp->firStereoRight) {
|
||||||
if (firStereoRight != NULL) {
|
// if (firStereoRight != NULL) {
|
||||||
firfilt_rrrf_destroy(firStereoRight);
|
// firfilt_rrrf_destroy(firStereoRight);
|
||||||
}
|
// }
|
||||||
firStereoRight = inp->firStereoRight;
|
// firStereoRight = inp->firStereoRight;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (iirStereoPilot != inp->iirStereoPilot) {
|
// if (iirStereoPilot != inp->iirStereoPilot) {
|
||||||
if (iirStereoPilot != NULL) {
|
// if (iirStereoPilot != NULL) {
|
||||||
iirfilt_crcf_destroy(iirStereoPilot);
|
// iirfilt_crcf_destroy(iirStereoPilot);
|
||||||
}
|
// }
|
||||||
iirStereoPilot = inp->iirStereoPilot;
|
// iirStereoPilot = inp->iirStereoPilot;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (agcData.size() != bufSize) {
|
if (agcData.size() != bufSize) {
|
||||||
if (agcData.capacity() < bufSize) {
|
if (agcData.capacity() < bufSize) {
|
||||||
@ -221,23 +221,24 @@ void DemodulatorThread::run() {
|
|||||||
agcAMData.resize(bufSize);
|
agcAMData.resize(bufSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
double audio_resample_ratio = inp->audioResampleRatio;
|
// double audio_resample_ratio = inp->audioResampleRatio;
|
||||||
|
|
||||||
if (demodOutputData.size() != bufSize) {
|
// if (demodOutputData.size() != bufSize) {
|
||||||
if (demodOutputData.capacity() < bufSize) {
|
// if (demodOutputData.capacity() < bufSize) {
|
||||||
demodOutputData.reserve(bufSize);
|
// demodOutputData.reserve(bufSize);
|
||||||
}
|
// }
|
||||||
demodOutputData.resize(bufSize);
|
// demodOutputData.resize(bufSize);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
if (demodOutputDataDigital.size() != bufSize) {
|
if (demodOutputDataDigital.size() != bufSize) {
|
||||||
if (demodOutputDataDigital.capacity() < bufSize) {
|
if (demodOutputDataDigital.capacity() < bufSize) {
|
||||||
demodOutputDataDigital.reserve(bufSize);
|
demodOutputDataDigital.reserve(bufSize);
|
||||||
}
|
}
|
||||||
demodOutputDataDigital.resize(bufSize);
|
demodOutputDataDigital.resize(bufSize);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
|
// int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
|
||||||
|
|
||||||
agc_crcf_execute_block(iqAutoGain, &(inp->data[0]), bufSize, &agcData[0]);
|
agc_crcf_execute_block(iqAutoGain, &(inp->data[0]), bufSize, &agcData[0]);
|
||||||
|
|
||||||
@ -258,8 +259,8 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset demodulator Constellations & Lock
|
// Reset demodulator Constellations & Lock
|
||||||
updateDemodulatorCons(0);
|
// updateDemodulatorCons(0);
|
||||||
|
/*
|
||||||
if (demodulatorType == DEMOD_TYPE_FM) {
|
if (demodulatorType == DEMOD_TYPE_FM) {
|
||||||
currentDemodLock = false;
|
currentDemodLock = false;
|
||||||
freqdem_demodulate_block(demodFM, &(*inputData)[0], bufSize, &demodOutputData[0]);
|
freqdem_demodulate_block(demodFM, &(*inputData)[0], bufSize, &demodOutputData[0]);
|
||||||
@ -669,7 +670,7 @@ void DemodulatorThread::run() {
|
|||||||
|
|
||||||
msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
|
msresamp_rrrf_execute(stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (currentSignalLevel > signalLevel) {
|
if (currentSignalLevel > signalLevel) {
|
||||||
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5;
|
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5;
|
||||||
@ -681,13 +682,14 @@ void DemodulatorThread::run() {
|
|||||||
|
|
||||||
if (audioOutputQueue != NULL) {
|
if (audioOutputQueue != NULL) {
|
||||||
if (!squelchEnabled || (signalLevel >= squelchLevel)) {
|
if (!squelchEnabled || (signalLevel >= squelchLevel)) {
|
||||||
|
|
||||||
ati = outputBuffers.getBuffer();
|
ati = outputBuffers.getBuffer();
|
||||||
|
|
||||||
ati->sampleRate = audioSampleRate;
|
ati->sampleRate = audioSampleRate;
|
||||||
ati->inputRate = inp->sampleRate;
|
ati->inputRate = inp->sampleRate;
|
||||||
ati->setRefCount(1);
|
ati->setRefCount(1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
if (demodulatorType == DEMOD_TYPE_RAW) {
|
if (demodulatorType == DEMOD_TYPE_RAW) {
|
||||||
ati->channels = 2;
|
ati->channels = 2;
|
||||||
if (ati->data.capacity() < (numAudioWritten * 2)) {
|
if (ati->data.capacity() < (numAudioWritten * 2)) {
|
||||||
@ -720,7 +722,7 @@ void DemodulatorThread::run() {
|
|||||||
ati->channels = 1;
|
ati->channels = 1;
|
||||||
ati->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten);
|
ati->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
std::vector<float>::iterator data_i;
|
std::vector<float>::iterator data_i;
|
||||||
ati->peak = 0;
|
ati->peak = 0;
|
||||||
for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) {
|
for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) {
|
||||||
@ -731,7 +733,7 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) {
|
if (ati && audioVisOutputQueue != NULL && audioVisOutputQueue->empty()) {
|
||||||
AudioThreadInput *ati_vis = audioVisBuffers.getBuffer();
|
AudioThreadInput *ati_vis = audioVisBuffers.getBuffer();
|
||||||
ati_vis->setRefCount(1);
|
ati_vis->setRefCount(1);
|
||||||
@ -762,6 +764,7 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
int numAudioWritten = ati->data.size();
|
||||||
ati_vis->channels = 1;
|
ati_vis->channels = 1;
|
||||||
if (numAudioWritten > bufSize) {
|
if (numAudioWritten > bufSize) {
|
||||||
ati_vis->inputRate = audioSampleRate;
|
ati_vis->inputRate = audioSampleRate;
|
||||||
@ -781,6 +784,7 @@ void DemodulatorThread::run() {
|
|||||||
|
|
||||||
audioVisOutputQueue->push(ati_vis);
|
audioVisOutputQueue->push(ati_vis);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (ati != NULL) {
|
if (ati != NULL) {
|
||||||
if (!muted.load()) {
|
if (!muted.load()) {
|
||||||
@ -791,7 +795,7 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!threadQueueControl->empty()) {
|
if (!threadQueueControl->empty()) {
|
||||||
int newDemodType = DEMOD_TYPE_NULL;
|
// int newDemodType = DEMOD_TYPE_NULL;
|
||||||
|
|
||||||
while (!threadQueueControl->empty()) {
|
while (!threadQueueControl->empty()) {
|
||||||
DemodulatorThreadControlCommand command;
|
DemodulatorThreadControlCommand command;
|
||||||
@ -804,14 +808,14 @@ void DemodulatorThread::run() {
|
|||||||
case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF:
|
case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF:
|
||||||
squelchEnabled = false;
|
squelchEnabled = false;
|
||||||
break;
|
break;
|
||||||
case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE:
|
// case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE:
|
||||||
newDemodType = command.demodType;
|
// newDemodType = command.demodType;
|
||||||
break;
|
// break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (newDemodType != DEMOD_TYPE_NULL) {
|
if (newDemodType != DEMOD_TYPE_NULL) {
|
||||||
switch (newDemodType) {
|
switch (newDemodType) {
|
||||||
case DEMOD_TYPE_FM:
|
case DEMOD_TYPE_FM:
|
||||||
@ -868,15 +872,15 @@ void DemodulatorThread::run() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
demodulatorType = newDemodType;
|
demodulatorType = newDemodType;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
demodOutputDataDigital.empty();
|
// demodOutputDataDigital.empty();
|
||||||
|
|
||||||
inp->decRefCount();
|
inp->decRefCount();
|
||||||
}
|
}
|
||||||
// end while !terminated
|
// end while !terminated
|
||||||
|
/*
|
||||||
if (audioResampler != NULL) {
|
if (audioResampler != NULL) {
|
||||||
msresamp_rrrf_destroy(audioResampler);
|
msresamp_rrrf_destroy(audioResampler);
|
||||||
}
|
}
|
||||||
@ -898,7 +902,7 @@ void DemodulatorThread::run() {
|
|||||||
firhilbf_destroy(firStereoC2R);
|
firhilbf_destroy(firStereoC2R);
|
||||||
nco_crcf_destroy(stereoPilot);
|
nco_crcf_destroy(stereoPilot);
|
||||||
resamp2_crcf_destroy(ssbFilt);
|
resamp2_crcf_destroy(ssbFilt);
|
||||||
|
*/
|
||||||
outputBuffers.purge();
|
outputBuffers.purge();
|
||||||
|
|
||||||
if (audioVisOutputQueue && !audioVisOutputQueue->empty()) {
|
if (audioVisOutputQueue && !audioVisOutputQueue->empty()) {
|
||||||
@ -920,14 +924,14 @@ void DemodulatorThread::terminate() {
|
|||||||
iqInputQueue->push(inp);
|
iqInputQueue->push(inp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorThread::setStereo(bool state) {
|
//void DemodulatorThread::setStereo(bool state) {
|
||||||
stereo.store(state);
|
// stereo.store(state);
|
||||||
std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl;
|
// std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl;
|
||||||
}
|
//}
|
||||||
|
|
||||||
bool DemodulatorThread::isStereo() {
|
//bool DemodulatorThread::isStereo() {
|
||||||
return stereo.load();
|
// return stereo.load();
|
||||||
}
|
//}
|
||||||
|
|
||||||
bool DemodulatorThread::isMuted() {
|
bool DemodulatorThread::isMuted() {
|
||||||
return muted.load();
|
return muted.load();
|
||||||
|
@ -21,8 +21,8 @@ public:
|
|||||||
void run();
|
void run();
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
void setStereo(bool state);
|
// void setStereo(bool state);
|
||||||
bool isStereo();
|
// bool isStereo();
|
||||||
|
|
||||||
void setAGC(bool state);
|
void setAGC(bool state);
|
||||||
bool getAGC();
|
bool getAGC();
|
||||||
@ -42,35 +42,35 @@ public:
|
|||||||
|
|
||||||
void setDemodulatorCons(int demod_cons_in);
|
void setDemodulatorCons(int demod_cons_in);
|
||||||
int getDemodulatorCons();
|
int getDemodulatorCons();
|
||||||
|
//
|
||||||
#ifdef __APPLE__
|
//#ifdef __APPLE__
|
||||||
static void *pthread_helper(void *context) {
|
// static void *pthread_helper(void *context) {
|
||||||
return ((DemodulatorThread *) context)->threadMain();
|
// return ((DemodulatorThread *) context)->threadMain();
|
||||||
}
|
// }
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ReBuffer<AudioThreadInput> outputBuffers;
|
ReBuffer<AudioThreadInput> outputBuffers;
|
||||||
|
|
||||||
std::vector<liquid_float_complex> agcData;
|
std::vector<liquid_float_complex> agcData;
|
||||||
std::vector<float> agcAMData;
|
std::vector<float> agcAMData;
|
||||||
std::vector<float> demodOutputData;
|
// std::vector<float> demodOutputData;
|
||||||
std::vector<float> demodStereoData;
|
// std::vector<float> demodStereoData;
|
||||||
std::vector<float> resampledOutputData;
|
// std::vector<float> resampledOutputData;
|
||||||
std::vector<float> resampledStereoData;
|
// std::vector<float> resampledStereoData;
|
||||||
std::vector<unsigned int> demodOutputDataDigital;
|
std::vector<unsigned int> demodOutputDataDigital;
|
||||||
//std::vector<unsigned int> demodOutputDataDigitalTest;
|
//std::vector<unsigned int> demodOutputDataDigitalTest;
|
||||||
|
|
||||||
//std::vector<unsigned char> demodOutputSoftbits;
|
//std::vector<unsigned char> demodOutputSoftbits;
|
||||||
//std::vector<unsigned char> demodOutputSoftbitsTest;
|
//std::vector<unsigned char> demodOutputSoftbitsTest;
|
||||||
|
|
||||||
freqdem demodFM;
|
// freqdem demodFM;
|
||||||
ampmodem demodAM;
|
// ampmodem demodAM;
|
||||||
ampmodem demodAM_DSB_CSP;
|
// ampmodem demodAM_DSB_CSP;
|
||||||
ampmodem demodAM_DSB;
|
// ampmodem demodAM_DSB;
|
||||||
ampmodem demodAM_LSB;
|
// ampmodem demodAM_LSB;
|
||||||
ampmodem demodAM_USB;
|
// ampmodem demodAM_USB;
|
||||||
|
/*
|
||||||
modem demodASK;
|
modem demodASK;
|
||||||
modem demodASK2;
|
modem demodASK2;
|
||||||
modem demodASK4;
|
modem demodASK4;
|
||||||
@ -130,14 +130,14 @@ protected:
|
|||||||
modem demodQAM256;
|
modem demodQAM256;
|
||||||
|
|
||||||
modem demodQPSK;
|
modem demodQPSK;
|
||||||
|
*/
|
||||||
agc_crcf iqAutoGain;
|
agc_crcf iqAutoGain;
|
||||||
|
|
||||||
float amOutputCeil;
|
float amOutputCeil;
|
||||||
float amOutputCeilMA;
|
float amOutputCeilMA;
|
||||||
float amOutputCeilMAA;
|
float amOutputCeilMAA;
|
||||||
|
|
||||||
std::atomic_bool stereo;
|
// std::atomic_bool stereo;
|
||||||
std::atomic_bool muted;
|
std::atomic_bool muted;
|
||||||
std::atomic_bool agcEnabled;
|
std::atomic_bool agcEnabled;
|
||||||
std::atomic_int demodulatorType;
|
std::atomic_int demodulatorType;
|
||||||
|
@ -47,12 +47,12 @@ void DemodulatorWorkerThread::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (filterCommand.bandwidth && filterCommand.audioSampleRate) {
|
if (filterCommand.bandwidth && filterCommand.audioSampleRate) {
|
||||||
result.audioResamplerRatio = (double) (filterCommand.audioSampleRate) / (double) filterCommand.bandwidth;
|
// result.audioResamplerRatio = (double) (filterCommand.audioSampleRate) / (double) filterCommand.bandwidth;
|
||||||
result.audioResampler = msresamp_rrrf_create(result.audioResamplerRatio, As);
|
// result.audioResampler = msresamp_rrrf_create(result.audioResamplerRatio, As);
|
||||||
result.stereoResampler = msresamp_rrrf_create(result.audioResamplerRatio, As);
|
// result.stereoResampler = msresamp_rrrf_create(result.audioResamplerRatio, As);
|
||||||
result.audioSampleRate = filterCommand.audioSampleRate;
|
// result.audioSampleRate = filterCommand.audioSampleRate;
|
||||||
|
|
||||||
// Stereo filters / shifters
|
/* // Stereo filters / shifters
|
||||||
double firStereoCutoff = ((double) 16000 / (double) filterCommand.audioSampleRate);
|
double firStereoCutoff = ((double) 16000 / (double) filterCommand.audioSampleRate);
|
||||||
float ft = ((double) 1000 / (double) filterCommand.audioSampleRate); // filter transition
|
float ft = ((double) 1000 / (double) filterCommand.audioSampleRate); // filter transition
|
||||||
float mu = 0.0f; // fractional timing offset
|
float mu = 0.0f; // fractional timing offset
|
||||||
@ -83,7 +83,7 @@ void DemodulatorWorkerThread::run() {
|
|||||||
float Ap = 1.0f;
|
float Ap = 1.0f;
|
||||||
As = 60.0f;
|
As = 60.0f;
|
||||||
|
|
||||||
result.iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As);
|
result.iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As); */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterCommand.bandwidth) {
|
if (filterCommand.bandwidth) {
|
||||||
|
@ -37,6 +37,8 @@ public:
|
|||||||
firfilt_rrrf firStereoRight;
|
firfilt_rrrf firStereoRight;
|
||||||
iirfilt_crcf iirStereoPilot;
|
iirfilt_crcf iirStereoPilot;
|
||||||
|
|
||||||
|
DemodulatorThread *demodThread;
|
||||||
|
|
||||||
long long sampleRate;
|
long long sampleRate;
|
||||||
unsigned int bandwidth;
|
unsigned int bandwidth;
|
||||||
unsigned int audioSampleRate;
|
unsigned int audioSampleRate;
|
||||||
|
27
src/modules/modem/Modem.cpp
Normal file
27
src/modules/modem/Modem.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "Modem.h"
|
||||||
|
|
||||||
|
ModemFactoryList Modem::modemFactories;
|
||||||
|
|
||||||
|
void Modem::addModemFactory(std::string modemName, ModemFactoryFunc *factoryFunc) {
|
||||||
|
modemFactories[modemName] = factoryFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemFactoryList Modem::getFactories() {
|
||||||
|
return modemFactories;
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *Modem::factory() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemKit *Modem::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modem::disposeKit(ModemKit *kit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Modem::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
return;
|
||||||
|
}
|
48
src/modules/modem/Modem.h
Normal file
48
src/modules/modem/Modem.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "liquid/liquid.h"
|
||||||
|
#include "IOThread.h"
|
||||||
|
#include "AudioThread.h"
|
||||||
|
|
||||||
|
class ModemKit {
|
||||||
|
public:
|
||||||
|
ModemKit() : sampleRate(0), audioSampleRate(0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
long long sampleRate;
|
||||||
|
int audioSampleRate;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModemIQData: public ReferenceCounter {
|
||||||
|
public:
|
||||||
|
std::vector<liquid_float_complex> data;
|
||||||
|
long long sampleRate;
|
||||||
|
|
||||||
|
ModemIQData() : sampleRate(0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~ModemIQData() {
|
||||||
|
std::lock_guard < std::mutex > lock(m_mutex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Modem;
|
||||||
|
typedef Modem *(Modem::*ModemFactoryFunc)();
|
||||||
|
typedef std::map<std::string,ModemFactoryFunc *> ModemFactoryList;
|
||||||
|
|
||||||
|
class Modem {
|
||||||
|
public:
|
||||||
|
static void addModemFactory(std::string modemName, ModemFactoryFunc *factoryFunc);
|
||||||
|
static ModemFactoryList getFactories();
|
||||||
|
|
||||||
|
virtual Modem *factory();
|
||||||
|
|
||||||
|
virtual ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
|
virtual void disposeKit(ModemKit *kit);
|
||||||
|
virtual void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
private:
|
||||||
|
static ModemFactoryList modemFactories;
|
||||||
|
};
|
78
src/modules/modem/ModemAnalog.cpp
Normal file
78
src/modules/modem/ModemAnalog.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
|
ModemAnalog::ModemAnalog() : aOutputCeil(1), aOutputCeilMA(1), aOutputCeilMAA(1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemKit *ModemAnalog::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
|
ModemKitAnalog *akit = new ModemKitAnalog;
|
||||||
|
|
||||||
|
// stop-band attenuation [dB]
|
||||||
|
float As = 60.0f;
|
||||||
|
|
||||||
|
akit->sampleRate = sampleRate;
|
||||||
|
akit->audioSampleRate = audioSampleRate;
|
||||||
|
akit->audioResampleRatio = double(audioSampleRate) / double(sampleRate);
|
||||||
|
akit->audioResampler = msresamp_rrrf_create(akit->audioResampleRatio, As);
|
||||||
|
|
||||||
|
return akit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemAnalog::disposeKit(ModemKit *kit) {
|
||||||
|
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
msresamp_rrrf_destroy(akit->audioResampler);
|
||||||
|
delete kit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemAnalog::initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input) {
|
||||||
|
bufSize = input->data.size();
|
||||||
|
|
||||||
|
if (!bufSize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double audio_resample_ratio = akit->audioResampleRatio;
|
||||||
|
|
||||||
|
int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
|
||||||
|
|
||||||
|
if (demodOutputData.size() != bufSize) {
|
||||||
|
if (demodOutputData.capacity() < bufSize) {
|
||||||
|
demodOutputData.reserve(bufSize);
|
||||||
|
}
|
||||||
|
demodOutputData.resize(bufSize);
|
||||||
|
}
|
||||||
|
if (resampledOutputData.size() != audio_out_size) {
|
||||||
|
if (resampledOutputData.capacity() < audio_out_size) {
|
||||||
|
resampledOutputData.reserve(audio_out_size);
|
||||||
|
}
|
||||||
|
resampledOutputData.resize(audio_out_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemAnalog::buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain) {
|
||||||
|
unsigned int numAudioWritten;
|
||||||
|
|
||||||
|
if (autoGain) {
|
||||||
|
aOutputCeilMA = aOutputCeilMA + (aOutputCeil - aOutputCeilMA) * 0.025;
|
||||||
|
aOutputCeilMAA = aOutputCeilMAA + (aOutputCeilMA - aOutputCeilMAA) * 0.025;
|
||||||
|
aOutputCeil = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < bufSize; i++) {
|
||||||
|
if (demodOutputData[i] > aOutputCeil) {
|
||||||
|
aOutputCeil = demodOutputData[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float gain = 0.5 / aOutputCeilMAA;
|
||||||
|
|
||||||
|
for (int i = 0; i < bufSize; i++) {
|
||||||
|
demodOutputData[i] *= gain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msresamp_rrrf_execute(akit->audioResampler, &demodOutputData[0], demodOutputData.size(), &resampledOutputData[0], &numAudioWritten);
|
||||||
|
|
||||||
|
audioOut->channels = 1;
|
||||||
|
audioOut->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten);
|
||||||
|
}
|
30
src/modules/modem/ModemAnalog.h
Normal file
30
src/modules/modem/ModemAnalog.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
||||||
|
class ModemKitAnalog : public ModemKit {
|
||||||
|
public:
|
||||||
|
ModemKitAnalog() : ModemKit(), audioResampler(nullptr), audioResampleRatio(0) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
msresamp_rrrf audioResampler;
|
||||||
|
double audioResampleRatio;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModemAnalog : public Modem {
|
||||||
|
public:
|
||||||
|
ModemAnalog();
|
||||||
|
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
|
void disposeKit(ModemKit *kit);
|
||||||
|
void initOutputBuffers(ModemKitAnalog *akit, ModemIQData *input);
|
||||||
|
void buildAudioOutput(ModemKitAnalog *akit, AudioThreadInput *audioOut, bool autoGain);
|
||||||
|
protected:
|
||||||
|
int bufSize;
|
||||||
|
std::vector<float> demodOutputData;
|
||||||
|
std::vector<float> resampledOutputData;
|
||||||
|
|
||||||
|
float aOutputCeil;
|
||||||
|
float aOutputCeilMA;
|
||||||
|
float aOutputCeilMAA;
|
||||||
|
};
|
24
src/modules/modem/analog/ModemAM.cpp
Normal file
24
src/modules/modem/analog/ModemAM.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "ModemAM.h"
|
||||||
|
|
||||||
|
ModemAM::ModemAM() {
|
||||||
|
demodAM = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemAM::factory() {
|
||||||
|
return new ModemAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemAM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
ModemKitAnalog *amkit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
initOutputBuffers(amkit,input);
|
||||||
|
|
||||||
|
if (!bufSize) {
|
||||||
|
input->decRefCount();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ampmodem_demodulate_block(demodAM, &input->data[0], bufSize, &demodOutputData[0]);
|
||||||
|
|
||||||
|
buildAudioOutput(amkit,audioOut,true);
|
||||||
|
}
|
13
src/modules/modem/analog/ModemAM.h
Normal file
13
src/modules/modem/analog/ModemAM.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
|
class ModemAM : public ModemAnalog {
|
||||||
|
public:
|
||||||
|
ModemAM();
|
||||||
|
Modem *factory();
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ampmodem demodAM;
|
||||||
|
};
|
24
src/modules/modem/analog/ModemDSB.cpp
Normal file
24
src/modules/modem/analog/ModemDSB.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "ModemDSB.h"
|
||||||
|
|
||||||
|
ModemDSB::ModemDSB() {
|
||||||
|
demodAM_DSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_DSB, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemDSB::factory() {
|
||||||
|
return new ModemDSB;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemDSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
ModemKitAnalog *amkit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
initOutputBuffers(amkit, input);
|
||||||
|
|
||||||
|
if (!bufSize) {
|
||||||
|
input->decRefCount();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ampmodem_demodulate_block(demodAM_DSB, &input->data[0], bufSize, &demodOutputData[0]);
|
||||||
|
|
||||||
|
buildAudioOutput(amkit, audioOut, true);
|
||||||
|
}
|
13
src/modules/modem/analog/ModemDSB.h
Normal file
13
src/modules/modem/analog/ModemDSB.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
|
class ModemDSB : public ModemAnalog {
|
||||||
|
public:
|
||||||
|
ModemDSB();
|
||||||
|
Modem *factory();
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ampmodem demodAM_DSB;
|
||||||
|
};
|
24
src/modules/modem/analog/ModemFM.cpp
Normal file
24
src/modules/modem/analog/ModemFM.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "ModemFM.h"
|
||||||
|
|
||||||
|
ModemFM::ModemFM() {
|
||||||
|
demodFM = freqdem_create(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemFM::factory() {
|
||||||
|
return new ModemFM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemFM::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
ModemKitAnalog *fmkit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
initOutputBuffers(fmkit, input);
|
||||||
|
|
||||||
|
if (!bufSize) {
|
||||||
|
input->decRefCount();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
freqdem_demodulate_block(demodFM, &input->data[0], bufSize, &demodOutputData[0]);
|
||||||
|
|
||||||
|
buildAudioOutput(fmkit, audioOut, false);
|
||||||
|
}
|
14
src/modules/modem/analog/ModemFM.h
Normal file
14
src/modules/modem/analog/ModemFM.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
|
class ModemFM : public ModemAnalog {
|
||||||
|
public:
|
||||||
|
ModemFM();
|
||||||
|
Modem *factory();
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
freqdem demodFM;
|
||||||
|
};
|
176
src/modules/modem/analog/ModemFMStereo.cpp
Normal file
176
src/modules/modem/analog/ModemFMStereo.cpp
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
#include "ModemFMStereo.h"
|
||||||
|
|
||||||
|
ModemFMStereo::ModemFMStereo() {
|
||||||
|
firStereoR2C = firhilbf_create(5, 60.0f);
|
||||||
|
firStereoC2R = firhilbf_create(5, 60.0f);
|
||||||
|
|
||||||
|
stereoPilot = nco_crcf_create(LIQUID_VCO);
|
||||||
|
nco_crcf_reset(stereoPilot);
|
||||||
|
nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemFMStereo::~ModemFMStereo() {
|
||||||
|
firhilbf_destroy(firStereoR2C);
|
||||||
|
firhilbf_destroy(firStereoC2R);
|
||||||
|
|
||||||
|
nco_crcf_destroy(stereoPilot);
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemFMStereo::factory() {
|
||||||
|
return new ModemFMStereo;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemKit *ModemFMStereo::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
|
ModemKitFMStereo *kit = new ModemKitFMStereo;
|
||||||
|
|
||||||
|
kit->audioResampleRatio = double(audioSampleRate) / double(sampleRate);
|
||||||
|
|
||||||
|
float As = 60.0f; // stop-band attenuation [dB]
|
||||||
|
|
||||||
|
kit->audioResampler = msresamp_rrrf_create(kit->audioResampleRatio, As);
|
||||||
|
kit->stereoResampler = msresamp_rrrf_create(kit->audioResampleRatio, As);
|
||||||
|
|
||||||
|
// Stereo filters / shifters
|
||||||
|
double firStereoCutoff = 16000.0 / double(audioSampleRate);
|
||||||
|
// filter transition
|
||||||
|
float ft = 1000.0 / double(audioSampleRate);
|
||||||
|
// fractional timing offset
|
||||||
|
float mu = 0.0f;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
kit->firStereoLeft = firfilt_rrrf_create(h, h_len);
|
||||||
|
kit->firStereoRight = firfilt_rrrf_create(h, h_len);
|
||||||
|
|
||||||
|
// stereo pilot filter
|
||||||
|
float bw = sampleRate;
|
||||||
|
if (bw < 100000.0) {
|
||||||
|
bw = 100000.0;
|
||||||
|
}
|
||||||
|
unsigned int order = 5; // filter order
|
||||||
|
float f0 = ((double) 19000 / bw);
|
||||||
|
float fc = ((double) 19500 / bw);
|
||||||
|
float Ap = 1.0f;
|
||||||
|
|
||||||
|
kit->iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As);
|
||||||
|
|
||||||
|
return kit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemFMStereo::disposeKit(ModemKit *kit) {
|
||||||
|
ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit;
|
||||||
|
|
||||||
|
msresamp_rrrf_destroy(fmkit->audioResampler);
|
||||||
|
msresamp_rrrf_destroy(fmkit->stereoResampler);
|
||||||
|
firfilt_rrrf_destroy(fmkit->firStereoLeft);
|
||||||
|
firfilt_rrrf_destroy(fmkit->firStereoRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ModemFMStereo::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit;
|
||||||
|
int bufSize = input->data.size();
|
||||||
|
liquid_float_complex u, v, w, x, y;
|
||||||
|
|
||||||
|
double audio_resample_ratio = fmkit->audioResampleRatio;
|
||||||
|
|
||||||
|
if (demodOutputData.size() != bufSize) {
|
||||||
|
if (demodOutputData.capacity() < bufSize) {
|
||||||
|
demodOutputData.reserve(bufSize);
|
||||||
|
}
|
||||||
|
demodOutputData.resize(bufSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int audio_out_size = ceil((double) (bufSize) * audio_resample_ratio) + 512;
|
||||||
|
|
||||||
|
freqdem_demodulate_block(demodFM, &input->data[0], bufSize, &demodOutputData[0]);
|
||||||
|
|
||||||
|
if (resampledOutputData.size() != audio_out_size) {
|
||||||
|
if (resampledOutputData.capacity() < audio_out_size) {
|
||||||
|
resampledOutputData.reserve(audio_out_size);
|
||||||
|
}
|
||||||
|
resampledOutputData.resize(audio_out_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int numAudioWritten;
|
||||||
|
|
||||||
|
msresamp_rrrf_execute(fmkit->audioResampler, &demodOutputData[0], bufSize, &resampledOutputData[0], &numAudioWritten);
|
||||||
|
|
||||||
|
if (demodStereoData.size() != bufSize) {
|
||||||
|
if (demodStereoData.capacity() < bufSize) {
|
||||||
|
demodStereoData.reserve(bufSize);
|
||||||
|
}
|
||||||
|
demodStereoData.resize(bufSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
float phase_error = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < bufSize; i++) {
|
||||||
|
// real -> complex
|
||||||
|
firhilbf_r2c_execute(firStereoR2C, demodOutputData[i], &x);
|
||||||
|
|
||||||
|
// 19khz pilot band-pass
|
||||||
|
iirfilt_crcf_execute(fmkit->iirStereoPilot, x, &v);
|
||||||
|
nco_crcf_cexpf(stereoPilot, &w);
|
||||||
|
|
||||||
|
w.imag = -w.imag; // conjf(w)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
phase_error = atan2f(u.imag,u.real);
|
||||||
|
|
||||||
|
// step pll
|
||||||
|
nco_crcf_pll_step(stereoPilot, phase_error);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::cout << "[PLL] phase error: " << phase_error;
|
||||||
|
// std::cout << " freq:" << (((nco_crcf_get_frequency(stereoPilot) / (2.0 * M_PI)) * inp->sampleRate)) << std::endl;
|
||||||
|
|
||||||
|
if (audio_out_size != resampledStereoData.size()) {
|
||||||
|
if (resampledStereoData.capacity() < audio_out_size) {
|
||||||
|
resampledStereoData.reserve(audio_out_size);
|
||||||
|
}
|
||||||
|
resampledStereoData.resize(audio_out_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
msresamp_rrrf_execute(fmkit->stereoResampler, &demodStereoData[0], bufSize, &resampledStereoData[0], &numAudioWritten);
|
||||||
|
|
||||||
|
audioOut->channels = 2;
|
||||||
|
if (audioOut->data.capacity() < (numAudioWritten * 2)) {
|
||||||
|
audioOut->data.reserve(numAudioWritten * 2);
|
||||||
|
}
|
||||||
|
audioOut->data.resize(numAudioWritten * 2);
|
||||||
|
for (int i = 0; i < numAudioWritten; i++) {
|
||||||
|
float l, r;
|
||||||
|
|
||||||
|
firfilt_rrrf_push(fmkit->firStereoLeft, 0.568 * (resampledOutputData[i] - (resampledStereoData[i])));
|
||||||
|
firfilt_rrrf_execute(fmkit->firStereoLeft, &l);
|
||||||
|
|
||||||
|
firfilt_rrrf_push(fmkit->firStereoRight, 0.568 * (resampledOutputData[i] + (resampledStereoData[i])));
|
||||||
|
firfilt_rrrf_execute(fmkit->firStereoRight, &r);
|
||||||
|
|
||||||
|
audioOut->data[i * 2] = l;
|
||||||
|
audioOut->data[i * 2 + 1] = r;
|
||||||
|
}
|
||||||
|
}
|
39
src/modules/modem/analog/ModemFMStereo.h
Normal file
39
src/modules/modem/analog/ModemFMStereo.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
||||||
|
class ModemKitFMStereo: public ModemKit {
|
||||||
|
public:
|
||||||
|
ModemKitFMStereo() : audioResampler(nullptr), stereoResampler(nullptr), audioResampleRatio(0), firStereoLeft(nullptr), firStereoRight(nullptr), iirStereoPilot(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
msresamp_rrrf audioResampler;
|
||||||
|
msresamp_rrrf stereoResampler;
|
||||||
|
double audioResampleRatio;
|
||||||
|
|
||||||
|
firfilt_rrrf firStereoLeft;
|
||||||
|
firfilt_rrrf firStereoRight;
|
||||||
|
iirfilt_crcf iirStereoPilot;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModemFMStereo : public Modem {
|
||||||
|
public:
|
||||||
|
ModemFMStereo();
|
||||||
|
~ModemFMStereo();
|
||||||
|
Modem *factory();
|
||||||
|
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
|
void disposeKit(ModemKit *kit);
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<float> demodOutputData;
|
||||||
|
std::vector<float> demodStereoData;
|
||||||
|
std::vector<float> resampledOutputData;
|
||||||
|
std::vector<float> resampledStereoData;
|
||||||
|
freqdem demodFM;
|
||||||
|
|
||||||
|
firhilbf firStereoR2C;
|
||||||
|
firhilbf firStereoC2R;
|
||||||
|
|
||||||
|
nco_crcf stereoPilot;
|
||||||
|
};
|
38
src/modules/modem/analog/ModemIQ.cpp
Normal file
38
src/modules/modem/analog/ModemIQ.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "ModemIQ.h"
|
||||||
|
|
||||||
|
ModemIQ::ModemIQ() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemIQ::factory() {
|
||||||
|
return new ModemIQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemKit *ModemIQ::buildKit(long long sampleRate, int audioSampleRate) {
|
||||||
|
ModemKit *kit = new ModemKit;
|
||||||
|
return kit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemIQ::disposeKit(ModemKit *kit) {
|
||||||
|
delete kit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemIQ::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
int bufSize = input->data.size();
|
||||||
|
|
||||||
|
if (!bufSize) {
|
||||||
|
input->decRefCount();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
audioOut->channels = 2;
|
||||||
|
if (audioOut->data.capacity() < (bufSize * 2)) {
|
||||||
|
audioOut->data.reserve(bufSize * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
audioOut->data.resize(bufSize * 2);
|
||||||
|
for (int i = 0; i < bufSize; i++) {
|
||||||
|
audioOut->data[i * 2] = input->data[i].imag;
|
||||||
|
audioOut->data[i * 2 + 1] = input->data[i].real;
|
||||||
|
}
|
||||||
|
}
|
14
src/modules/modem/analog/ModemIQ.h
Normal file
14
src/modules/modem/analog/ModemIQ.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
||||||
|
class ModemIQ : public Modem {
|
||||||
|
public:
|
||||||
|
ModemIQ();
|
||||||
|
Modem *factory();
|
||||||
|
ModemKit *buildKit(long long sampleRate, int audioSampleRate);
|
||||||
|
void disposeKit(ModemKit *kit);
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
35
src/modules/modem/analog/ModemLSB.cpp
Normal file
35
src/modules/modem/analog/ModemLSB.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "ModemLSB.h"
|
||||||
|
|
||||||
|
ModemLSB::ModemLSB() {
|
||||||
|
// half band filter used for side-band elimination
|
||||||
|
ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
||||||
|
demodAM_LSB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_LSB, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemLSB::factory() {
|
||||||
|
return new ModemLSB;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemLSB::~ModemLSB() {
|
||||||
|
resamp2_crcf_destroy(ssbFilt);
|
||||||
|
ampmodem_destroy(demodAM_LSB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemLSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
initOutputBuffers(akit,input);
|
||||||
|
|
||||||
|
if (!bufSize) {
|
||||||
|
input->decRefCount();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
liquid_float_complex x, y;
|
||||||
|
for (int i = 0; i < bufSize; i++) { // Reject upper band
|
||||||
|
resamp2_crcf_filter_execute(ssbFilt,input->data[i],&x,&y);
|
||||||
|
ampmodem_demodulate(demodAM_LSB, x, &demodOutputData[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAudioOutput(akit, audioOut, true);
|
||||||
|
}
|
15
src/modules/modem/analog/ModemLSB.h
Normal file
15
src/modules/modem/analog/ModemLSB.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
|
class ModemLSB : public ModemAnalog {
|
||||||
|
public:
|
||||||
|
ModemLSB();
|
||||||
|
~ModemLSB();
|
||||||
|
Modem *factory();
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
resamp2_crcf ssbFilt;
|
||||||
|
ampmodem demodAM_LSB;
|
||||||
|
};
|
36
src/modules/modem/analog/ModemUSB.cpp
Normal file
36
src/modules/modem/analog/ModemUSB.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "ModemUSB.h"
|
||||||
|
|
||||||
|
ModemUSB::ModemUSB() {
|
||||||
|
// half band filter used for side-band elimination
|
||||||
|
ssbFilt = resamp2_crcf_create(12,-0.25f,60.0f);
|
||||||
|
demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Modem *ModemUSB::factory() {
|
||||||
|
return new ModemUSB;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemUSB::~ModemUSB() {
|
||||||
|
resamp2_crcf_destroy(ssbFilt);
|
||||||
|
ampmodem_destroy(demodAM_USB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModemUSB::demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut) {
|
||||||
|
ModemKitAnalog *akit = (ModemKitAnalog *)kit;
|
||||||
|
|
||||||
|
initOutputBuffers(akit,input);
|
||||||
|
|
||||||
|
if (!bufSize) {
|
||||||
|
input->decRefCount();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
liquid_float_complex x, y;
|
||||||
|
for (int i = 0; i < bufSize; i++) { // Reject lower band
|
||||||
|
resamp2_crcf_filter_execute(ssbFilt,input->data[i],&x,&y);
|
||||||
|
ampmodem_demodulate(demodAM_USB, y, &demodOutputData[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAudioOutput(akit, audioOut, true);
|
||||||
|
}
|
||||||
|
|
14
src/modules/modem/analog/ModemUSB.h
Normal file
14
src/modules/modem/analog/ModemUSB.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ModemAnalog.h"
|
||||||
|
|
||||||
|
class ModemUSB : public ModemAnalog {
|
||||||
|
public:
|
||||||
|
ModemUSB();
|
||||||
|
~ModemUSB();
|
||||||
|
Modem *factory();
|
||||||
|
void demodulate(ModemKit *kit, ModemIQData *input, AudioThreadInput *audioOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
resamp2_crcf ssbFilt;
|
||||||
|
ampmodem demodAM_USB;
|
||||||
|
};
|
1
src/modules/modem/digital/ModemAPSK.cpp
Normal file
1
src/modules/modem/digital/ModemAPSK.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemAPSK.h"
|
3
src/modules/modem/digital/ModemAPSK.h
Normal file
3
src/modules/modem/digital/ModemAPSK.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
1
src/modules/modem/digital/ModemASK.cpp
Normal file
1
src/modules/modem/digital/ModemASK.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemASK.h"
|
3
src/modules/modem/digital/ModemASK.h
Normal file
3
src/modules/modem/digital/ModemASK.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
1
src/modules/modem/digital/ModemBPSK.cpp
Normal file
1
src/modules/modem/digital/ModemBPSK.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemBPSK.h"
|
3
src/modules/modem/digital/ModemBPSK.h
Normal file
3
src/modules/modem/digital/ModemBPSK.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
1
src/modules/modem/digital/ModemDPSK.cpp
Normal file
1
src/modules/modem/digital/ModemDPSK.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemDPSK.h"
|
3
src/modules/modem/digital/ModemDPSK.h
Normal file
3
src/modules/modem/digital/ModemDPSK.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
1
src/modules/modem/digital/ModemOOK.cpp
Normal file
1
src/modules/modem/digital/ModemOOK.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemOOK.h"
|
3
src/modules/modem/digital/ModemOOK.h
Normal file
3
src/modules/modem/digital/ModemOOK.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
1
src/modules/modem/digital/ModemPSK.cpp
Normal file
1
src/modules/modem/digital/ModemPSK.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemPSK.h"
|
3
src/modules/modem/digital/ModemPSK.h
Normal file
3
src/modules/modem/digital/ModemPSK.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
1
src/modules/modem/digital/ModemQAM.cpp
Normal file
1
src/modules/modem/digital/ModemQAM.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemQAM.h"
|
3
src/modules/modem/digital/ModemQAM.h
Normal file
3
src/modules/modem/digital/ModemQAM.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
1
src/modules/modem/digital/ModemQPSK.cpp
Normal file
1
src/modules/modem/digital/ModemQPSK.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemQPSK.h"
|
3
src/modules/modem/digital/ModemQPSK.h
Normal file
3
src/modules/modem/digital/ModemQPSK.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
1
src/modules/modem/digital/ModemSQAM.cpp
Normal file
1
src/modules/modem/digital/ModemSQAM.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ModemSQAM.h"
|
3
src/modules/modem/digital/ModemSQAM.h
Normal file
3
src/modules/modem/digital/ModemSQAM.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
||||||
|
|
2
src/modules/modem/digital/ModemST.cpp
Normal file
2
src/modules/modem/digital/ModemST.cpp
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#include "ModemST.h"
|
||||||
|
|
2
src/modules/modem/digital/ModemST.h
Normal file
2
src/modules/modem/digital/ModemST.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Modem.h"
|
Loading…
x
Reference in New Issue
Block a user