diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 2c80502..beb251f 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -96,12 +96,14 @@ void AppFrame::OnIdle(wxIdleEvent& event) { // std::this_thread::yield(); //#endif if (!wxGetApp().getIQVisualQueue()->empty()) { - SDRThreadIQData iqData; + DemodulatorThreadIQData *iqData; wxGetApp().getIQVisualQueue()->pop(iqData); - if (iqData.data.size()) { - spectrumCanvas->setData(&iqData.data); - waterfallCanvas->setData(&iqData.data); + if (iqData && iqData->data.size()) { + spectrumCanvas->setData(&iqData->data); + waterfallCanvas->setData(&iqData->data); + + delete iqData; } else { std::cout << "Incoming IQ data empty?" << std::endl; } @@ -109,19 +111,19 @@ void AppFrame::OnIdle(wxIdleEvent& event) { } if (!wxGetApp().getAudioVisualQueue()->empty()) { - AudioThreadInput demodAudioData; + AudioThreadInput *demodAudioData; wxGetApp().getAudioVisualQueue()->pop(demodAudioData); - if (demodAudioData.data.size()) { - - if (scopeCanvas->waveform_points.size() != demodAudioData.data.size()*2) { - scopeCanvas->waveform_points.resize(demodAudioData.data.size()*2); + if (demodAudioData && demodAudioData->data.size()) { + if (scopeCanvas->waveform_points.size() != demodAudioData->data.size()*2) { + scopeCanvas->waveform_points.resize(demodAudioData->data.size()*2); } - for (int i = 0, iMax = demodAudioData.data.size(); i < iMax; i++) { - scopeCanvas->waveform_points[i * 2 + 1] = demodAudioData.data[i] * 0.5f; + for (int i = 0, iMax = demodAudioData->data.size(); i < iMax; i++) { + scopeCanvas->waveform_points[i * 2 + 1] = demodAudioData->data[i] * 0.5f; scopeCanvas->waveform_points[i * 2] = ((double) i / (double) iMax); } + delete demodAudioData; } else { std::cout << "Incoming Demodulator data empty?" << std::endl; } diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index fc78863..f2e6e8a 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -30,7 +30,7 @@ bool CubicSDR::OnInit() { sdrPostThread = new SDRPostThread(); iqPostDataQueue = new SDRThreadIQDataQueue; - iqVisualQueue = new SDRThreadIQDataQueue; + iqVisualQueue = new DemodulatorThreadInputQueue; iqVisualQueue->set_max_num_items(1); sdrThread->setIQDataOutQueue(iqPostDataQueue); @@ -115,7 +115,7 @@ DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() { return audioVisualQueue; } -SDRThreadIQDataQueue* CubicSDR::getIQVisualQueue() { +DemodulatorThreadInputQueue* CubicSDR::getIQVisualQueue() { return iqVisualQueue; } diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 5128368..b84e23e 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -20,8 +20,7 @@ class CubicSDR: public wxApp { public: CubicSDR() : - m_glContext(NULL), t_PostSDR(NULL), t_SDR(NULL), audioVisualQueue(NULL), threadCmdQueueSDR(NULL), iqVisualQueue(NULL), frequency( - DEFAULT_FREQ), sdrPostThread(NULL), iqPostDataQueue(NULL), sdrThread(NULL) { + m_glContext(NULL), frequency(DEFAULT_FREQ), sdrThread(NULL), sdrPostThread(NULL), threadCmdQueueSDR(NULL), iqVisualQueue(NULL), iqPostDataQueue(NULL), audioVisualQueue(NULL), t_SDR(NULL), t_PostSDR(NULL) { } @@ -34,7 +33,7 @@ public: int getFrequency(); DemodulatorThreadOutputQueue* getAudioVisualQueue(); - SDRThreadIQDataQueue* getIQVisualQueue(); + DemodulatorThreadInputQueue* getIQVisualQueue(); DemodulatorMgr &getDemodMgr(); void bindDemodulator(DemodulatorInstance *demod); @@ -51,8 +50,8 @@ private: SDRPostThread *sdrPostThread; SDRThreadCommandQueue* threadCmdQueueSDR; - SDRThreadIQDataQueue* iqVisualQueue; SDRThreadIQDataQueue* iqPostDataQueue; + DemodulatorThreadInputQueue* iqVisualQueue; DemodulatorThreadOutputQueue* audioVisualQueue; std::thread *t_SDR; diff --git a/src/CubicSDRDefs.h b/src/CubicSDRDefs.h index d54cf73..7a8bb8e 100644 --- a/src/CubicSDRDefs.h +++ b/src/CubicSDRDefs.h @@ -11,3 +11,25 @@ #define DEFAULT_FREQ 98900000 #define AUDIO_FREQUENCY 44100 + +#include +#include + +class ReferenceCounter { +public: + mutable std::mutex m_mutex; + + void setRefCount(int rc) { + refCount.store(rc); + } + + void decRefCount() { + refCount.store(refCount.load()-1); + } + + int getRefCount() { + return refCount.load(); + } +protected: + std::atomic refCount; +}; diff --git a/src/audio/AudioThread.cpp b/src/audio/AudioThread.cpp index b429ec3..de94c66 100644 --- a/src/audio/AudioThread.cpp +++ b/src/audio/AudioThread.cpp @@ -10,8 +10,8 @@ std::map AudioThread::deviceThread; #endif AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) : - inputQueue(inputQueue), terminated(false), audio_queue_ptr(0), underflow_count(0), threadQueueNotify(threadQueueNotify), gain(1.0), active( - false) { + currentInput(NULL), inputQueue(inputQueue), audio_queue_ptr(0), underflow_count(0), terminated(false), active(false), gain(1.0), threadQueueNotify( + threadQueueNotify) { #ifdef __APPLE__ boundThreads = new std::vector; #endif @@ -65,31 +65,68 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu continue; } - if (srcmix->currentInput.channels == 0) { + if (!srcmix->currentInput) { + if (srcmix->terminated) { + continue; + } + srcmix->inputQueue->pop(srcmix->currentInput); + srcmix->audio_queue_ptr = 0; + continue; + } + + std::lock_guard < std::mutex > lock(srcmix->currentInput->m_mutex); + + if (srcmix->currentInput->channels == 0 || !srcmix->currentInput->data.size()) { if (!srcmix->inputQueue->empty()) { + if (srcmix->currentInput) { + srcmix->currentInput->decRefCount(); + srcmix->currentInput = NULL; + } + if (srcmix->terminated) { + continue; + } srcmix->inputQueue->pop(srcmix->currentInput); + srcmix->audio_queue_ptr = 0; } continue; } - if (srcmix->currentInput.channels == 1) { + if (srcmix->currentInput->channels == 1) { for (int i = 0; i < nBufferFrames; i++) { - if (srcmix->audio_queue_ptr >= srcmix->currentInput.data.size()) { + if (srcmix->audio_queue_ptr >= srcmix->currentInput->data.size()) { + if (srcmix->currentInput) { + srcmix->currentInput->decRefCount(); + srcmix->currentInput = NULL; + } + if (srcmix->terminated) { + continue; + } srcmix->inputQueue->pop(srcmix->currentInput); srcmix->audio_queue_ptr = 0; } - float v = srcmix->currentInput.data[srcmix->audio_queue_ptr] * src->gain; - out[i * 2] += v; - out[i * 2 + 1] += v; + if (srcmix->currentInput && srcmix->currentInput->data.size()) { + float v = srcmix->currentInput->data[srcmix->audio_queue_ptr] * src->gain; + out[i * 2] += v; + out[i * 2 + 1] += v; + } srcmix->audio_queue_ptr++; } } else { - for (int i = 0, iMax = src->currentInput.channels * nBufferFrames; i < iMax; i++) { - if (srcmix->audio_queue_ptr >= srcmix->currentInput.data.size()) { + for (int i = 0, iMax = src->currentInput->channels * nBufferFrames; i < iMax; i++) { + if (srcmix->audio_queue_ptr >= srcmix->currentInput->data.size()) { + if (srcmix->currentInput) { + srcmix->currentInput->decRefCount(); + srcmix->currentInput = NULL; + } + if (srcmix->terminated) { + continue; + } srcmix->inputQueue->pop(srcmix->currentInput); srcmix->audio_queue_ptr = 0; } - out[i] = out[i] + srcmix->currentInput.data[srcmix->audio_queue_ptr] * src->gain; + if (srcmix->currentInput && srcmix->currentInput->data.size()) { + out[i] = out[i] + srcmix->currentInput->data[srcmix->audio_queue_ptr] * src->gain; + } srcmix->audio_queue_ptr++; } } @@ -110,35 +147,59 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu std::cout << "Audio buffer underflow.." << (src->underflow_count++) << std::endl; } - if (src->currentInput.channels == 0) { + if (!src->currentInput) { + src->inputQueue->pop(src->currentInput); + src->audio_queue_ptr = 0; + return 0; + } + + std::lock_guard < std::mutex > lock(src->currentInput->m_mutex); + + if (src->currentInput->channels == 0 || !src->currentInput->data.size()) { if (!src->inputQueue->empty()) { + if (src->currentInput) { + src->currentInput->decRefCount(); + src->currentInput = NULL; + } + if (src->terminated) { + return 1; + } src->inputQueue->pop(src->currentInput); + src->audio_queue_ptr = 0; } return 0; } - if (src->currentInput.channels == 1) { + if (src->currentInput->channels == 1) { for (int i = 0; i < nBufferFrames; i++) { - if (src->audio_queue_ptr >= src->currentInput.data.size()) { + if (src->audio_queue_ptr >= src->currentInput->data.size()) { + if (src->currentInput) { + src->currentInput->decRefCount(); + src->currentInput = NULL; + } if (src->terminated) { - break; + return 1; } src->inputQueue->pop(src->currentInput); src->audio_queue_ptr = 0; } - out[i * 2] = out[i * 2 + 1] = src->currentInput.data[src->audio_queue_ptr] * src->gain; + if (src->currentInput && src->currentInput->data.size()) { + out[i * 2] = out[i * 2 + 1] = src->currentInput->data[src->audio_queue_ptr] * src->gain; + } src->audio_queue_ptr++; } } else { - for (int i = 0, iMax = src->currentInput.channels * nBufferFrames; i < iMax; i++) { - if (src->audio_queue_ptr >= src->currentInput.data.size()) { + for (int i = 0, iMax = src->currentInput->channels * nBufferFrames; i < iMax; i++) { + if (src->audio_queue_ptr >= src->currentInput->data.size()) { if (src->terminated) { - break; + return 1; } src->inputQueue->pop(src->currentInput); src->audio_queue_ptr = 0; } - out[i] = src->currentInput.data[src->audio_queue_ptr] * src->gain; + if (src->currentInput && src->currentInput->data.size()) { + out[i] = src->currentInput->data[src->audio_queue_ptr] * src->gain; + } src->audio_queue_ptr++; } } @@ -297,16 +358,22 @@ bool AudioThread::isActive() { void AudioThread::setActive(bool state) { #ifdef __APPLE__ - AudioThreadInput dummy; + AudioThreadInput *dummy; if (state && !active) { - deviceController[parameters.deviceId]->bindThread(this); while (!inputQueue->empty()) { // flush queue inputQueue->pop(dummy); + if (dummy) { + delete dummy; + } } + deviceController[parameters.deviceId]->bindThread(this); } else if (!state && active) { deviceController[parameters.deviceId]->removeThread(this); while (!inputQueue->empty()) { // flush queue inputQueue->pop(dummy); + if (dummy) { + delete dummy; + } } } #endif diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index 9ea135a..da411b3 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -18,21 +18,21 @@ #include "RtAudio.h" #include "DemodDefs.h" -class AudioThreadInput { +class AudioThreadInput: public ReferenceCounter { public: int frequency; int sampleRate; int channels; + std::vector data; - AudioThreadInput(): frequency(0), sampleRate(0), channels(0) { + AudioThreadInput() : + frequency(0), sampleRate(0), channels(0) { } ~AudioThreadInput() { } - - std::vector data; }; class AudioThreadCommand { @@ -49,13 +49,13 @@ public: int int_value; }; -typedef ThreadQueue AudioThreadInputQueue; +typedef ThreadQueue AudioThreadInputQueue; typedef ThreadQueue AudioThreadCommandQueue; class AudioThread { public: - AudioThreadInput currentInput; + AudioThreadInput *currentInput; AudioThreadInputQueue *inputQueue; std::atomic audio_queue_ptr; std::atomic underflow_count; diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index e5822c1..c8ddf22 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -4,11 +4,11 @@ #include "CubicSDRDefs.h" #include "liquid/liquid.h" +#include +#include + enum DemodulatorType { - DEMOD_TYPE_NULL, - DEMOD_TYPE_AM, - DEMOD_TYPE_FM, - DEMOD_TYPE_LSB, DEMOD_TYPE_USB + DEMOD_TYPE_NULL, DEMOD_TYPE_AM, DEMOD_TYPE_FM, DEMOD_TYPE_LSB, DEMOD_TYPE_USB }; class DemodulatorThread; @@ -24,26 +24,24 @@ public: }; DemodulatorThreadCommand() : - cmd(DEMOD_THREAD_CMD_NULL), int_value(0), context(NULL) { + cmd(DEMOD_THREAD_CMD_NULL), context(NULL), int_value(0) { } DemodulatorThreadCommand(DemodulatorThreadCommandEnum cmd) : - cmd(cmd), int_value(0), context(NULL) { + cmd(cmd), context(NULL), int_value(0) { - } + } - DemodulatorThreadCommandEnum cmd; - void *context; - int int_value; + DemodulatorThreadCommandEnum cmd; + void *context; + int int_value; }; class DemodulatorThreadControlCommand { public: enum DemodulatorThreadControlCommandEnum { - DEMOD_THREAD_CMD_CTL_NULL, - DEMOD_THREAD_CMD_CTL_SQUELCH_AUTO, - DEMOD_THREAD_CMD_CTL_SQUELCH_OFF + DEMOD_THREAD_CMD_CTL_NULL, DEMOD_THREAD_CMD_CTL_SQUELCH_AUTO, DEMOD_THREAD_CMD_CTL_SQUELCH_OFF }; DemodulatorThreadControlCommand() : @@ -53,77 +51,68 @@ public: DemodulatorThreadControlCommandEnum cmd; }; -class DemodulatorThreadIQData { +class DemodulatorThreadIQData: public ReferenceCounter { public: - unsigned int frequency; - unsigned int bandwidth; - std::vector data; + unsigned int frequency; + unsigned int bandwidth; + std::vector data; - DemodulatorThreadIQData() : - frequency(0), bandwidth(0) { + DemodulatorThreadIQData() : + frequency(0), bandwidth(0) { - } + } - DemodulatorThreadIQData(unsigned int bandwidth, unsigned int frequency, - std::vector data) : - data(data), frequency(frequency), bandwidth(bandwidth) { + ~DemodulatorThreadIQData() { - } - - ~DemodulatorThreadIQData() { - - } + } }; -class DemodulatorThreadPostIQData { +class DemodulatorThreadPostIQData: public ReferenceCounter { public: - std::vector data; - float audio_resample_ratio; - msresamp_rrrf audio_resampler; + std::vector data; + float audio_resample_ratio; + msresamp_rrrf audio_resampler; float resample_ratio; msresamp_crcf resampler; - DemodulatorThreadPostIQData(): audio_resample_ratio(0), audio_resampler(NULL), resample_ratio(0), resampler(NULL) { + DemodulatorThreadPostIQData() : + audio_resample_ratio(0), audio_resampler(NULL), resample_ratio(0), resampler(NULL) { - } + } - ~DemodulatorThreadPostIQData() { + ~DemodulatorThreadPostIQData() { - } + } }; - -class DemodulatorThreadAudioData { +class DemodulatorThreadAudioData: public ReferenceCounter { public: - unsigned int frequency; - unsigned int sampleRate; - unsigned char channels; + unsigned int frequency; + unsigned int sampleRate; + unsigned char channels; - std::vector data; + std::vector *data; - DemodulatorThreadAudioData() : - sampleRate(0), frequency(0), channels(0) { + DemodulatorThreadAudioData() : + frequency(0), sampleRate(0), channels(0), data(NULL) { - } + } - DemodulatorThreadAudioData(unsigned int frequency, unsigned int sampleRate, - std::vector data) : - data(data), sampleRate(sampleRate), frequency(frequency), channels( - 1) { + DemodulatorThreadAudioData(unsigned int frequency, unsigned int sampleRate, std::vector *data) : + frequency(frequency), sampleRate(sampleRate), channels(1), data(data) { - } + } - ~DemodulatorThreadAudioData() { + ~DemodulatorThreadAudioData() { - } + } }; -typedef ThreadQueue DemodulatorThreadInputQueue; -typedef ThreadQueue DemodulatorThreadPostInputQueue; +typedef ThreadQueue DemodulatorThreadInputQueue; +typedef ThreadQueue DemodulatorThreadPostInputQueue; typedef ThreadQueue DemodulatorThreadCommandQueue; typedef ThreadQueue DemodulatorThreadControlCommandQueue; - class DemodulatorThreadParameters { public: unsigned int frequency; @@ -135,7 +124,7 @@ public: DemodulatorThreadParameters() : frequency(0), inputRate(SRATE), bandwidth(200000), audioSampleRate( - AUDIO_FREQUENCY), demodType(DEMOD_TYPE_FM) { + AUDIO_FREQUENCY), demodType(DEMOD_TYPE_FM) { } diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index 9d46565..ab26849 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -77,12 +77,12 @@ DemodulatorThreadParameters &DemodulatorInstance::getParams() { } void DemodulatorInstance::terminate() { - std::cout << "Terminating demodulator preprocessor thread.." << std::endl; - demodulatorPreThread->terminate(); - std::cout << "Terminating demodulator thread.." << std::endl; - demodulatorThread->terminate(); std::cout << "Terminating demodulator audio thread.." << std::endl; audioThread->terminate(); + std::cout << "Terminating demodulator thread.." << std::endl; + demodulatorThread->terminate(); + std::cout << "Terminating demodulator preprocessor thread.." << std::endl; + demodulatorPreThread->terminate(); } std::string DemodulatorInstance::getLabel() { @@ -146,7 +146,6 @@ void DemodulatorInstance::setActive(bool state) { audioThread->setActive(state); } - void DemodulatorInstance::squelchAuto() { DemodulatorThreadControlCommand command; command.cmd = DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_AUTO; diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index ccd14be..2853d6c 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -49,16 +49,11 @@ public: bool isActive(); void setActive(bool state); - void squelchAuto(); - bool isSquelchEnabled(); + void squelchAuto();bool isSquelchEnabled(); void setSquelchEnabled(bool state); private: - std::atomic label; - bool terminated; - bool demodTerminated; - bool audioTerminated; - bool preDemodTerminated; + std::atomic label;bool terminated;bool demodTerminated;bool audioTerminated;bool preDemodTerminated; std::atomic active; std::atomic squelch; }; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 19775ec..065141f 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -10,7 +10,8 @@ DemodulatorPreThread::DemodulatorPreThread(DemodulatorThreadInputQueue* pQueueIn, DemodulatorThreadPostInputQueue* pQueueOut, DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify) : inputQueue(pQueueIn), postInputQueue(pQueueOut), terminated(false), initialized(false), audio_resampler(NULL), resample_ratio(1), audio_resample_ratio( - 1), resampler(NULL), commandQueue(NULL), fir_filter(NULL), audioInputQueue(NULL), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl) { + 1), resampler(NULL), commandQueue(NULL), fir_filter(NULL), audioInputQueue(NULL), threadQueueNotify(threadQueueNotify), threadQueueControl( + threadQueueControl) { float kf = 0.5; // modulation factor fdem = freqdem_create(kf); @@ -90,7 +91,7 @@ void DemodulatorPreThread::threadMain() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO )-1; - sched_param prio = { priority }; // scheduling priority of thread + sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif @@ -99,8 +100,15 @@ void DemodulatorPreThread::threadMain() { } std::cout << "Demodulator preprocessor thread started.." << std::endl; + + std::deque buffers; + std::deque::iterator buffers_i; + + std::vector in_buf_data; + std::vector out_buf_data; + while (!terminated) { - DemodulatorThreadIQData inp; + DemodulatorThreadIQData *inp; inputQueue->pop(inp); bool bandwidthChanged = false; @@ -144,9 +152,9 @@ void DemodulatorPreThread::threadMain() { } // Requested frequency is not center, shift it into the center! - if (inp.frequency != params.frequency) { - if ((params.frequency - inp.frequency) != shift_freq) { - shift_freq = params.frequency - inp.frequency; + if (inp->frequency != params.frequency) { + if ((params.frequency - inp->frequency) != shift_freq) { + shift_freq = params.frequency - inp->frequency; if (abs(shift_freq) <= (int) ((float) (SRATE / 2) * 1.5)) { nco_crcf_set_frequency(nco_shift, (2.0 * M_PI) * (((float) abs(shift_freq)) / ((float) SRATE))); } @@ -157,22 +165,26 @@ void DemodulatorPreThread::threadMain() { continue; } - std::vector *data = &inp.data; +// std::lock_guard < std::mutex > lock(inp->m_mutex); + std::vector *data = &inp->data; if (data->size()) { - int bufSize = data->size() / 2; + int bufSize = data->size(); - liquid_float_complex in_buf_data[bufSize]; - liquid_float_complex out_buf_data[bufSize]; - - liquid_float_complex *in_buf = in_buf_data; - liquid_float_complex *out_buf = out_buf_data; - liquid_float_complex *temp_buf = NULL; - - for (int i = 0; i < bufSize; i++) { - in_buf[i].real = (float) (*data)[i * 2] / 127.0f; - in_buf[i].imag = (float) (*data)[i * 2 + 1] / 127.0f; + if (in_buf_data.size() != bufSize) { + if (in_buf_data.capacity() < bufSize) { + in_buf_data.reserve(bufSize); + out_buf_data.reserve(bufSize); + } + in_buf_data.resize(bufSize); + out_buf_data.resize(bufSize); } + in_buf_data.assign(inp->data.begin(),inp->data.end()); + + liquid_float_complex *in_buf = &in_buf_data[0]; + liquid_float_complex *out_buf = &out_buf_data[0]; + liquid_float_complex *temp_buf = NULL; + if (shift_freq != 0) { if (shift_freq < 0) { nco_crcf_mix_block_up(nco_shift, in_buf, out_buf, bufSize); @@ -184,19 +196,35 @@ void DemodulatorPreThread::threadMain() { out_buf = temp_buf; } - DemodulatorThreadPostIQData resamp; - resamp.data.resize(bufSize); + DemodulatorThreadPostIQData *resamp = NULL; - firfilt_crcf_execute_block(fir_filter, in_buf, bufSize, &resamp.data[0]); + for (buffers_i = buffers.begin(); buffers_i != buffers.end(); buffers_i++) { + if ((*buffers_i)->getRefCount() <= 0) { + resamp = (*buffers_i); + break; + } + } - resamp.audio_resample_ratio = audio_resample_ratio; - resamp.audio_resampler = audio_resampler; - resamp.resample_ratio = resample_ratio; - resamp.resampler = resampler; + if (resamp == NULL) { + resamp = new DemodulatorThreadPostIQData; + buffers.push_back(resamp); + } + + resamp->setRefCount(1); + resamp->data.assign(in_buf, in_buf + bufSize); + +// firfilt_crcf_execute_block(fir_filter, in_buf, bufSize, &((*resamp.data)[0])); + + resamp->audio_resample_ratio = audio_resample_ratio; + resamp->audio_resampler = audio_resampler; + resamp->resample_ratio = resample_ratio; + resamp->resampler = resampler; postInputQueue->push(resamp); } + inp->decRefCount(); + if (!workerResults->empty()) { while (!workerResults->empty()) { DemodulatorWorkerThreadResult result; @@ -225,6 +253,13 @@ void DemodulatorPreThread::threadMain() { } } + while (!buffers.empty()) { + DemodulatorThreadPostIQData *iqDataDel = buffers.front(); + buffers.pop_front(); + std::lock_guard < std::mutex > lock(iqDataDel->m_mutex); + delete iqDataDel; + } + std::cout << "Demodulator preprocessor thread done." << std::endl; DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED); tCmd.context = this; @@ -233,7 +268,7 @@ void DemodulatorPreThread::threadMain() { void DemodulatorPreThread::terminate() { terminated = true; - DemodulatorThreadIQData inp; // push dummy to nudge queue + DemodulatorThreadIQData *inp = new DemodulatorThreadIQData; // push dummy to nudge queue inputQueue->push(inp); workerThread->terminate(); } diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index 0295984..95304da 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -32,7 +32,6 @@ public: threadQueueControl = tQueue; } - DemodulatorThreadParameters &getParams() { return params; } diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index f9befc5..8b4f7ea 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -6,8 +6,10 @@ #include #endif -DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* pQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify) : - postInputQueue(pQueue), visOutQueue(NULL), terminated(false), audioInputQueue(NULL), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl), agc(NULL), squelch_enabled(false), squelch_level(0), squelch_tolerance(0) { +DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* pQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, + DemodulatorThreadCommandQueue* threadQueueNotify) : + postInputQueue(pQueue), visOutQueue(NULL), audioInputQueue(NULL), agc(NULL), terminated(false), threadQueueNotify(threadQueueNotify), threadQueueControl( + threadQueueControl), squelch_level(0), squelch_tolerance(0), squelch_enabled(false) { float kf = 0.5; // modulation factor fdem = freqdem_create(kf); @@ -35,71 +37,115 @@ void DemodulatorThread::threadMain() { agc_crcf_set_bandwidth(agc, 1e-3f); std::cout << "Demodulator thread started.." << std::endl; - while (!terminated) { - DemodulatorThreadPostIQData inp; - postInputQueue->pop(inp); - int bufSize = inp.data.size(); + std::deque buffers; + std::deque::iterator buffers_i; + + std::vector resampled_data; + std::vector agc_data; + std::vector demod_output; + std::vector resampled_audio_output; + + while (!terminated) { + DemodulatorThreadPostIQData *inp; + postInputQueue->pop(inp); + std::lock_guard < std::mutex > lock(inp->m_mutex); + + int bufSize = inp->data.size(); if (!bufSize) { + inp->decRefCount(); continue; } if (resampler == NULL) { - resampler = inp.resampler; - audio_resampler = inp.audio_resampler; - } else if (resampler != inp.resampler) { + resampler = inp->resampler; + audio_resampler = inp->audio_resampler; + } else if (resampler != inp->resampler) { msresamp_crcf_destroy(resampler); msresamp_rrrf_destroy(audio_resampler); - resampler = inp.resampler; - audio_resampler = inp.audio_resampler; + resampler = inp->resampler; + audio_resampler = inp->audio_resampler; } - int out_size = ceil((float) (bufSize) * inp.resample_ratio); - liquid_float_complex resampled_data[out_size]; - liquid_float_complex agc_data[out_size]; + int out_size = ceil((float) (bufSize) * inp->resample_ratio); + + if (agc_data.size() != out_size) { + if (agc_data.capacity() < out_size) { + agc_data.reserve(out_size); + resampled_data.reserve(out_size); + } + agc_data.resize(out_size); + resampled_data.resize(out_size); + } unsigned int num_written; - msresamp_crcf_execute(resampler, &inp.data[0], bufSize, resampled_data, &num_written); + msresamp_crcf_execute(resampler, &(inp->data[0]), bufSize, &resampled_data[0], &num_written); - agc_crcf_execute_block(agc, resampled_data, num_written, agc_data); + agc_crcf_execute_block(agc, &resampled_data[0], num_written, &agc_data[0]); - float audio_resample_ratio = inp.audio_resample_ratio; - float demod_output[num_written]; + float audio_resample_ratio = inp->audio_resample_ratio; - freqdem_demodulate_block(fdem, agc_data, num_written, demod_output); + if (demod_output.size() != num_written) { + if (demod_output.capacity() < num_written) { + demod_output.reserve(num_written); + } + demod_output.resize(num_written); + } + + freqdem_demodulate_block(fdem, &agc_data[0], num_written, &demod_output[0]); int audio_out_size = ceil((float) (num_written) * audio_resample_ratio); - float resampled_audio_output[audio_out_size]; + + if (audio_out_size != resampled_audio_output.size()) { + if (resampled_audio_output.capacity() < audio_out_size) { + resampled_audio_output.reserve(audio_out_size); + } + resampled_audio_output.resize(audio_out_size); + } unsigned int num_audio_written; - msresamp_rrrf_execute(audio_resampler, demod_output, num_written, resampled_audio_output, &num_audio_written); - - AudioThreadInput ati; - ati.channels = 1; - ati.data.assign(resampled_audio_output,resampled_audio_output+num_audio_written); + msresamp_rrrf_execute(audio_resampler, &demod_output[0], num_written, &resampled_audio_output[0], &num_audio_written); if (audioInputQueue != NULL) { if (!squelch_enabled || ((agc_crcf_get_signal_level(agc)) >= 0.1)) { + AudioThreadInput *ati = NULL; + + for (buffers_i = buffers.begin(); buffers_i != buffers.end(); buffers_i++) { + if ((*buffers_i)->getRefCount() <= 0) { + ati = (*buffers_i); + break; + } + } + + if (ati == NULL) { + ati = new AudioThreadInput; + buffers.push_back(ati); + } + + ati->setRefCount(1); + ati->channels = 1; + ati->data.assign(resampled_audio_output.begin(), resampled_audio_output.begin() + num_audio_written); + audioInputQueue->push(ati); } } if (visOutQueue != NULL && visOutQueue->empty()) { - AudioThreadInput ati_vis; - ati_vis.channels = ati.channels; + AudioThreadInput *ati_vis = new AudioThreadInput; + ati_vis->channels = 1; int num_vis = DEMOD_VIS_SIZE; if (num_audio_written > num_written) { if (num_vis > num_audio_written) { num_vis = num_audio_written; } - ati_vis.data.assign(ati.data.begin(), ati.data.begin()+num_vis); + ati_vis->data.assign(resampled_audio_output.begin(), resampled_audio_output.begin() + num_vis); } else { if (num_vis > num_written) { num_vis = num_written; } - ati_vis.data.assign(demod_output, demod_output + num_vis); + ati_vis->data.assign(demod_output.begin(), demod_output.begin() + num_vis); } visOutQueue->push(ati_vis); @@ -114,7 +160,7 @@ void DemodulatorThread::threadMain() { switch (command.cmd) { case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_AUTO: squelch_level = agc_crcf_get_signal_level(agc); - squelch_tolerance = agc_crcf_get_signal_level(agc)/2.0; + squelch_tolerance = agc_crcf_get_signal_level(agc) / 2.0; squelch_enabled = true; break; case DemodulatorThreadControlCommand::DEMOD_THREAD_CMD_CTL_SQUELCH_OFF: @@ -128,6 +174,7 @@ void DemodulatorThread::threadMain() { } } + inp->decRefCount(); } if (resampler != NULL) { @@ -139,6 +186,13 @@ void DemodulatorThread::threadMain() { agc_crcf_destroy(agc); + while (!buffers.empty()) { + AudioThreadInput *audioDataDel = buffers.front(); + buffers.pop_front(); + std::lock_guard < std::mutex > lock(audioDataDel->m_mutex); + delete audioDataDel; + } + std::cout << "Demodulator thread done." << std::endl; DemodulatorThreadCommand tCmd(DemodulatorThreadCommand::DEMOD_THREAD_CMD_DEMOD_TERMINATED); tCmd.context = this; @@ -147,6 +201,6 @@ void DemodulatorThread::threadMain() { void DemodulatorThread::terminate() { terminated = true; - DemodulatorThreadPostIQData inp; // push dummy to nudge queue + DemodulatorThreadPostIQData *inp = new DemodulatorThreadPostIQData; // push dummy to nudge queue postInputQueue->push(inp); } diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 5327620..3fb4bf6 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -6,14 +6,15 @@ #include "DemodDefs.h" #include "AudioThread.h" -typedef ThreadQueue DemodulatorThreadOutputQueue; +typedef ThreadQueue DemodulatorThreadOutputQueue; #define DEMOD_VIS_SIZE 2048 class DemodulatorThread { public: - DemodulatorThread(DemodulatorThreadPostInputQueue* pQueueIn, DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify); + DemodulatorThread(DemodulatorThreadPostInputQueue* pQueueIn, DemodulatorThreadControlCommandQueue *threadQueueControl, + DemodulatorThreadCommandQueue* threadQueueNotify); ~DemodulatorThread(); #ifdef __APPLE__ @@ -53,6 +54,5 @@ protected: DemodulatorThreadCommandQueue* threadQueueNotify; DemodulatorThreadControlCommandQueue *threadQueueControl; float squelch_level; - float squelch_tolerance; - bool squelch_enabled; + float squelch_tolerance;bool squelch_enabled; }; diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index 950b5f1..8db4c5a 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -22,17 +22,19 @@ public: }; DemodulatorWorkerThreadResult() : - cmd(DEMOD_WORKER_THREAD_RESULT_NULL), audioSampleRate(0), bandwidth(0), inputRate(0), fir_filter(NULL), resampler(NULL), resample_ratio( - 0), audio_resampler(NULL), audio_resample_ratio(0) { + cmd(DEMOD_WORKER_THREAD_RESULT_NULL), fir_filter(NULL), resampler(NULL), resample_ratio(0), audio_resampler(NULL), audio_resample_ratio( + 0), inputRate(0), bandwidth(0), audioSampleRate(0) { } DemodulatorWorkerThreadResult(DemodulatorThreadResultEnum cmd) : - cmd(cmd), audioSampleRate(0), bandwidth(0), inputRate(0), fir_filter(NULL), resampler(NULL), resample_ratio(0), audio_resampler(NULL), audio_resample_ratio( - 0) { + cmd(cmd), fir_filter(NULL), resampler(NULL), resample_ratio(0), audio_resampler(NULL), audio_resample_ratio(0), inputRate(0), bandwidth( + 0), audioSampleRate(0) { } + DemodulatorThreadResultEnum cmd; + firfilt_crcf fir_filter; msresamp_crcf resampler; float resample_ratio; @@ -43,7 +45,6 @@ public: unsigned int bandwidth; unsigned int audioSampleRate; - DemodulatorThreadResultEnum cmd; }; class DemodulatorWorkerThreadCommand { @@ -62,12 +63,12 @@ public: } + DemodulatorThreadCommandEnum cmd; + unsigned int frequency; unsigned int inputRate; unsigned int bandwidth; unsigned int audioSampleRate; - - DemodulatorThreadCommandEnum cmd; }; typedef ThreadQueue DemodulatorThreadWorkerCommandQueue; diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index 5487c68..bb93b6d 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -1,17 +1,19 @@ #include "SDRPostThread.h" #include "CubicSDRDefs.h" -#include #include "CubicSDR.h" +#include +#include + SDRPostThread::SDRPostThread() : - iqDataInQueue(NULL), iqDataOutQueue(NULL), iqVisualQueue(NULL), terminated(false), dcFilter(NULL), sample_rate(SRATE) { + sample_rate(SRATE), iqDataOutQueue(NULL), iqDataInQueue(NULL), iqVisualQueue(NULL), terminated(false), dcFilter(NULL) { } SDRPostThread::~SDRPostThread() { } void SDRPostThread::bindDemodulator(DemodulatorInstance *demod) { - demodulators.push_back(demod); + demodulators_add.push_back(demod); } void SDRPostThread::removeDemodulator(DemodulatorInstance *demod) { @@ -19,22 +21,16 @@ void SDRPostThread::removeDemodulator(DemodulatorInstance *demod) { return; } - std::vector::iterator i; - - i = std::find(demodulators.begin(), demodulators.end(), demod); - - if (i != demodulators.end()) { - demodulators.erase(i); - } + demodulators_remove.push_back(demod); } void SDRPostThread::setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue) { iqDataInQueue = iqDataQueue; } -void SDRPostThread::setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue) { +void SDRPostThread::setIQDataOutQueue(DemodulatorThreadInputQueue* iqDataQueue) { iqDataOutQueue = iqDataQueue; } -void SDRPostThread::setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue) { +void SDRPostThread::setIQVisualQueue(DemodulatorThreadInputQueue *iqVisQueue) { iqVisualQueue = iqVisQueue; } @@ -45,83 +41,162 @@ void SDRPostThread::threadMain() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread int priority = sched_get_priority_max( SCHED_FIFO) - 1; - sched_param prio = { priority }; // scheduling priority of thread + sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif dcFilter = iirfilt_crcf_create_dc_blocker(0.0005); - liquid_float_complex x, y; - std::cout << "SDR post-processing thread started.." << std::endl; + std::deque buffers; + std::deque::iterator buffers_i; + std::vector fpData; + std::vector dataOut; + while (!terminated) { - SDRThreadIQData data_in; + SDRThreadIQData *data_in; iqDataInQueue.load()->pop(data_in); +// std::lock_guard < std::mutex > lock(data_in->m_mutex); - if (data_in.data.size()) { - SDRThreadIQData dataOut; - - dataOut.frequency = data_in.frequency; - dataOut.bandwidth = data_in.bandwidth; - dataOut.data = data_in.data; - - for (int i = 0, iMax = dataOut.data.size() / 2; i < iMax; i++) { - x.real = (float) dataOut.data[i * 2] / 127.0; - x.imag = (float) dataOut.data[i * 2 + 1] / 127.0; - - iirfilt_crcf_execute(dcFilter, x, &y); - - dataOut.data[i * 2] = (signed char) floor(y.real * 127.0); - dataOut.data[i * 2 + 1] = (signed char) floor(y.imag * 127.0); + if (data_in && data_in->data.size()) { + int dataSize = data_in->data.size()/2; + if (dataSize > fpData.capacity()) { + fpData.reserve(dataSize); + dataOut.reserve(dataSize); } + if (dataSize != fpData.size()) { + fpData.resize(dataSize); + dataOut.resize(dataSize); + } + + for (int i = 0, iMax = dataSize; i < iMax; i++) { + fpData[i].real = (float) data_in->data[i * 2] / 127.0; + fpData[i].imag = (float) data_in->data[i * 2 + 1] / 127.0; + } + + iirfilt_crcf_execute_block(dcFilter, &fpData[0], dataSize, &dataOut[0]); if (iqDataOutQueue != NULL) { - iqDataOutQueue.load()->push(dataOut); + DemodulatorThreadIQData *pipeDataOut = new DemodulatorThreadIQData; + + pipeDataOut->frequency = data_in->frequency; + pipeDataOut->bandwidth = data_in->bandwidth; + pipeDataOut->data.assign(dataOut.begin(), dataOut.end()); + iqDataOutQueue.load()->push(pipeDataOut); } - if (iqVisualQueue != NULL) { - if (iqVisualQueue.load()->empty()) { - iqVisualQueue.load()->push(dataOut); + if (iqVisualQueue != NULL && iqVisualQueue.load()->empty()) { + DemodulatorThreadIQData *visualDataOut = new DemodulatorThreadIQData; + visualDataOut->data.assign(dataOut.begin(), dataOut.begin() + FFT_SIZE); + iqVisualQueue.load()->push(visualDataOut); + } + + if (demodulators_add.size()) { + while (!demodulators_add.empty()) { + demodulators.push_back(demodulators_add.back()); + demodulators_add.pop_back(); + } + } + if (demodulators_remove.size()) { + while (!demodulators_remove.empty()) { + DemodulatorInstance *demod = demodulators_remove.back(); + demodulators_remove.pop_back(); + + std::vector::iterator i = std::find(demodulators.begin(), demodulators.end(), demod); + + if (i != demodulators.end()) { + demodulators.erase(i); + } } } + int activeDemods = 0; + bool pushedData = false; + if (demodulators.size()) { - DemodulatorThreadIQData dummyDataOut; - dummyDataOut.frequency = data_in.frequency; - dummyDataOut.bandwidth = data_in.bandwidth; - DemodulatorThreadIQData demodDataOut; - demodDataOut.frequency = data_in.frequency; - demodDataOut.bandwidth = data_in.bandwidth; - demodDataOut.data = data_in.data; std::vector::iterator i; for (i = demodulators.begin(); i != demodulators.end(); i++) { DemodulatorInstance *demod = *i; - DemodulatorThreadInputQueue *demodQueue = demod->threadQueueDemod; - if (demod->getParams().frequency != data_in.frequency - && abs(data_in.frequency - demod->getParams().frequency) > (int) ((float) ((float) SRATE / 2.0) * 1.15)) { - if (demod->isActive()) { - demod->setActive(false); - demodQueue->push(dummyDataOut); - continue; + if (demod->getParams().frequency != data_in->frequency + && abs(data_in->frequency - demod->getParams().frequency) > (int) ((float) ((float) SRATE / 2.0))) { + continue; + } + activeDemods++; + } + + if (demodulators.size()) { + + DemodulatorThreadIQData *demodDataOut = NULL; + + for (buffers_i = buffers.begin(); buffers_i != buffers.end(); buffers_i++) { + if ((*buffers_i)->getRefCount() <= 0) { + demodDataOut = (*buffers_i); + break; } - } else if (!demod->isActive()) { - demod->setActive(true); } - demodQueue->push(demodDataOut); + if (demodDataOut == NULL) { + demodDataOut = new DemodulatorThreadIQData; + buffers.push_back(demodDataOut); + } + +// std::lock_guard < std::mutex > lock(demodDataOut->m_mutex); + demodDataOut->frequency = data_in->frequency; + demodDataOut->bandwidth = data_in->bandwidth; + demodDataOut->setRefCount(activeDemods); + demodDataOut->data.assign(dataOut.begin(), dataOut.end()); + + std::vector::iterator i; + for (i = demodulators.begin(); i != demodulators.end(); i++) { + DemodulatorInstance *demod = *i; + DemodulatorThreadInputQueue *demodQueue = demod->threadQueueDemod; + + if (demod->getParams().frequency != data_in->frequency + && abs(data_in->frequency - demod->getParams().frequency) > (int) ((float) ((float) SRATE / 2.0))) { + if (demod->isActive()) { + demod->setActive(false); + DemodulatorThreadIQData *dummyDataOut = new DemodulatorThreadIQData; + dummyDataOut->frequency = data_in->frequency; + dummyDataOut->bandwidth = data_in->bandwidth; + demodQueue->push(dummyDataOut); + } + } else if (!demod->isActive()) { + demod->setActive(true); + } + + if (!demod->isActive()) { + continue; + } + + demodQueue->push(demodDataOut); + pushedData = true; + } + + if (!pushedData) { + demodDataOut->setRefCount(0); + } } } } + data_in->decRefCount(); } + + while (!buffers.empty()) { + DemodulatorThreadIQData *demodDataDel = buffers.front(); + buffers.pop_front(); +// std::lock_guard < std::mutex > lock(demodDataDel->m_mutex); +// delete demodDataDel; + } + std::cout << "SDR post-processing thread done." << std::endl; } void SDRPostThread::terminate() { terminated = true; - SDRThreadIQData dummy; + SDRThreadIQData *dummy = new SDRThreadIQData; iqDataInQueue.load()->push(dummy); } diff --git a/src/sdr/SDRPostThread.h b/src/sdr/SDRPostThread.h index bd71b76..e70f082 100644 --- a/src/sdr/SDRPostThread.h +++ b/src/sdr/SDRPostThread.h @@ -12,8 +12,8 @@ public: void removeDemodulator(DemodulatorInstance *demod); void setIQDataInQueue(SDRThreadIQDataQueue* iqDataQueue); - void setIQDataOutQueue(SDRThreadIQDataQueue* iqDataQueue); - void setIQVisualQueue(SDRThreadIQDataQueue *iqVisQueue); + void setIQDataOutQueue(DemodulatorThreadInputQueue* iqDataQueue); + void setIQVisualQueue(DemodulatorThreadInputQueue* iqVisQueue); void threadMain(); void terminate(); @@ -21,11 +21,13 @@ public: protected: uint32_t sample_rate; - std::atomic iqDataOutQueue; - std::atomic iqDataInQueue; - std::atomic iqVisualQueue; + std::atomic iqDataInQueue; + std::atomic iqDataOutQueue; + std::atomic iqVisualQueue; std::vector demodulators; + std::vector demodulators_add; + std::vector demodulators_remove; std::atomic terminated; iirfilt_crcf dcFilter; }; diff --git a/src/sdr/SDRThread.cpp b/src/sdr/SDRThread.cpp index adfffb0..932dfa2 100644 --- a/src/sdr/SDRThread.cpp +++ b/src/sdr/SDRThread.cpp @@ -91,8 +91,8 @@ int SDRThread::enumerate_rtl() { void SDRThread::threadMain() { #ifdef __APPLE__ pthread_t tID = pthread_self(); // ID of this thread - int priority = sched_get_priority_max( SCHED_FIFO )-1; - sched_param prio = { priority }; // scheduling priority of thread + int priority = sched_get_priority_max( SCHED_FIFO) - 1; + sched_param prio = {priority}; // scheduling priority of thread pthread_setschedparam(tID, SCHED_FIFO, &prio); #endif @@ -128,6 +128,10 @@ void SDRThread::threadMain() { double seconds = 0.0; std::cout << "SDR thread started.." << std::endl; + + std::deque buffers; + std::deque::iterator buffers_i; + while (!terminated) { SDRThreadCommandQueue *cmdQueue = m_pQueue.load(); @@ -145,6 +149,8 @@ void SDRThread::threadMain() { freq_changed = true; new_freq = command.int_value; break; + default: + break; } } @@ -156,24 +162,52 @@ void SDRThread::threadMain() { rtlsdr_read_sync(dev, buf, BUF_SIZE, &n_read); - std::vector new_buffer; + SDRThreadIQData *dataOut = NULL; + + for (buffers_i = buffers.begin(); buffers_i != buffers.end(); buffers_i++) { + if ((*buffers_i)->getRefCount() <= 0) { + dataOut = (*buffers_i); + break; + } + } + + if (dataOut == NULL) { + dataOut = new SDRThreadIQData; + buffers.push_back(dataOut); + } + +// std::lock_guard < std::mutex > lock(dataOut->m_mutex); + dataOut->setRefCount(1); + dataOut->frequency = frequency; + dataOut->bandwidth = bandwidth; + + if (dataOut->data.capacity() < n_read) { + dataOut->data.reserve(n_read); + } + + if (dataOut->data.size() != n_read) { + dataOut->data.resize(n_read); + } for (int i = 0; i < n_read; i++) { - new_buffer.push_back(buf[i] - 127); + dataOut->data[i] = buf[i] - 127; } double time_slice = (double) n_read / (double) sample_rate; seconds += time_slice; - SDRThreadIQData dataOut; - dataOut.frequency = frequency; - dataOut.bandwidth = bandwidth; - dataOut.data = new_buffer; - if (iqDataOutQueue != NULL) { iqDataOutQueue.load()->push(dataOut); } } + + while (!buffers.empty()) { + SDRThreadIQData *iqDataDel = buffers.front(); + buffers.pop_front(); +// std::lock_guard < std::mutex > lock(iqDataDel->m_mutex); +// delete iqDataDel; + } + std::cout << "SDR thread done." << std::endl; } diff --git a/src/sdr/SDRThread.h b/src/sdr/SDRThread.h index ab76759..8c9ad26 100644 --- a/src/sdr/SDRThread.h +++ b/src/sdr/SDRThread.h @@ -34,7 +34,7 @@ public: int int_value; }; -class SDRThreadIQData { +class SDRThreadIQData : public ReferenceCounter { public: unsigned int frequency; unsigned int bandwidth; @@ -45,8 +45,8 @@ public: } - SDRThreadIQData(unsigned int bandwidth, unsigned int frequency, std::vector data) : - data(data), frequency(frequency), bandwidth(bandwidth) { + SDRThreadIQData(unsigned int bandwidth, unsigned int frequency, std::vector *data) : + frequency(frequency), bandwidth(bandwidth) { } @@ -56,7 +56,7 @@ public: }; typedef ThreadQueue SDRThreadCommandQueue; -typedef ThreadQueue SDRThreadIQDataQueue; +typedef ThreadQueue SDRThreadIQDataQueue; class SDRThread { public: diff --git a/src/util/GLFont.cpp b/src/util/GLFont.cpp index 4035c30..4fa2bed 100644 --- a/src/util/GLFont.cpp +++ b/src/util/GLFont.cpp @@ -5,7 +5,7 @@ #include GLFontChar::GLFontChar() : - id(0), x(0), y(0), width(0), height(0), xadvance(0), xoffset(0), yoffset(0), index(0), aspect(1) { + id(0), x(0), y(0), width(0), height(0), xoffset(0), yoffset(0), xadvance(0), aspect(1), index(0) { } @@ -96,7 +96,7 @@ int GLFontChar::getIndex() { } GLFont::GLFont() : - numCharacters(0), imageHeight(0), imageWidth(0), base(0), lineHeight(0), texId(0), loaded(false) { + numCharacters(0), lineHeight(0), base(0), imageWidth(0), imageHeight(0), loaded(false), texId(0) { } @@ -289,7 +289,7 @@ void GLFont::loadFont(std::string fontFile) { unsigned int ofs = 0; for (char_i = characters.begin(); char_i != characters.end(); char_i++) { - int charId = (*char_i).first; +// int charId = (*char_i).first; GLFontChar *fchar = (*char_i).second; float faspect = fchar->getAspect(); diff --git a/src/util/MouseTracker.h b/src/util/MouseTracker.h index dad15a3..ed0870f 100644 --- a/src/util/MouseTracker.h +++ b/src/util/MouseTracker.h @@ -5,14 +5,12 @@ class MouseTracker { public: MouseTracker(wxWindow *target) : - target(target), mouseX(0), mouseY(0), lastMouseX(0), lastMouseY(0), originMouseX(0), originMouseY(0), deltaMouseX(0), deltaMouseY(0), isMouseDown( - false), vertDragLock(false), horizDragLock(false), isMouseInView(false) { + mouseX(0), mouseY(0), lastMouseX(0), lastMouseY(0), originMouseX(0), originMouseY(0), deltaMouseX(0), deltaMouseY(0), vertDragLock(false), horizDragLock(false), isMouseDown(false), isMouseInView(false), target(target) { } MouseTracker() : - target(NULL), mouseX(0), mouseY(0), lastMouseX(0), lastMouseY(0), originMouseX(0), originMouseY(0), deltaMouseX(0), deltaMouseY(0), isMouseDown( - false), vertDragLock(false), horizDragLock(false), isMouseInView(false) { + mouseX(0), mouseY(0), lastMouseX(0), lastMouseY(0), originMouseX(0), originMouseY(0), deltaMouseX(0), deltaMouseY(0), vertDragLock(false), horizDragLock(false), isMouseDown(false), isMouseInView(false), target(NULL) { } @@ -43,10 +41,10 @@ public: private: float mouseX, mouseY; float lastMouseX, lastMouseY; - float deltaMouseX, deltaMouseY; float originMouseX, originMouseY; + float deltaMouseX, deltaMouseY; - bool isMouseDown, isMouseInView; bool vertDragLock, horizDragLock; + bool isMouseDown, isMouseInView; wxWindow *target; }; diff --git a/src/util/Timer.cpp b/src/util/Timer.cpp index 4237d42..99ca67a 100644 --- a/src/util/Timer.cpp +++ b/src/util/Timer.cpp @@ -5,7 +5,7 @@ #include #endif -Timer::Timer(void) : time_elapsed(0), system_milliseconds(0), start_time(0), end_time(0), last_update(0), paused_time(0), offset(0), paused_state(false), num_updates(0), lock_state(0), lock_rate(0) +Timer::Timer(void) : time_elapsed(0), system_milliseconds(0), start_time(0), end_time(0), last_update(0), num_updates(0), paused_time(0), offset(0), paused_state(false), lock_state(0), lock_rate(0) { } diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index 0974d3b..e9b9c27 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -29,7 +29,7 @@ SpectrumCanvas::SpectrumCanvas(wxWindow *parent, int *attribList) : wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0) { - int in_block_size = BUF_SIZE / 2; + int in_block_size = FFT_SIZE; int out_block_size = FFT_SIZE; in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * in_block_size); @@ -73,16 +73,16 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { SwapBuffers(); } -void SpectrumCanvas::setData(std::vector *data) { +void SpectrumCanvas::setData(std::vector *data) { if (data && data->size()) { if (spectrum_points.size() < FFT_SIZE * 2) { spectrum_points.resize(FFT_SIZE * 2); } - for (int i = 0; i < BUF_SIZE / 2; i++) { - in[i][0] = (float) (*data)[i * 2] / 127.0f; - in[i][1] = (float) (*data)[i * 2 + 1] / 127.0f; + for (int i = 0; i < FFT_SIZE; i++) { + in[i][0] = (*data)[i].real; + in[i][1] = (*data)[i].imag; } fftw_execute(plan); diff --git a/src/visual/SpectrumCanvas.h b/src/visual/SpectrumCanvas.h index 5f96fd5..d02f4fe 100644 --- a/src/visual/SpectrumCanvas.h +++ b/src/visual/SpectrumCanvas.h @@ -17,7 +17,7 @@ public: SpectrumCanvas(wxWindow *parent, int *attribList = NULL); ~SpectrumCanvas(); - void setData(std::vector *data); + void setData(std::vector *data); private: void OnPaint(wxPaintEvent& event); diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 6318996..2d07282 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -30,10 +30,10 @@ wxEND_EVENT_TABLE() WaterfallCanvas::WaterfallCanvas(wxWindow *parent, int *attribList) : wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, - wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), dragState(WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown( - false), altDown(false), ctrlDown(false), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0) { + wxFULL_REPAINT_ON_RESIZE), parent(parent), frameTimer(0), activeDemodulatorBandwidth(0), activeDemodulatorFrequency(0), dragState( + WF_DRAG_NONE), nextDragState(WF_DRAG_NONE), shiftDown(false), altDown(false), ctrlDown(false) { - int in_block_size = BUF_SIZE / 2; + int in_block_size = FFT_SIZE; int out_block_size = FFT_SIZE; in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * in_block_size); @@ -77,7 +77,8 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator(); - bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); + bool isNew = shiftDown + || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); if (mTracker.mouseInView()) { if (nextDragState == WF_DRAG_RANGE) { @@ -163,13 +164,21 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { switch (event.GetKeyCode()) { case WXK_RIGHT: freq = wxGetApp().getFrequency(); - freq += SRATE / 2; + if (shiftDown) { + freq += SRATE * 10; + } else { + freq += SRATE / 2; + } wxGetApp().setFrequency(freq); ((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq)); break; case WXK_LEFT: freq = wxGetApp().getFrequency(); - freq -= SRATE / 2; + if (shiftDown) { + freq -= SRATE * 10; + } else { + freq -= SRATE / 2; + } wxGetApp().setFrequency(freq); ((wxFrame*) parent)->GetStatusBar()->SetStatusText(wxString::Format(wxT("Set center frequency: %i"), freq)); break; @@ -197,16 +206,16 @@ void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { } } -void WaterfallCanvas::setData(std::vector *data) { +void WaterfallCanvas::setData(std::vector *data) { if (data && data->size()) { if (spectrum_points.size() < FFT_SIZE * 2) { spectrum_points.resize(FFT_SIZE * 2); } - for (int i = 0; i < BUF_SIZE / 2; i++) { - in[i][0] = (float) (*data)[i * 2] / 127.0f; - in[i][1] = (float) (*data)[i * 2 + 1] / 127.0f; + for (int i = 0; i < FFT_SIZE; i++) { + in[i][0] = (*data)[i].real; + in[i][1] = (*data)[i].imag; } fftw_execute(plan); @@ -431,7 +440,8 @@ void WaterfallCanvas::mouseReleased(wxMouseEvent& event) { altDown = event.AltDown(); ctrlDown = event.ControlDown(); - bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); + bool isNew = shiftDown + || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); mTracker.setVertDragLock(false); mTracker.setHorizDragLock(false); diff --git a/src/visual/WaterfallCanvas.h b/src/visual/WaterfallCanvas.h index 2600682..e320a73 100644 --- a/src/visual/WaterfallCanvas.h +++ b/src/visual/WaterfallCanvas.h @@ -21,7 +21,7 @@ public: WaterfallCanvas(wxWindow *parent, int *attribList = NULL); ~WaterfallCanvas(); - void setData(std::vector *data); + void setData(std::vector *data); int GetFrequencyAt(float x); private: