From 4147582d2a61112b051963415a1312fc85909936 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 15 Mar 2015 21:02:26 -0400 Subject: [PATCH] Refactor for sample rate changes, audio thread race crash fixes --- src/AppFrame.cpp | 2 +- src/audio/AudioThread.cpp | 101 +++++++++++++++++++------- src/audio/AudioThread.h | 1 + src/demod/DemodDefs.h | 7 +- src/demod/DemodulatorInstance.cpp | 32 +++++++- src/demod/DemodulatorInstance.h | 6 ++ src/demod/DemodulatorPreThread.cpp | 49 +++++++++++-- src/demod/DemodulatorPreThread.h | 3 + src/demod/DemodulatorThread.cpp | 44 +++++------ src/demod/DemodulatorThread.h | 1 + src/demod/DemodulatorWorkerThread.cpp | 20 +++++ src/demod/DemodulatorWorkerThread.h | 10 ++- 12 files changed, 211 insertions(+), 65 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index cc0dc35..0a6d243 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -251,9 +251,9 @@ wxFrame(NULL, wxID_ANY, CUBICSDR_TITLE), activeDemodulator(NULL) { wxMenuItem *itm = subMenu->AppendRadioItem(menu_id+j, srateName.str(), wxT("Description?")); if ((*srate) == DEFAULT_AUDIO_SAMPLE_RATE) { + AudioThread::deviceSampleRate[mdevices_i->first] = DEFAULT_AUDIO_SAMPLE_RATE; itm->Check(true); } - audioSampleRateMenuItems[menu_id+j] = itm; j++; diff --git a/src/audio/AudioThread.cpp b/src/audio/AudioThread.cpp index 59d9220..654af30 100644 --- a/src/audio/AudioThread.cpp +++ b/src/audio/AudioThread.cpp @@ -2,7 +2,9 @@ #include "CubicSDRDefs.h" #include #include +#include "CubicSDR.h" #include "DemodulatorThread.h" +#include "DemodulatorInstance.h" #include std::map AudioThread::deviceController; @@ -11,7 +13,7 @@ std::map AudioThread::deviceThread; AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) : currentInput(NULL), inputQueue(inputQueue), audioQueuePtr(0), underflowCount(0), terminated(false), active(false), outputDevice(-1), gain( - 1.0), threadQueueNotify(threadQueueNotify), sampleRate(DEFAULT_AUDIO_SAMPLE_RATE), nBufferFrames(256) { + 1.0), threadQueueNotify(threadQueueNotify), sampleRate(0), nBufferFrames(1024) { boundThreads = new std::vector; } @@ -68,33 +70,53 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu } if (!srcmix->currentInput) { - if (srcmix->terminated) { + srcmix->audioQueuePtr = 0; + if (srcmix->terminated || srcmix->inputQueue->empty()) { continue; } srcmix->inputQueue->pop(srcmix->currentInput); if (srcmix->terminated) { continue; } - srcmix->audioQueuePtr = 0; continue; } - std::lock_guard < std::mutex > lock(srcmix->currentInput->m_mutex); +// std::lock_guard < std::mutex > lock(srcmix->currentInput->m_mutex); + + if (srcmix->currentInput->sampleRate != src->getSampleRate()) { + while (srcmix->inputQueue->size()) { + srcmix->inputQueue->pop(srcmix->currentInput); + if (srcmix->currentInput) { + if (srcmix->currentInput->sampleRate == src->getSampleRate()) { + break; + } + srcmix->currentInput->decRefCount(); + } + srcmix->currentInput = NULL; + } + + srcmix->audioQueuePtr = 0; + + if (!srcmix->currentInput) { + continue; + } + } + if (srcmix->currentInput->channels == 0 || !srcmix->currentInput->data.size()) { if (!srcmix->inputQueue->empty()) { + srcmix->audioQueuePtr = 0; if (srcmix->currentInput) { srcmix->currentInput->decRefCount(); srcmix->currentInput = NULL; } - if (srcmix->terminated) { + if (srcmix->terminated || srcmix->inputQueue->empty()) { continue; } srcmix->inputQueue->pop(srcmix->currentInput); if (srcmix->terminated) { continue; } - srcmix->audioQueuePtr = 0; } continue; } @@ -104,18 +126,18 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu if (srcmix->currentInput->channels == 1) { for (int i = 0; i < nBufferFrames; i++) { if (srcmix->audioQueuePtr >= srcmix->currentInput->data.size()) { + srcmix->audioQueuePtr = 0; if (srcmix->currentInput) { srcmix->currentInput->decRefCount(); srcmix->currentInput = NULL; } - if (srcmix->terminated) { - continue; + if (srcmix->terminated || srcmix->inputQueue->empty()) { + break; } srcmix->inputQueue->pop(srcmix->currentInput); if (srcmix->terminated) { - continue; + break; } - srcmix->audioQueuePtr = 0; float srcPeak = srcmix->currentInput->peak * srcmix->gain; if (mixPeak < srcPeak) { mixPeak = srcPeak; @@ -131,18 +153,18 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu } else { for (int i = 0, iMax = srcmix->currentInput->channels * nBufferFrames; i < iMax; i++) { if (srcmix->audioQueuePtr >= srcmix->currentInput->data.size()) { + srcmix->audioQueuePtr = 0; if (srcmix->currentInput) { srcmix->currentInput->decRefCount(); srcmix->currentInput = NULL; } - if (srcmix->terminated) { - continue; + if (srcmix->terminated || srcmix->inputQueue->empty()) { + break; } srcmix->inputQueue->pop(srcmix->currentInput); if (srcmix->terminated) { - continue; + break; } - srcmix->audioQueuePtr = 0; float srcPeak = srcmix->currentInput->peak * srcmix->gain; if (mixPeak < srcPeak) { mixPeak = srcPeak; @@ -228,12 +250,37 @@ void AudioThread::setDeviceSampleRate(int deviceId, int sampleRate) { } void AudioThread::setSampleRate(int sampleRate) { - deviceSampleRate[outputDevice] = sampleRate; + if (deviceController[outputDevice.load()] == this) { + deviceSampleRate[outputDevice.load()] = sampleRate; + + dac.stopStream(); + dac.closeStream(); + + for (int j = 0; j < boundThreads.load()->size(); j++) { + AudioThread *srcmix = (*(boundThreads.load()))[j]; + srcmix->setSampleRate(sampleRate); + } + + std::vector::iterator demod_i; + std::vector *demodulators; + + demodulators = &wxGetApp().getDemodMgr().getDemodulators(); + + for (demod_i = demodulators->begin(); demod_i != demodulators->end(); demod_i++) { + if ((*demod_i)->getOutputDevice() == outputDevice.load()) { + (*demod_i)->setAudioSampleRate(sampleRate); + } + } + + dac.openStream(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &nBufferFrames, &audioCallback, (void *) this, &opts); + dac.startStream(); + } + this->sampleRate = sampleRate; - dac.stopStream(); - dac.closeStream(); - dac.openStream(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &nBufferFrames, &audioCallback, (void *) this, &opts); - dac.startStream(); +} + +int AudioThread::getSampleRate() { + return this->sampleRate; } void AudioThread::setupDevice(int deviceId) { @@ -253,15 +300,17 @@ void AudioThread::setupDevice(int deviceId) { // opts.flags = RTAUDIO_MINIMIZE_LATENCY; opts.flags = RTAUDIO_SCHEDULE_REALTIME; + if (deviceSampleRate.find(parameters.deviceId) != deviceSampleRate.end()) { + sampleRate = deviceSampleRate[parameters.deviceId]; + } else { + sampleRate = DEFAULT_AUDIO_SAMPLE_RATE; + deviceSampleRate[parameters.deviceId] = sampleRate; + } + if (deviceController.find(parameters.deviceId) == deviceController.end()) { deviceController[parameters.deviceId] = new AudioThread(NULL, NULL); - int srate = DEFAULT_AUDIO_SAMPLE_RATE; - if (deviceSampleRate.find(parameters.deviceId) != deviceSampleRate.end()) { - srate = deviceSampleRate[parameters.deviceId]; - } else { - deviceSampleRate[parameters.deviceId] = srate; - } - deviceController[parameters.deviceId]->setInitOutputDevice(parameters.deviceId, srate); + + deviceController[parameters.deviceId]->setInitOutputDevice(parameters.deviceId, sampleRate); deviceController[parameters.deviceId]->bindThread(this); deviceThread[parameters.deviceId] = new std::thread(&AudioThread::threadMain, deviceController[parameters.deviceId]); diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index b28f022..0d10f97 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -68,6 +68,7 @@ public: void setInitOutputDevice(int deviceId, int sampleRate=-1); int getOutputDevice(); void setSampleRate(int sampleRate); + int getSampleRate(); void threadMain(); void terminate(); diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index fb5f5d9..fa1adc0 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -21,6 +21,7 @@ public: DEMOD_THREAD_CMD_NULL, DEMOD_THREAD_CMD_SET_BANDWIDTH, DEMOD_THREAD_CMD_SET_FREQUENCY, + DEMOD_THREAD_CMD_SET_AUDIO_RATE, DEMOD_THREAD_CMD_DEMOD_PREPROCESS_TERMINATED, DEMOD_THREAD_CMD_DEMOD_TERMINATED, DEMOD_THREAD_CMD_AUDIO_TERMINATED @@ -78,9 +79,13 @@ public: msresamp_rrrf audioResampler; msresamp_rrrf stereoResampler; double audioResampleRatio; + int audioSampleRate; + + firfilt_rrrf firStereoLeft; + firfilt_rrrf firStereoRight; DemodulatorThreadPostIQData() : - sampleRate(0), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(0) { + sampleRate(0), audioResampler(NULL), stereoResampler(NULL), audioResampleRatio(0), audioSampleRate(0), firStereoLeft(NULL), firStereoRight(NULL) { } diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index eba50f3..12a27fb 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -50,6 +50,8 @@ void DemodulatorInstance::run() { currentFrequency = demodulatorPreThread->getParams().frequency; currentDemodType = demodulatorThread->getDemodulatorType(); + currentAudioSampleRate = AudioThread::deviceSampleRate[getOutputDevice()]; + demodulatorPreThread->getParams().audioSampleRate = currentAudioSampleRate; t_Audio = new std::thread(&AudioThread::threadMain, audioThread); @@ -215,6 +217,8 @@ void DemodulatorInstance::setOutputDevice(int device_id) { if (!active) { audioThread->setInitOutputDevice(device_id); } else if (audioThread) { + setAudioSampleRate(AudioThread::deviceSampleRate[device_id]); + AudioThreadCommand command; command.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE; command.int_value = device_id; @@ -225,10 +229,10 @@ void DemodulatorInstance::setOutputDevice(int device_id) { int DemodulatorInstance::getOutputDevice() { if (currentOutputDevice == -1) { - return audioThread->getOutputDevice(); - } else { - return currentOutputDevice; + currentOutputDevice = audioThread->getOutputDevice(); } + + return currentOutputDevice; } void DemodulatorInstance::checkBandwidth() { @@ -302,6 +306,28 @@ long long DemodulatorInstance::getFrequency() { return currentFrequency; } + +void DemodulatorInstance::setAudioSampleRate(int sampleRate) { + if (terminated) { + currentAudioSampleRate = sampleRate; + demodulatorPreThread->getParams().audioSampleRate = sampleRate; + } else if (demodulatorPreThread && threadQueueCommand) { + DemodulatorThreadCommand command; + command.cmd = DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE; + currentAudioSampleRate = sampleRate; + command.llong_value = sampleRate; + threadQueueCommand->push(command); + } +} + +int DemodulatorInstance::getAudioSampleRate() { + if (!currentAudioSampleRate) { + currentAudioSampleRate = audioThread->getSampleRate(); + } + return currentAudioSampleRate; +} + + void DemodulatorInstance::setGain(float gain_in) { audioThread->setGain(gain_in); } diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index ee1eb42..15743b6 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -73,6 +73,11 @@ public: void setFrequency(long long freq); long long getFrequency(); + + void setAudioSampleRate(int sampleRate); + int getAudioSampleRate(); + + private: void checkBandwidth(); @@ -90,4 +95,5 @@ private: int currentBandwidth; int currentDemodType; int currentOutputDevice; + int currentAudioSampleRate; }; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 1d85c4a..3d5345d 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -11,7 +11,7 @@ DemodulatorPreThread::DemodulatorPreThread(DemodulatorThreadInputQueue* iqInputQueue, DemodulatorThreadPostInputQueue* iqOutputQueue, DemodulatorThreadControlCommandQueue *threadQueueControl, DemodulatorThreadCommandQueue* threadQueueNotify) : iqInputQueue(iqInputQueue), iqOutputQueue(iqOutputQueue), terminated(false), initialized(false), audioResampler(NULL), stereoResampler(NULL), iqResampleRatio( - 1), audioResampleRatio(1), iqResampler(NULL), commandQueue(NULL), threadQueueNotify(threadQueueNotify), threadQueueControl( + 1), audioResampleRatio(1), firStereoRight(NULL), firStereoLeft(NULL), iqResampler(NULL), commandQueue(NULL), threadQueueNotify(threadQueueNotify), threadQueueControl( threadQueueControl) { freqShifter = nco_crcf_create(LIQUID_VCO); @@ -36,8 +36,27 @@ void DemodulatorPreThread::initialize() { audioResampler = msresamp_rrrf_create(audioResampleRatio, As); stereoResampler = msresamp_rrrf_create(audioResampleRatio, As); + // Stereo filters / shifters + double firStereoCutoff = 0.5 * ((double) 36000 / (double) params.audioSampleRate); // filter cutoff frequency + float ft = 0.05f; // filter transition + float mu = 0.0f; // fractional timing offset + + 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); + initialized = true; -// std::cout << "inputResampleRate " << params.bandwidth << std::endl; lastParams = params; } @@ -100,7 +119,11 @@ void DemodulatorPreThread::threadMain() { bandwidthChanged = true; break; case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_FREQUENCY: - params.frequency = command.llong_value; + params.frequency = tempParams.frequency = command.llong_value; + break; + case DemodulatorThreadCommand::DEMOD_THREAD_CMD_SET_AUDIO_RATE: + tempParams.audioSampleRate = (int)command.llong_value; + rateChanged = true; break; default: break; @@ -228,7 +251,10 @@ void DemodulatorPreThread::threadMain() { resamp->audioResampleRatio = audioResampleRatio; resamp->audioResampler = audioResampler; + resamp->audioSampleRate = params.audioSampleRate; resamp->stereoResampler = stereoResampler; + resamp->firStereoLeft = firStereoLeft; + resamp->firStereoRight = firStereoRight; resamp->sampleRate = params.bandwidth; iqOutputQueue->push(resamp); @@ -245,23 +271,34 @@ void DemodulatorPreThread::threadMain() { case DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS: msresamp_crcf_destroy(iqResampler); - if (result.iqResampler) { iqResampler = result.iqResampler; iqResampleRatio = result.iqResampleRatio; } + if (result.firStereoLeft) { + firStereoLeft = result.firStereoLeft; + } + + if (result.firStereoRight) { + firStereoRight = result.firStereoRight; + } + if (result.audioResampler) { audioResampler = result.audioResampler; audioResampleRatio = result.audioResamplerRatio; stereoResampler = result.stereoResampler; + } + + if (result.audioSampleRate) { params.audioSampleRate = result.audioSampleRate; } - if (params.bandwidth) { + if (result.bandwidth) { params.bandwidth = result.bandwidth; } - if (params.sampleRate) { + + if (result.sampleRate) { params.sampleRate = result.sampleRate; } break; diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index e5d8467..dde1239 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -58,6 +58,9 @@ protected: msresamp_rrrf stereoResampler; double audioResampleRatio; + firfilt_rrrf firStereoLeft; + firfilt_rrrf firStereoRight; + DemodulatorThreadParameters params; DemodulatorThreadParameters lastParams; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index e8d7cf6..1aa70a4 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -16,7 +16,7 @@ DemodulatorThread::DemodulatorThread(DemodulatorThreadPostInputQueue* iqInputQue iqInputQueue(iqInputQueue), audioVisOutputQueue(NULL), audioOutputQueue(NULL), iqAutoGain(NULL), amOutputCeil(1), amOutputCeilMA(1), amOutputCeilMAA( 1), stereo(false), terminated( false), demodulatorType(DEMOD_TYPE_FM), threadQueueNotify(threadQueueNotify), threadQueueControl(threadQueueControl), squelchLevel(0), signalLevel( - 0), squelchEnabled(false) { + 0), squelchEnabled(false), audioSampleRate(0) { demodFM = freqdem_create(0.5); demodAM_USB = ampmodem_create(0.5, 0.0, LIQUID_AMPMODEM_USB, 1); @@ -46,29 +46,6 @@ void DemodulatorThread::threadMain() { firfilt_rrrf firStereoLeft = NULL; firfilt_rrrf firStereoRight = NULL; - // Stereo filters / shifters - double firStereoCutoff = 0.5 * ((double) 36000 / (double) DEFAULT_AUDIO_SAMPLE_RATE); // filter cutoff frequency - float ft = 0.05f; // filter transition - float As = 120.0f; // stop-band attenuation [dB] - float mu = 0.0f; // fractional timing offset - - 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); - - delete h; - liquid_float_complex x, y, z[2]; float rz[2]; @@ -124,11 +101,15 @@ void DemodulatorThread::threadMain() { if (audioResampler == NULL) { audioResampler = inp->audioResampler; stereoResampler = inp->stereoResampler; + firStereoLeft = inp->firStereoLeft; + firStereoRight = inp->firStereoRight; + 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); @@ -136,6 +117,20 @@ void DemodulatorThread::threadMain() { freqdem_reset(demodFM); } + 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 (agcData.size() != bufSize) { if (agcData.capacity() < bufSize) { agcData.reserve(bufSize); @@ -274,6 +269,7 @@ void DemodulatorThread::threadMain() { outputBuffers.push_back(ati); } + ati->sampleRate = audioSampleRate; ati->setRefCount(1); if (stereo) { diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 01bd5eb..f9d013b 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -75,6 +75,7 @@ protected: std::atomic stereo; std::atomic terminated; std::atomic demodulatorType; + int audioSampleRate; DemodulatorThreadCommandQueue* threadQueueNotify; DemodulatorThreadControlCommandQueue *threadQueueControl; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index cddd3ed..99199d1 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -49,6 +49,26 @@ void DemodulatorWorkerThread::threadMain() { result.audioResampler = msresamp_rrrf_create(result.audioResamplerRatio, As); result.stereoResampler = msresamp_rrrf_create(result.audioResamplerRatio, As); result.audioSampleRate = filterCommand.audioSampleRate; + + // Stereo filters / shifters + double firStereoCutoff = 0.5 * ((double) 36000 / (double) filterCommand.audioSampleRate); // filter cutoff frequency + float ft = 0.05f; // filter transition + float mu = 0.0f; // fractional timing offset + + 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); + + result.firStereoLeft = firfilt_rrrf_create(h, h_len); + result.firStereoRight = firfilt_rrrf_create(h, h_len); } if (filterCommand.bandwidth) { diff --git a/src/demod/DemodulatorWorkerThread.h b/src/demod/DemodulatorWorkerThread.h index 47b014f..a14f375 100644 --- a/src/demod/DemodulatorWorkerThread.h +++ b/src/demod/DemodulatorWorkerThread.h @@ -16,14 +16,13 @@ public: DemodulatorWorkerThreadResult() : cmd(DEMOD_WORKER_THREAD_RESULT_NULL), iqResampler(NULL), iqResampleRatio(0), audioResampler(NULL), stereoResampler(NULL), audioResamplerRatio( - 0), sampleRate(0), bandwidth(0), audioSampleRate(0) { + 0), firStereoLeft(NULL), firStereoRight(NULL), sampleRate(0), bandwidth(0), audioSampleRate(0) { } DemodulatorWorkerThreadResult(DemodulatorThreadResultEnum cmd) : - cmd(cmd), iqResampler(NULL), iqResampleRatio(0), audioResampler(NULL), stereoResampler(NULL), audioResamplerRatio(0), sampleRate(0), bandwidth( - 0), audioSampleRate(0) { - + DemodulatorWorkerThreadResult() { + this->cmd = cmd; } DemodulatorThreadResultEnum cmd; @@ -34,6 +33,9 @@ public: msresamp_rrrf stereoResampler; double audioResamplerRatio; + firfilt_rrrf firStereoLeft; + firfilt_rrrf firStereoRight; + long long sampleRate; unsigned int bandwidth; unsigned int audioSampleRate;