diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d7fea..0178a2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,6 +234,25 @@ SET (cubicsdr_sources src/demod/DemodulatorWorkerThread.cpp src/demod/DemodulatorInstance.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/util/Gradient.cpp src/util/Timer.cpp @@ -293,6 +312,25 @@ SET (cubicsdr_headers src/demod/DemodulatorInstance.h src/demod/DemodulatorMgr.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/util/Gradient.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("SDR" REGULAR_EXPRESSION "src/sdr/${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("Utility" REGULAR_EXPRESSION "src/util/${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/sdr ${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/util ${PROJECT_SOURCE_DIR}/src/panel diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index a9a0d48..ce6e36b 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -93,21 +93,14 @@ public: } }; + class DemodulatorThreadPostIQData: public ReferenceCounter { public: std::vector data; long long sampleRate; - msresamp_rrrf audioResampler; - msresamp_rrrf stereoResampler; - double audioResampleRatio; - int audioSampleRate; - - firfilt_rrrf firStereoLeft; - firfilt_rrrf firStereoRight; - iirfilt_crcf iirStereoPilot; 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 { public: long long frequency; diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index f5d285a..0cd93aa 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -202,7 +202,7 @@ bool DemodulatorInstance::isStereo() { void DemodulatorInstance::setStereo(bool state) { stereo = state; - demodulatorThread->setStereo(state); +// demodulatorThread->setStereo(state); } void DemodulatorInstance::squelchAuto() { diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index f96dc2c..32d235b 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -27,45 +27,45 @@ void DemodulatorPreThread::initialize() { initialized = false; 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); - audioResampler = msresamp_rrrf_create(audioResampleRatio, As); - stereoResampler = msresamp_rrrf_create(audioResampleRatio, As); +// audioResampler = msresamp_rrrf_create(audioResampleRatio, As); +// stereoResampler = msresamp_rrrf_create(audioResampleRatio, As); // Stereo filters / shifters - double firStereoCutoff = ((double) 16000 / (double) params.audioSampleRate); - float ft = ((double) 1000 / (double) params.audioSampleRate); // filter transition - float mu = 0.0f; // fractional timing offset +// double firStereoCutoff = ((double) 16000 / (double) params.audioSampleRate); +// float ft = ((double) 1000 / (double) params.audioSampleRate); // filter transition +// float mu = 0.0f; // fractional timing offset +// +// if (firStereoCutoff < 0) { +// firStereoCutoff = 0; +// } +// +// if (firStereoCutoff > 0.5) { +// firStereoCutoff = 0.5; +// } - 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); - - firStereoLeft = firfilt_rrrf_create(h, h_len); - 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 - float bw = params.bandwidth; - 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; - As = 60.0f; - iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As); +// float bw = params.bandwidth; +// 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; +// As = 60.0f; +// iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As); initialized = true; lastParams = params; @@ -218,7 +218,6 @@ void DemodulatorPreThread::run() { msresamp_crcf_execute(iqResampler, in_buf, bufSize, &resampledData[0], &numWritten); resamp->setRefCount(1); - resamp->data.assign(resampledData.begin(), resampledData.begin() + numWritten); // bool uneven = (numWritten % 2 != 0); @@ -245,13 +244,13 @@ void DemodulatorPreThread::run() { - resamp->audioResampleRatio = audioResampleRatio; - resamp->audioResampler = audioResampler; - resamp->audioSampleRate = params.audioSampleRate; - resamp->stereoResampler = stereoResampler; - resamp->firStereoLeft = firStereoLeft; - resamp->firStereoRight = firStereoRight; - resamp->iirStereoPilot = iirStereoPilot; +// resamp->audioResampleRatio = audioResampleRatio; +// resamp->audioResampler = audioResampler; +// resamp->audioSampleRate = params.audioSampleRate; +// resamp->stereoResampler = stereoResampler; +// resamp->firStereoLeft = firStereoLeft; +// resamp->firStereoRight = firStereoRight; +// resamp->iirStereoPilot = iirStereoPilot; resamp->sampleRate = params.bandwidth; iqOutputQueue->push(resamp); diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index b46ff03..3f9d4a7 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -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) { - stereo.store(false); +// stereo.store(false); muted.store(false); agcEnabled.store(false); demodulatorType.store(DEMOD_TYPE_FM); - 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; +// 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; // advanced demodulators - demodulatorCons.store(2); +/* demodulatorCons.store(2); currentDemodCons = 0; demodASK = demodASK2; @@ -90,7 +90,7 @@ DemodulatorThread::DemodulatorThread() : IOThread(), iqAutoGain(NULL), amOutputC demodQPSK = modem_create(LIQUID_MODEM_QPSK); - currentDemodLock = false; + currentDemodLock = false; */ } DemodulatorThread::~DemodulatorThread() { @@ -110,23 +110,23 @@ void DemodulatorThread::run() { pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif - msresamp_rrrf audioResampler = NULL; - msresamp_rrrf stereoResampler = NULL; - firfilt_rrrf firStereoLeft = NULL; - firfilt_rrrf firStereoRight = NULL; - iirfilt_crcf iirStereoPilot = NULL; +// msresamp_rrrf audioResampler = NULL; +// msresamp_rrrf stereoResampler = NULL; +// firfilt_rrrf firStereoLeft = NULL; +// firfilt_rrrf firStereoRight = 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 firStereoC2R = firhilbf_create(5, 60.0f); +// firhilbf firStereoR2C = firhilbf_create(5, 60.0f); +// firhilbf firStereoC2R = firhilbf_create(5, 60.0f); - nco_crcf stereoPilot = nco_crcf_create(LIQUID_VCO); - nco_crcf_reset(stereoPilot); - nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f); +// nco_crcf stereoPilot = nco_crcf_create(LIQUID_VCO); +// nco_crcf_reset(stereoPilot); +// nco_crcf_pll_set_bandwidth(stereoPilot, 0.25f); // 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 iqAutoGain = agc_crcf_create(); @@ -141,22 +141,22 @@ void DemodulatorThread::run() { threadQueueControl = (DemodulatorThreadControlCommandQueue *)getInputQueue("ControlQueue"); threadQueueNotify = (DemodulatorThreadCommandQueue*)getOutputQueue("NotifyQueue"); - 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; - } +// 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; +// } while (!terminated) { DemodulatorThreadPostIQData *inp; @@ -170,47 +170,47 @@ void DemodulatorThread::run() { continue; } - 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; - } +// 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; +// } if (agcData.size() != bufSize) { if (agcData.capacity() < bufSize) { @@ -221,23 +221,24 @@ void DemodulatorThread::run() { agcAMData.resize(bufSize); } - double audio_resample_ratio = inp->audioResampleRatio; +// double audio_resample_ratio = inp->audioResampleRatio; - if (demodOutputData.size() != bufSize) { - if (demodOutputData.capacity() < bufSize) { - demodOutputData.reserve(bufSize); - } - demodOutputData.resize(bufSize); - } +// if (demodOutputData.size() != bufSize) { +// if (demodOutputData.capacity() < bufSize) { +// demodOutputData.reserve(bufSize); +// } +// demodOutputData.resize(bufSize); +// } +/* if (demodOutputDataDigital.size() != bufSize) { if (demodOutputDataDigital.capacity() < bufSize) { demodOutputDataDigital.reserve(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]); @@ -258,8 +259,8 @@ void DemodulatorThread::run() { } // Reset demodulator Constellations & Lock - updateDemodulatorCons(0); - +// updateDemodulatorCons(0); +/* if (demodulatorType == DEMOD_TYPE_FM) { currentDemodLock = false; 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); } - } + }*/ if (currentSignalLevel > signalLevel) { signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5; @@ -681,13 +682,14 @@ void DemodulatorThread::run() { if (audioOutputQueue != NULL) { if (!squelchEnabled || (signalLevel >= squelchLevel)) { - ati = outputBuffers.getBuffer(); ati->sampleRate = audioSampleRate; ati->inputRate = inp->sampleRate; ati->setRefCount(1); + /* + if (demodulatorType == DEMOD_TYPE_RAW) { ati->channels = 2; if (ati->data.capacity() < (numAudioWritten * 2)) { @@ -720,7 +722,7 @@ void DemodulatorThread::run() { ati->channels = 1; ati->data.assign(resampledOutputData.begin(), resampledOutputData.begin() + numAudioWritten); } - +*/ std::vector::iterator data_i; ati->peak = 0; 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()) { AudioThreadInput *ati_vis = audioVisBuffers.getBuffer(); ati_vis->setRefCount(1); @@ -762,6 +764,7 @@ void DemodulatorThread::run() { } } } else { + int numAudioWritten = ati->data.size(); ati_vis->channels = 1; if (numAudioWritten > bufSize) { ati_vis->inputRate = audioSampleRate; @@ -781,7 +784,8 @@ void DemodulatorThread::run() { audioVisOutputQueue->push(ati_vis); } - +*/ + if (ati != NULL) { if (!muted.load()) { audioOutputQueue->push(ati); @@ -791,7 +795,7 @@ void DemodulatorThread::run() { } if (!threadQueueControl->empty()) { - int newDemodType = DEMOD_TYPE_NULL; +// int newDemodType = DEMOD_TYPE_NULL; while (!threadQueueControl->empty()) { DemodulatorThreadControlCommand command; @@ -804,14 +808,14 @@ void DemodulatorThread::run() { case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF: squelchEnabled = false; break; - case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE: - newDemodType = command.demodType; - break; +// case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_TYPE: +// newDemodType = command.demodType; +// break; default: break; } } - +/* if (newDemodType != DEMOD_TYPE_NULL) { switch (newDemodType) { case DEMOD_TYPE_FM: @@ -868,15 +872,15 @@ void DemodulatorThread::run() { break; } demodulatorType = newDemodType; - } + }*/ } - demodOutputDataDigital.empty(); +// demodOutputDataDigital.empty(); inp->decRefCount(); } // end while !terminated - +/* if (audioResampler != NULL) { msresamp_rrrf_destroy(audioResampler); } @@ -898,7 +902,7 @@ void DemodulatorThread::run() { firhilbf_destroy(firStereoC2R); nco_crcf_destroy(stereoPilot); resamp2_crcf_destroy(ssbFilt); - +*/ outputBuffers.purge(); if (audioVisOutputQueue && !audioVisOutputQueue->empty()) { @@ -920,14 +924,14 @@ void DemodulatorThread::terminate() { iqInputQueue->push(inp); } -void DemodulatorThread::setStereo(bool state) { - stereo.store(state); - std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl; -} +//void DemodulatorThread::setStereo(bool state) { +// stereo.store(state); +// std::cout << "Stereo " << (state ? "Enabled" : "Disabled") << std::endl; +//} -bool DemodulatorThread::isStereo() { - return stereo.load(); -} +//bool DemodulatorThread::isStereo() { +// return stereo.load(); +//} bool DemodulatorThread::isMuted() { return muted.load(); diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 891849f..216996c 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -21,8 +21,8 @@ public: void run(); void terminate(); - void setStereo(bool state); - bool isStereo(); +// void setStereo(bool state); +// bool isStereo(); void setAGC(bool state); bool getAGC(); @@ -42,35 +42,35 @@ public: void setDemodulatorCons(int demod_cons_in); int getDemodulatorCons(); - -#ifdef __APPLE__ - static void *pthread_helper(void *context) { - return ((DemodulatorThread *) context)->threadMain(); - } -#endif +// +//#ifdef __APPLE__ +// static void *pthread_helper(void *context) { +// return ((DemodulatorThread *) context)->threadMain(); +// } +//#endif protected: ReBuffer outputBuffers; std::vector agcData; std::vector agcAMData; - std::vector demodOutputData; - std::vector demodStereoData; - std::vector resampledOutputData; - std::vector resampledStereoData; +// std::vector demodOutputData; +// std::vector demodStereoData; +// std::vector resampledOutputData; +// std::vector resampledStereoData; std::vector demodOutputDataDigital; //std::vector demodOutputDataDigitalTest; //std::vector demodOutputSoftbits; //std::vector demodOutputSoftbitsTest; - freqdem demodFM; - ampmodem demodAM; - ampmodem demodAM_DSB_CSP; - ampmodem demodAM_DSB; - ampmodem demodAM_LSB; - ampmodem demodAM_USB; - +// freqdem demodFM; +// ampmodem demodAM; +// ampmodem demodAM_DSB_CSP; +// ampmodem demodAM_DSB; +// ampmodem demodAM_LSB; +// ampmodem demodAM_USB; +/* modem demodASK; modem demodASK2; modem demodASK4; @@ -130,14 +130,14 @@ protected: modem demodQAM256; modem demodQPSK; - +*/ agc_crcf iqAutoGain; float amOutputCeil; float amOutputCeilMA; float amOutputCeilMAA; - std::atomic_bool stereo; +// std::atomic_bool stereo; std::atomic_bool muted; std::atomic_bool agcEnabled; std::atomic_int demodulatorType; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index c9c5761..e3dc0bf 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -47,12 +47,12 @@ void DemodulatorWorkerThread::run() { } if (filterCommand.bandwidth && filterCommand.audioSampleRate) { - result.audioResamplerRatio = (double) (filterCommand.audioSampleRate) / (double) filterCommand.bandwidth; - result.audioResampler = msresamp_rrrf_create(result.audioResamplerRatio, As); - result.stereoResampler = msresamp_rrrf_create(result.audioResamplerRatio, As); - result.audioSampleRate = filterCommand.audioSampleRate; +// result.audioResamplerRatio = (double) (filterCommand.audioSampleRate) / (double) filterCommand.bandwidth; +// result.audioResampler = msresamp_rrrf_create(result.audioResamplerRatio, As); +// result.stereoResampler = msresamp_rrrf_create(result.audioResamplerRatio, As); +// result.audioSampleRate = filterCommand.audioSampleRate; - // Stereo filters / shifters +/* // Stereo filters / shifters double firStereoCutoff = ((double) 16000 / (double) filterCommand.audioSampleRate); float ft = ((double) 1000 / (double) filterCommand.audioSampleRate); // filter transition float mu = 0.0f; // fractional timing offset @@ -83,7 +83,7 @@ void DemodulatorWorkerThread::run() { float Ap = 1.0f; As = 60.0f; - result.iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As); + result.iirStereoPilot = iirfilt_crcf_create_prototype(LIQUID_IIRDES_CHEBY2, LIQUID_IIRDES_BANDPASS, LIQUID_IIRDES_SOS, order, fc, f0, Ap, As); */ } if (filterCommand.bandwidth) { diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index 490ed5d..4a202c9 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -36,6 +36,8 @@ public: firfilt_rrrf firStereoLeft; firfilt_rrrf firStereoRight; iirfilt_crcf iirStereoPilot; + + DemodulatorThread *demodThread; long long sampleRate; unsigned int bandwidth; diff --git a/src/modules/modem/Modem.cpp b/src/modules/modem/Modem.cpp new file mode 100644 index 0000000..2502ef3 --- /dev/null +++ b/src/modules/modem/Modem.cpp @@ -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; +} diff --git a/src/modules/modem/Modem.h b/src/modules/modem/Modem.h new file mode 100644 index 0000000..66c4060 --- /dev/null +++ b/src/modules/modem/Modem.h @@ -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 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 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; +}; \ No newline at end of file diff --git a/src/modules/modem/ModemAnalog.cpp b/src/modules/modem/ModemAnalog.cpp new file mode 100644 index 0000000..183a700 --- /dev/null +++ b/src/modules/modem/ModemAnalog.cpp @@ -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); +} diff --git a/src/modules/modem/ModemAnalog.h b/src/modules/modem/ModemAnalog.h new file mode 100644 index 0000000..0a64151 --- /dev/null +++ b/src/modules/modem/ModemAnalog.h @@ -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 demodOutputData; + std::vector resampledOutputData; + + float aOutputCeil; + float aOutputCeilMA; + float aOutputCeilMAA; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemAM.cpp b/src/modules/modem/analog/ModemAM.cpp new file mode 100644 index 0000000..dbd6bc0 --- /dev/null +++ b/src/modules/modem/analog/ModemAM.cpp @@ -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); +} diff --git a/src/modules/modem/analog/ModemAM.h b/src/modules/modem/analog/ModemAM.h new file mode 100644 index 0000000..d7d115e --- /dev/null +++ b/src/modules/modem/analog/ModemAM.h @@ -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; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemDSB.cpp b/src/modules/modem/analog/ModemDSB.cpp new file mode 100644 index 0000000..62c5054 --- /dev/null +++ b/src/modules/modem/analog/ModemDSB.cpp @@ -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); +} diff --git a/src/modules/modem/analog/ModemDSB.h b/src/modules/modem/analog/ModemDSB.h new file mode 100644 index 0000000..1c94e7a --- /dev/null +++ b/src/modules/modem/analog/ModemDSB.h @@ -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; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemFM.cpp b/src/modules/modem/analog/ModemFM.cpp new file mode 100644 index 0000000..ee28692 --- /dev/null +++ b/src/modules/modem/analog/ModemFM.cpp @@ -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); +} diff --git a/src/modules/modem/analog/ModemFM.h b/src/modules/modem/analog/ModemFM.h new file mode 100644 index 0000000..c96bcdd --- /dev/null +++ b/src/modules/modem/analog/ModemFM.h @@ -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; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemFMStereo.cpp b/src/modules/modem/analog/ModemFMStereo.cpp new file mode 100644 index 0000000..f6f7c18 --- /dev/null +++ b/src/modules/modem/analog/ModemFMStereo.cpp @@ -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; + } +} diff --git a/src/modules/modem/analog/ModemFMStereo.h b/src/modules/modem/analog/ModemFMStereo.h new file mode 100644 index 0000000..b3f116e --- /dev/null +++ b/src/modules/modem/analog/ModemFMStereo.h @@ -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 demodOutputData; + std::vector demodStereoData; + std::vector resampledOutputData; + std::vector resampledStereoData; + freqdem demodFM; + + firhilbf firStereoR2C; + firhilbf firStereoC2R; + + nco_crcf stereoPilot; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemIQ.cpp b/src/modules/modem/analog/ModemIQ.cpp new file mode 100644 index 0000000..055c6e8 --- /dev/null +++ b/src/modules/modem/analog/ModemIQ.cpp @@ -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; + } +} diff --git a/src/modules/modem/analog/ModemIQ.h b/src/modules/modem/analog/ModemIQ.h new file mode 100644 index 0000000..7bda47e --- /dev/null +++ b/src/modules/modem/analog/ModemIQ.h @@ -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: + +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemLSB.cpp b/src/modules/modem/analog/ModemLSB.cpp new file mode 100644 index 0000000..74c3b3a --- /dev/null +++ b/src/modules/modem/analog/ModemLSB.cpp @@ -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); +} diff --git a/src/modules/modem/analog/ModemLSB.h b/src/modules/modem/analog/ModemLSB.h new file mode 100644 index 0000000..180928b --- /dev/null +++ b/src/modules/modem/analog/ModemLSB.h @@ -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; +}; \ No newline at end of file diff --git a/src/modules/modem/analog/ModemUSB.cpp b/src/modules/modem/analog/ModemUSB.cpp new file mode 100644 index 0000000..2827451 --- /dev/null +++ b/src/modules/modem/analog/ModemUSB.cpp @@ -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); +} + diff --git a/src/modules/modem/analog/ModemUSB.h b/src/modules/modem/analog/ModemUSB.h new file mode 100644 index 0000000..8267526 --- /dev/null +++ b/src/modules/modem/analog/ModemUSB.h @@ -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; +}; \ No newline at end of file diff --git a/src/modules/modem/digital/ModemAPSK.cpp b/src/modules/modem/digital/ModemAPSK.cpp new file mode 100644 index 0000000..b21c7fc --- /dev/null +++ b/src/modules/modem/digital/ModemAPSK.cpp @@ -0,0 +1 @@ +#include "ModemAPSK.h" \ No newline at end of file diff --git a/src/modules/modem/digital/ModemAPSK.h b/src/modules/modem/digital/ModemAPSK.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemAPSK.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemASK.cpp b/src/modules/modem/digital/ModemASK.cpp new file mode 100644 index 0000000..19ba6e9 --- /dev/null +++ b/src/modules/modem/digital/ModemASK.cpp @@ -0,0 +1 @@ +#include "ModemASK.h" diff --git a/src/modules/modem/digital/ModemASK.h b/src/modules/modem/digital/ModemASK.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemASK.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemBPSK.cpp b/src/modules/modem/digital/ModemBPSK.cpp new file mode 100644 index 0000000..4cb3576 --- /dev/null +++ b/src/modules/modem/digital/ModemBPSK.cpp @@ -0,0 +1 @@ +#include "ModemBPSK.h" diff --git a/src/modules/modem/digital/ModemBPSK.h b/src/modules/modem/digital/ModemBPSK.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemBPSK.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemDPSK.cpp b/src/modules/modem/digital/ModemDPSK.cpp new file mode 100644 index 0000000..04c269d --- /dev/null +++ b/src/modules/modem/digital/ModemDPSK.cpp @@ -0,0 +1 @@ +#include "ModemDPSK.h" diff --git a/src/modules/modem/digital/ModemDPSK.h b/src/modules/modem/digital/ModemDPSK.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemDPSK.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemOOK.cpp b/src/modules/modem/digital/ModemOOK.cpp new file mode 100644 index 0000000..50dd454 --- /dev/null +++ b/src/modules/modem/digital/ModemOOK.cpp @@ -0,0 +1 @@ +#include "ModemOOK.h" diff --git a/src/modules/modem/digital/ModemOOK.h b/src/modules/modem/digital/ModemOOK.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemOOK.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemPSK.cpp b/src/modules/modem/digital/ModemPSK.cpp new file mode 100644 index 0000000..3efece7 --- /dev/null +++ b/src/modules/modem/digital/ModemPSK.cpp @@ -0,0 +1 @@ +#include "ModemPSK.h" diff --git a/src/modules/modem/digital/ModemPSK.h b/src/modules/modem/digital/ModemPSK.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemPSK.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemQAM.cpp b/src/modules/modem/digital/ModemQAM.cpp new file mode 100644 index 0000000..8b4b6d2 --- /dev/null +++ b/src/modules/modem/digital/ModemQAM.cpp @@ -0,0 +1 @@ +#include "ModemQAM.h" diff --git a/src/modules/modem/digital/ModemQAM.h b/src/modules/modem/digital/ModemQAM.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemQAM.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemQPSK.cpp b/src/modules/modem/digital/ModemQPSK.cpp new file mode 100644 index 0000000..e2dea39 --- /dev/null +++ b/src/modules/modem/digital/ModemQPSK.cpp @@ -0,0 +1 @@ +#include "ModemQPSK.h" diff --git a/src/modules/modem/digital/ModemQPSK.h b/src/modules/modem/digital/ModemQPSK.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemQPSK.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemSQAM.cpp b/src/modules/modem/digital/ModemSQAM.cpp new file mode 100644 index 0000000..fed6b18 --- /dev/null +++ b/src/modules/modem/digital/ModemSQAM.cpp @@ -0,0 +1 @@ +#include "ModemSQAM.h" diff --git a/src/modules/modem/digital/ModemSQAM.h b/src/modules/modem/digital/ModemSQAM.h new file mode 100644 index 0000000..d8fc4cc --- /dev/null +++ b/src/modules/modem/digital/ModemSQAM.h @@ -0,0 +1,3 @@ +#pragma once +#include "Modem.h" + diff --git a/src/modules/modem/digital/ModemST.cpp b/src/modules/modem/digital/ModemST.cpp new file mode 100644 index 0000000..81cea23 --- /dev/null +++ b/src/modules/modem/digital/ModemST.cpp @@ -0,0 +1,2 @@ +#include "ModemST.h" + diff --git a/src/modules/modem/digital/ModemST.h b/src/modules/modem/digital/ModemST.h new file mode 100644 index 0000000..ae80ca2 --- /dev/null +++ b/src/modules/modem/digital/ModemST.h @@ -0,0 +1,2 @@ +#pragma once +#include "Modem.h" \ No newline at end of file