mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-10 06:18:57 -05:00
Refactor for sample rate changes, audio thread race crash fixes
This commit is contained in:
parent
b197a7ddb2
commit
4147582d2a
@ -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++;
|
||||
|
@ -2,7 +2,9 @@
|
||||
#include "CubicSDRDefs.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "CubicSDR.h"
|
||||
#include "DemodulatorThread.h"
|
||||
#include "DemodulatorInstance.h"
|
||||
#include <memory.h>
|
||||
|
||||
std::map<int, AudioThread *> AudioThread::deviceController;
|
||||
@ -11,7 +13,7 @@ std::map<int, std::thread *> 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<AudioThread *>;
|
||||
}
|
||||
|
||||
@ -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<DemodulatorInstance *>::iterator demod_i;
|
||||
std::vector<DemodulatorInstance *> *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]);
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
void setInitOutputDevice(int deviceId, int sampleRate=-1);
|
||||
int getOutputDevice();
|
||||
void setSampleRate(int sampleRate);
|
||||
int getSampleRate();
|
||||
void threadMain();
|
||||
void terminate();
|
||||
|
||||
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -58,6 +58,9 @@ protected:
|
||||
msresamp_rrrf stereoResampler;
|
||||
double audioResampleRatio;
|
||||
|
||||
firfilt_rrrf firStereoLeft;
|
||||
firfilt_rrrf firStereoRight;
|
||||
|
||||
DemodulatorThreadParameters params;
|
||||
DemodulatorThreadParameters lastParams;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -75,6 +75,7 @@ protected:
|
||||
std::atomic<bool> stereo;
|
||||
std::atomic<bool> terminated;
|
||||
std::atomic<int> demodulatorType;
|
||||
int audioSampleRate;
|
||||
|
||||
DemodulatorThreadCommandQueue* threadQueueNotify;
|
||||
DemodulatorThreadControlCommandQueue *threadQueueControl;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user