1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-04-04 02:28:33 -04:00

SSB modulator: use settings in modulator

This commit is contained in:
f4exb 2017-10-21 12:17:11 +02:00
parent e36a6a0eb7
commit 483cdfdcea
4 changed files with 252 additions and 489 deletions

View File

@ -27,6 +27,7 @@
#include "util/db.h"
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureSSBMod, Message)
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureChannelizer, Message)
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureFileSourceName, Message)
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureFileSourceSeek, Message)
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureAFInput, Message)
@ -59,26 +60,16 @@ SSBMod::SSBMod(BasebandSampleSink* sampleSink) :
{
setObjectName("SSBMod");
m_SSBFilter = new fftfilt(m_config.m_lowCutoff / m_config.m_audioSampleRate, m_config.m_bandwidth / m_config.m_audioSampleRate, m_ssbFftLen);
m_DSBFilter = new fftfilt((2.0f * m_config.m_bandwidth) / m_config.m_audioSampleRate, 2 * m_ssbFftLen);
m_SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_settings.m_audioSampleRate, m_settings.m_bandwidth / m_settings.m_audioSampleRate, m_ssbFftLen);
m_DSBFilter = new fftfilt((2.0f * m_settings.m_bandwidth) / m_settings.m_audioSampleRate, 2 * m_ssbFftLen);
m_SSBFilterBuffer = new Complex[m_ssbFftLen>>1]; // filter returns data exactly half of its size
m_DSBFilterBuffer = new Complex[m_ssbFftLen];
memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
m_config.m_outputSampleRate = 48000;
m_config.m_inputFrequencyOffset = 0;
m_config.m_bandwidth = 12500;
m_config.m_toneFrequency = 1000.0f;
m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioBuffer.resize(1<<14);
m_audioBufferFill = 0;
// m_magsqSpectrum = 0.0f;
// m_magsqSum = 0.0f;
// m_magsqPeak = 0.0f;
// m_magsqCount = 0;
m_sum.real(0.0f);
m_sum.imag(0.0f);
m_undersampleCount = 0;
@ -87,18 +78,18 @@ SSBMod::SSBMod(BasebandSampleSink* sampleSink) :
m_movingAverage.resize(16, 0);
m_magsq = 0.0;
m_toneNco.setFreq(1000.0, m_config.m_audioSampleRate);
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
DSPEngine::instance()->addAudioSource(&m_audioFifo);
// CW keyer
m_cwKeyer.setSampleRate(m_config.m_audioSampleRate);
m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
m_cwKeyer.setWPM(13);
m_cwKeyer.setMode(CWKeyer::CWNone);
m_inAGC.setGate(m_config.m_agcThresholdGate);
m_inAGC.setStepDownDelay(m_config.m_agcThresholdDelay);
m_inAGC.setGate(m_settings.m_agcThresholdGate);
m_inAGC.setStepDownDelay(m_settings.m_agcThresholdDelay);
m_inAGC.setClamping(true);
apply();
applySettings(m_settings, true);
}
SSBMod::~SSBMod()
@ -122,43 +113,6 @@ SSBMod::~SSBMod()
DSPEngine::instance()->removeAudioSource(&m_audioFifo);
}
void SSBMod::configure(MessageQueue* messageQueue,
Real bandwidth,
Real lowCutoff,
float toneFrequency,
float volumeFactor,
int spanLog2,
bool audioBinaural,
bool audioFlipChannels,
bool dsb,
bool audioMute,
bool playLoop,
bool agc,
float agcOrder,
int agcTime,
int agcThreshold,
int agcThresholdGate,
int agcThresholdDelay)
{
Message* cmd = MsgConfigureSSBMod::create(bandwidth,
lowCutoff,
toneFrequency,
volumeFactor,
spanLog2,
audioBinaural,
audioFlipChannels,
dsb,
audioMute,
playLoop,
agc,
agcOrder,
agcTime,
agcThreshold,
agcThresholdGate,
agcThresholdDelay);
messageQueue->push(cmd);
}
void SSBMod::pull(Sample& sample)
{
Complex ci;
@ -200,7 +154,7 @@ void SSBMod::pull(Sample& sample)
void SSBMod::pullAudio(int nbSamples)
{
unsigned int nbSamplesAudio = nbSamples * ((Real) m_config.m_audioSampleRate / (Real) m_config.m_basebandSampleRate);
unsigned int nbSamplesAudio = nbSamples * ((Real) m_settings.m_audioSampleRate / (Real) m_settings.m_basebandSampleRate);
if (nbSamplesAudio > m_audioBuffer.size())
{
@ -220,7 +174,7 @@ void SSBMod::modulateSample()
void SSBMod::pullAF(Complex& sample)
{
if (m_running.m_audioMute)
if (m_settings.m_audioMute)
{
sample.real(0.0f);
sample.imag(0.0f);
@ -231,13 +185,13 @@ void SSBMod::pullAF(Complex& sample)
fftfilt::cmplx *filtered;
int n_out = 0;
int decim = 1<<(m_running.m_spanLog2 - 1);
int decim = 1<<(m_settings.m_spanLog2 - 1);
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
switch (m_afInput)
{
case SSBModInputTone:
if (m_running.m_dsb)
if (m_settings.m_dsb)
{
Real t = m_toneNco.next()/1.25;
sample.real(t);
@ -245,7 +199,7 @@ void SSBMod::pullAF(Complex& sample)
}
else
{
if (m_running.m_usb) {
if (m_settings.m_usb) {
sample = m_toneNco.nextIQ();
} else {
sample = m_toneNco.nextQI();
@ -263,7 +217,7 @@ void SSBMod::pullAF(Complex& sample)
{
if (m_ifstream.eof())
{
if (m_running.m_playLoop)
if (m_settings.m_playLoop)
{
m_ifstream.clear();
m_ifstream.seekg(0, std::ios::beg);
@ -277,19 +231,19 @@ void SSBMod::pullAF(Complex& sample)
}
else
{
if (m_running.m_audioBinaural)
if (m_settings.m_audioBinaural)
{
Complex c;
m_ifstream.read(reinterpret_cast<char*>(&c), sizeof(Complex));
if (m_running.m_audioFlipChannels)
if (m_settings.m_audioFlipChannels)
{
ci.real(c.imag() * m_running.m_volumeFactor);
ci.imag(c.real() * m_running.m_volumeFactor);
ci.real(c.imag() * m_settings.m_volumeFactor);
ci.imag(c.real() * m_settings.m_volumeFactor);
}
else
{
ci = c * m_running.m_volumeFactor;
ci = c * m_settings.m_volumeFactor;
}
}
else
@ -297,16 +251,16 @@ void SSBMod::pullAF(Complex& sample)
Real real;
m_ifstream.read(reinterpret_cast<char*>(&real), sizeof(Real));
if (m_running.m_agc)
if (m_settings.m_agc)
{
ci.real(real);
ci.imag(0.0f);
m_inAGC.feed(ci);
ci *= m_running.m_volumeFactor;
ci *= m_settings.m_volumeFactor;
}
else
{
ci.real(real * m_running.m_volumeFactor);
ci.real(real * m_settings.m_volumeFactor);
ci.imag(0.0f);
}
}
@ -319,31 +273,31 @@ void SSBMod::pullAF(Complex& sample)
}
break;
case SSBModInputAudio:
if (m_running.m_audioBinaural)
if (m_settings.m_audioBinaural)
{
if (m_running.m_audioFlipChannels)
if (m_settings.m_audioFlipChannels)
{
ci.real((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_running.m_volumeFactor);
ci.imag((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_running.m_volumeFactor);
ci.real((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_settings.m_volumeFactor);
ci.imag((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_settings.m_volumeFactor);
}
else
{
ci.real((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_running.m_volumeFactor);
ci.imag((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_running.m_volumeFactor);
ci.real((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_settings.m_volumeFactor);
ci.imag((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_settings.m_volumeFactor);
}
}
else
{
if (m_running.m_agc)
if (m_settings.m_agc)
{
ci.real(((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f));
ci.imag(0.0f);
m_inAGC.feed(ci);
ci *= m_running.m_volumeFactor;
ci *= m_settings.m_volumeFactor;
}
else
{
ci.real(((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_running.m_volumeFactor);
ci.real(((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_settings.m_volumeFactor);
ci.imag(0.0f);
}
}
@ -356,7 +310,7 @@ void SSBMod::pullAF(Complex& sample)
{
m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
if (m_running.m_dsb)
if (m_settings.m_dsb)
{
Real t = m_toneNco.next() * fadeFactor;
sample.real(t);
@ -364,7 +318,7 @@ void SSBMod::pullAF(Complex& sample)
}
else
{
if (m_running.m_usb) {
if (m_settings.m_usb) {
sample = m_toneNco.nextIQ() * fadeFactor;
} else {
sample = m_toneNco.nextQI() * fadeFactor;
@ -375,7 +329,7 @@ void SSBMod::pullAF(Complex& sample)
{
if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor))
{
if (m_running.m_dsb)
if (m_settings.m_dsb)
{
Real t = (m_toneNco.next() * fadeFactor)/1.25;
sample.real(t);
@ -383,7 +337,7 @@ void SSBMod::pullAF(Complex& sample)
}
else
{
if (m_running.m_usb) {
if (m_settings.m_usb) {
sample = m_toneNco.nextIQ() * fadeFactor;
} else {
sample = m_toneNco.nextQI() * fadeFactor;
@ -406,7 +360,7 @@ void SSBMod::pullAF(Complex& sample)
if ((m_afInput == SSBModInputFile) || (m_afInput == SSBModInputAudio)) // real audio
{
if (m_running.m_dsb)
if (m_settings.m_dsb)
{
n_out = m_DSBFilter->runDSB(ci, &filtered);
@ -421,7 +375,7 @@ void SSBMod::pullAF(Complex& sample)
}
else
{
n_out = m_SSBFilter->runSSB(ci, &filtered, m_running.m_usb);
n_out = m_SSBFilter->runSSB(ci, &filtered, m_settings.m_usb);
if (n_out > 0)
{
@ -457,7 +411,7 @@ void SSBMod::pullAF(Complex& sample)
//
// m_magsqCount++;
if (!m_running.m_dsb & !m_running.m_usb)
if (!m_settings.m_dsb & !m_settings.m_usb)
{ // invert spectrum for LSB
m_sampleBuffer.push_back(Sample(avgi, avgr));
}
@ -491,7 +445,7 @@ void SSBMod::pullAF(Complex& sample)
//
// m_magsqCount++;
if (!m_running.m_dsb & !m_running.m_usb)
if (!m_settings.m_dsb & !m_settings.m_usb)
{ // invert spectrum for LSB
m_sampleBuffer.push_back(Sample(avgi, avgr));
}
@ -504,7 +458,7 @@ void SSBMod::pullAF(Complex& sample)
m_sum.imag(0.0);
}
if (m_sumCount < (m_running.m_dsb ? m_ssbFftLen : m_ssbFftLen>>1))
if (m_sumCount < (m_settings.m_dsb ? m_ssbFftLen : m_ssbFftLen>>1))
{
n_out = 0;
m_sumCount++;
@ -520,7 +474,7 @@ void SSBMod::pullAF(Complex& sample)
{
if (m_sampleSink != 0)
{
m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), !m_running.m_dsb);
m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), !m_settings.m_dsb);
}
m_sampleBuffer.clear();
@ -550,8 +504,8 @@ void SSBMod::calculateLevel(Complex& sample)
void SSBMod::start()
{
qDebug() << "SSBMod::start: m_outputSampleRate: " << m_config.m_outputSampleRate
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
qDebug() << "SSBMod::start: m_outputSampleRate: " << m_settings.m_outputSampleRate
<< " m_inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset;
m_audioFifo.clear();
}
@ -566,91 +520,82 @@ bool SSBMod::handleMessage(const Message& cmd)
{
UpChannelizer::MsgChannelizerNotification& notif = (UpChannelizer::MsgChannelizerNotification&) cmd;
m_config.m_basebandSampleRate = notif.getBasebandSampleRate();
m_config.m_outputSampleRate = notif.getSampleRate();
m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
SSBModSettings settings = m_settings;
apply();
settings.m_basebandSampleRate = notif.getBasebandSampleRate();
settings.m_outputSampleRate = notif.getSampleRate();
settings.m_inputFrequencyOffset = notif.getFrequencyOffset();
applySettings(settings);
qDebug() << "SSBMod::handleMessage: MsgChannelizerNotification:"
<< " m_basebandSampleRate: " << m_config.m_basebandSampleRate
<< " m_outputSampleRate: " << m_config.m_outputSampleRate
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
<< " m_basebandSampleRate: " << settings.m_basebandSampleRate
<< " m_outputSampleRate: " << settings.m_outputSampleRate
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset;
return true;
}
else if (MsgConfigureSSBMod::match(cmd))
{
float band, lowCutoff;
else if (MsgConfigureSSBMod::match(cmd))
{
float band, lowCutoff;
MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd;
MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd;
m_settingsMutex.lock();
SSBModSettings settings = cfg.getSettings();
band = cfg.getBandwidth();
lowCutoff = cfg.getLowCutoff();
// These settings are set with UpChannelizer::MsgChannelizerNotification
settings.m_basebandSampleRate = m_settings.m_basebandSampleRate;
settings.m_outputSampleRate = m_settings.m_outputSampleRate;
settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset;
if (band < 0) // negative means LSB
{
band = -band; // turn to positive
lowCutoff = -lowCutoff;
m_config.m_usb = false; // and take note of side band
}
else
{
m_config.m_usb = true;
}
band = settings.m_bandwidth;
lowCutoff = settings.m_lowCutoff;
if (band < 100.0f) // at least 100 Hz
{
band = 100.0f;
lowCutoff = 0;
}
if (band < 0) // negative means LSB
{
band = -band; // turn to positive
lowCutoff = -lowCutoff;
settings.m_usb = false; // and take note of side band
}
else
{
settings.m_usb = true;
}
m_config.m_bandwidth = band;
m_config.m_lowCutoff = lowCutoff;
if (band < 100.0f) // at least 100 Hz
{
band = 100.0f;
lowCutoff = 0;
}
m_config.m_toneFrequency = cfg.getToneFrequency();
m_config.m_volumeFactor = cfg.getVolumeFactor();
m_config.m_spanLog2 = cfg.getSpanLog2();
m_config.m_audioBinaural = cfg.getAudioBinaural();
m_config.m_audioFlipChannels = cfg.getAudioFlipChannels();
m_config.m_dsb = cfg.getDSB();
m_config.m_audioMute = cfg.getAudioMute();
m_config.m_playLoop = cfg.getPlayLoop();
m_config.m_agc = cfg.getAGC();
settings.m_bandwidth = band;
settings.m_lowCutoff = lowCutoff;
m_config.m_agcTime = cfg.getAGCTime(); // ms
m_config.m_agcOrder = cfg.getAGCOrder();
m_config.m_agcThresholdEnable = cfg.getAGCThreshold() != -99;
m_config.m_agcThreshold = CalcDb::powerFromdB(cfg.getAGCThreshold()); // power dB
m_config.m_agcThresholdGate = cfg.getAGCThresholdGate(); // ms
m_config.m_agcThresholdDelay = cfg.getAGCThresholdDelay(); // ms
applySettings(settings, cfg.getForce());
apply();
qDebug() << "SSBMod::handleMessage: MsgConfigureSSBMod:"
<< " m_bandwidth: " << settings.m_bandwidth
<< " m_lowCutoff: " << settings.m_lowCutoff
<< " m_toneFrequency: " << settings.m_toneFrequency
<< " m_volumeFactor: " << settings.m_volumeFactor
<< " m_spanLog2: " << settings.m_spanLog2
<< " m_outputSampleRate: " << m_settings.m_outputSampleRate
<< " m_audioSampleRate: " << settings.m_audioSampleRate
<< " m_audioBinaural: " << settings.m_audioBinaural
<< " m_audioFlipChannels: " << settings.m_audioFlipChannels
<< " m_dsb: " << settings.m_dsb
<< " m_audioMute: " << settings.m_audioMute
<< " m_playLoop: " << settings.m_playLoop
<< " m_agc: " << settings.m_agc
<< " m_agcTime: " << settings.m_agcTime
<< " m_agcOrder: " << settings.m_agcOrder
<< " m_agcThresholdEnable: " << settings.m_agcThresholdEnable
<< " m_agcThreshold: " << settings.m_agcThreshold
<< " m_agcThresholdGate: " << settings.m_agcThresholdGate
<< " m_agcThresholdDelay: " << settings.m_agcThresholdDelay
<< " force: " << cfg.getForce();
m_settingsMutex.unlock();
qDebug() << "SSBMod::handleMessage: MsgConfigureSSBMod:"
<< " m_bandwidth: " << m_config.m_bandwidth
<< " m_lowCutoff: " << m_config.m_lowCutoff
<< " m_toneFrequency: " << m_config.m_toneFrequency
<< " m_volumeFactor: " << m_config.m_volumeFactor
<< " m_spanLog2: " << m_config.m_spanLog2
<< " m_audioBinaural: " << m_config.m_audioBinaural
<< " m_audioFlipChannels: " << m_config.m_audioFlipChannels
<< " m_dsb: " << m_config.m_dsb
<< " m_audioMute: " << m_config.m_audioMute
<< " m_playLoop: " << m_config.m_playLoop
<< " m_agc: " << m_config.m_agc
<< " m_agcTime: " << m_config.m_agcTime
<< " m_agcOrder: " << m_config.m_agcOrder
<< " m_agcThresholdEnable: " << m_config.m_agcThresholdEnable
<< " m_agcThreshold: " << m_config.m_agcThreshold
<< " m_agcThresholdGate: " << m_config.m_agcThresholdGate
<< " m_agcThresholdDelay: " << m_config.m_agcThresholdDelay;
return true;
}
return true;
}
else if (MsgConfigureFileSourceName::match(cmd))
{
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd;
@ -695,115 +640,6 @@ bool SSBMod::handleMessage(const Message& cmd)
}
}
void SSBMod::apply()
{
if ((m_config.m_bandwidth != m_running.m_bandwidth) ||
(m_config.m_lowCutoff != m_running.m_lowCutoff) ||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate))
{
m_settingsMutex.lock();
m_SSBFilter->create_filter(m_config.m_lowCutoff / m_config.m_audioSampleRate, m_config.m_bandwidth / m_config.m_audioSampleRate);
m_DSBFilter->create_dsb_filter((2.0f * m_config.m_bandwidth) / m_config.m_audioSampleRate);
m_settingsMutex.unlock();
}
if ((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) ||
(m_config.m_outputSampleRate != m_running.m_outputSampleRate))
{
m_settingsMutex.lock();
m_carrierNco.setFreq(m_config.m_inputFrequencyOffset, m_config.m_outputSampleRate);
m_settingsMutex.unlock();
}
if((m_config.m_outputSampleRate != m_running.m_outputSampleRate) ||
(m_config.m_bandwidth != m_running.m_bandwidth) ||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate))
{
m_settingsMutex.lock();
m_interpolatorDistanceRemain = 0;
m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) m_config.m_audioSampleRate / (Real) m_config.m_outputSampleRate;
m_interpolator.create(48, m_config.m_audioSampleRate, m_config.m_bandwidth, 3.0);
m_settingsMutex.unlock();
}
if ((m_config.m_toneFrequency != m_running.m_toneFrequency) ||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate))
{
m_settingsMutex.lock();
m_toneNco.setFreq(m_config.m_toneFrequency, m_config.m_audioSampleRate);
m_settingsMutex.unlock();
}
if (m_config.m_audioSampleRate != m_running.m_audioSampleRate)
{
m_settingsMutex.lock();
m_cwKeyer.setSampleRate(m_config.m_audioSampleRate);
m_settingsMutex.unlock();
}
if (m_config.m_dsb != m_running.m_dsb)
{
if (m_config.m_dsb)
{
memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
m_DSBFilterBufferIndex = 0;
}
else
{
memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
m_SSBFilterBufferIndex = 0;
}
}
if ((m_config.m_agcTime != m_running.m_agcTime) || (m_config.m_agcOrder != m_running.m_agcOrder))
{
m_inAGC.resize(m_config.m_agcTime, m_config.m_agcOrder);
}
if (m_config.m_agcThresholdEnable != m_running.m_agcThresholdEnable)
{
m_inAGC.setThresholdEnable(m_config.m_agcThresholdEnable);
}
if (m_config.m_agcThreshold != m_running.m_agcThreshold)
{
m_inAGC.setThreshold(m_config.m_agcThreshold);
}
if (m_config.m_agcThresholdGate != m_running.m_agcThresholdGate)
{
m_inAGC.setGate(m_config.m_agcThresholdGate);
}
if (m_config.m_agcThresholdDelay != m_running.m_agcThresholdDelay)
{
m_inAGC.setStepDownDelay(m_config.m_agcThresholdDelay);
}
m_running.m_outputSampleRate = m_config.m_outputSampleRate;
m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset;
m_running.m_bandwidth = m_config.m_bandwidth;
m_running.m_lowCutoff = m_config.m_lowCutoff;
m_running.m_usb = m_config.m_usb;
m_running.m_toneFrequency = m_config.m_toneFrequency;
m_running.m_volumeFactor = m_config.m_volumeFactor;
m_running.m_audioSampleRate = m_config.m_audioSampleRate;
m_running.m_spanLog2 = m_config.m_spanLog2;
m_running.m_audioBinaural = m_config.m_audioBinaural;
m_running.m_audioFlipChannels = m_config.m_audioFlipChannels;
m_running.m_dsb = m_config.m_dsb;
m_running.m_audioMute = m_config.m_audioMute;
m_running.m_playLoop = m_config.m_playLoop;
m_running.m_agc = m_config.m_agc;
m_running.m_agcOrder = m_config.m_agcOrder;
m_running.m_agcTime = m_config.m_agcTime;
m_running.m_agcThresholdEnable = m_config.m_agcThresholdEnable;
m_running.m_agcThreshold = m_config.m_agcThreshold;
m_running.m_agcThresholdGate = m_config.m_agcThresholdGate;
m_running.m_agcThresholdDelay = m_config.m_agcThresholdDelay;
}
void SSBMod::openFileStream()
{
if (m_ifstream.is_open()) {
@ -838,3 +674,93 @@ void SSBMod::seekFileStream(int seekPercentage)
m_ifstream.seekg(seekPoint, std::ios::beg);
}
}
void SSBMod::applySettings(const SSBModSettings& settings, bool force)
{
if ((settings.m_bandwidth != m_settings.m_bandwidth) ||
(settings.m_lowCutoff != m_settings.m_lowCutoff) ||
(settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
{
m_settingsMutex.lock();
m_SSBFilter->create_filter(settings.m_lowCutoff / settings.m_audioSampleRate, settings.m_bandwidth / settings.m_audioSampleRate);
m_DSBFilter->create_dsb_filter((2.0f * settings.m_bandwidth) / settings.m_audioSampleRate);
m_settingsMutex.unlock();
}
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) ||
(settings.m_outputSampleRate != m_settings.m_outputSampleRate) || force)
{
m_settingsMutex.lock();
m_carrierNco.setFreq(settings.m_inputFrequencyOffset, settings.m_outputSampleRate);
m_settingsMutex.unlock();
}
if((settings.m_outputSampleRate != m_settings.m_outputSampleRate) ||
(settings.m_bandwidth != m_settings.m_bandwidth) ||
(settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
{
m_settingsMutex.lock();
m_interpolatorDistanceRemain = 0;
m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) settings.m_audioSampleRate / (Real) settings.m_outputSampleRate;
m_interpolator.create(48, settings.m_audioSampleRate, settings.m_bandwidth, 3.0);
m_settingsMutex.unlock();
}
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) ||
(settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
{
m_settingsMutex.lock();
m_toneNco.setFreq(settings.m_toneFrequency, settings.m_audioSampleRate);
m_settingsMutex.unlock();
}
if ((settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
{
m_settingsMutex.lock();
m_cwKeyer.setSampleRate(settings.m_audioSampleRate);
m_settingsMutex.unlock();
}
if ((settings.m_dsb != m_settings.m_dsb) || force)
{
if (settings.m_dsb)
{
memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen));
m_DSBFilterBufferIndex = 0;
}
else
{
memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
m_SSBFilterBufferIndex = 0;
}
}
if ((settings.m_agcTime != m_settings.m_agcTime) ||
(settings.m_agcOrder != m_settings.m_agcOrder) || force)
{
m_inAGC.resize(settings.m_agcTime, settings.m_agcOrder);
}
if ((settings.m_agcThresholdEnable != m_settings.m_agcThresholdEnable) || force)
{
m_inAGC.setThresholdEnable(settings.m_agcThresholdEnable);
}
if ((settings.m_agcThreshold != m_settings.m_agcThreshold) || force)
{
m_inAGC.setThreshold(settings.m_agcThreshold);
}
if ((settings.m_agcThresholdGate != m_settings.m_agcThresholdGate) || force)
{
m_inAGC.setGate(settings.m_agcThresholdGate);
}
if ((settings.m_agcThresholdDelay != m_settings.m_agcThresholdDelay) || force)
{
m_inAGC.setStepDownDelay(settings.m_agcThresholdDelay);
}
m_settings = settings;
}

View File

@ -33,6 +33,8 @@
#include "audio/audiofifo.h"
#include "util/message.h"
#include "ssbmodsettings.h"
class SSBMod : public BasebandSampleSource {
Q_OBJECT
@ -46,6 +48,52 @@ public:
SSBModInputCWTone
} SSBModInputAF;
class MsgConfigureSSBMod : public Message {
MESSAGE_CLASS_DECLARATION
public:
const SSBModSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureSSBMod* create(const SSBModSettings& settings, bool force)
{
return new MsgConfigureSSBMod(settings, force);
}
private:
SSBModSettings m_settings;
bool m_force;
MsgConfigureSSBMod(const SSBModSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgConfigureChannelizer : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getSampleRate() const { return m_sampleRate; }
int getCenterFrequency() const { return m_centerFrequency; }
static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency)
{
return new MsgConfigureChannelizer(sampleRate, centerFrequency);
}
private:
int m_sampleRate;
int m_centerFrequency;
MsgConfigureChannelizer(int sampleRate, int centerFrequency) :
Message(),
m_sampleRate(sampleRate),
m_centerFrequency(centerFrequency)
{ }
};
class MsgConfigureFileSourceName : public Message
{
MESSAGE_CLASS_DECLARATION
@ -177,24 +225,6 @@ public:
SSBMod(BasebandSampleSink* sampleSink);
~SSBMod();
void configure(MessageQueue* messageQueue,
Real bandwidth,
Real lowCutoff,
float toneFrequency,
float volumeFactor,
int spanLog2,
bool audioBinaural,
bool audioFlipChannels,
bool dsb,
bool audioMute,
bool playLoop,
bool agc,
float agcOrder,
int agcTime,
int agcThreshold,
int agcThresholdGate,
int agcThresholdDelay);
virtual void pull(Sample& sample);
virtual void pullAudio(int nbSamples);
virtual void start();
@ -216,178 +246,12 @@ signals:
private:
class MsgConfigureSSBMod : public Message
{
MESSAGE_CLASS_DECLARATION
public:
Real getBandwidth() const { return m_bandwidth; }
Real getLowCutoff() const { return m_lowCutoff; }
float getToneFrequency() const { return m_toneFrequency; }
float getVolumeFactor() const { return m_volumeFactor; }
int getSpanLog2() const { return m_spanLog2; }
bool getAudioBinaural() const { return m_audioBinaural; }
bool getAudioFlipChannels() const { return m_audioFlipChannels; }
bool getDSB() const { return m_dsb; }
bool getAudioMute() const { return m_audioMute; }
bool getPlayLoop() const { return m_playLoop; }
bool getAGC() const { return m_agc; }
float getAGCOrder() const { return m_agcOrder; }
int getAGCTime() const { return m_agcTime; }
int getAGCThreshold() const { return m_agcThreshold; }
int getAGCThresholdGate() const { return m_agcThresholdGate; }
int getAGCThresholdDelay() const { return m_agcThresholdDelay; }
static MsgConfigureSSBMod* create(Real bandwidth,
Real lowCutoff,
float toneFrequency,
float volumeFactor,
int spanLog2,
bool audioBinaural,
bool audioFlipChannels,
bool dsb,
bool audioMute,
bool playLoop,
bool agc,
float agcOrder,
int agcTime,
int agcThreshold,
int agcThresholdGate,
int agcThresholdDelay)
{
return new MsgConfigureSSBMod(bandwidth,
lowCutoff,
toneFrequency,
volumeFactor,
spanLog2,
audioBinaural,
audioFlipChannels,
dsb,
audioMute,
playLoop,
agc,
agcOrder,
agcTime,
agcThreshold,
agcThresholdGate,
agcThresholdDelay);
}
private:
Real m_bandwidth;
Real m_lowCutoff;
float m_toneFrequency;
float m_volumeFactor;
int m_spanLog2;
bool m_audioBinaural;
bool m_audioFlipChannels;
bool m_dsb;
bool m_audioMute;
bool m_playLoop;
bool m_agc;
float m_agcOrder;
int m_agcTime;
int m_agcThreshold;
int m_agcThresholdGate;
int m_agcThresholdDelay;
MsgConfigureSSBMod(Real bandwidth,
Real lowCutoff,
float toneFrequency,
float volumeFactor,
int spanLog2,
bool audioBinaural,
bool audioFlipChannels,
bool dsb,
bool audioMute,
bool playLoop,
bool agc,
float agcOrder,
int agcTime,
int agcThreshold,
int agcThresholdGate,
int agcThresholdDelay) :
Message(),
m_bandwidth(bandwidth),
m_lowCutoff(lowCutoff),
m_toneFrequency(toneFrequency),
m_volumeFactor(volumeFactor),
m_spanLog2(spanLog2),
m_audioBinaural(audioBinaural),
m_audioFlipChannels(audioFlipChannels),
m_dsb(dsb),
m_audioMute(audioMute),
m_playLoop(playLoop),
m_agc(agc),
m_agcOrder(agcOrder),
m_agcTime(agcTime),
m_agcThreshold(agcThreshold),
m_agcThresholdGate(agcThresholdGate),
m_agcThresholdDelay(agcThresholdDelay)
{ }
};
//=================================================================
enum RateState {
RSInitialFill,
RSRunning
};
struct Config {
int m_basebandSampleRate;
int m_outputSampleRate;
qint64 m_inputFrequencyOffset;
Real m_bandwidth;
Real m_lowCutoff;
bool m_usb;
float m_toneFrequency;
float m_volumeFactor;
quint32 m_audioSampleRate;
int m_spanLog2;
bool m_audioBinaural;
bool m_audioFlipChannels;
bool m_dsb;
bool m_audioMute;
bool m_playLoop;
bool m_agc;
float m_agcOrder;
int m_agcTime;
bool m_agcThresholdEnable;
double m_agcThreshold;
int m_agcThresholdGate;
int m_agcThresholdDelay;
Config() :
m_basebandSampleRate(0),
m_outputSampleRate(0),
m_inputFrequencyOffset(0),
m_bandwidth(3000.0f),
m_lowCutoff(300.0f),
m_usb(true),
m_toneFrequency(1000.0f),
m_volumeFactor(1.0f),
m_audioSampleRate(0),
m_spanLog2(3),
m_audioBinaural(false),
m_audioFlipChannels(false),
m_dsb(false),
m_audioMute(false),
m_playLoop(false),
m_agc(false),
m_agcOrder(0.2),
m_agcTime(9600),
m_agcThresholdEnable(true),
m_agcThreshold(1e-4),
m_agcThresholdGate(192),
m_agcThresholdDelay(2400)
{ }
};
//=================================================================
Config m_config;
Config m_running;
SSBModSettings m_settings;
NCOF m_carrierNco;
NCOF m_toneNco;
@ -407,10 +271,6 @@ private:
BasebandSampleSink* m_sampleSink;
SampleVector m_sampleBuffer;
// Real m_magsqSpectrum;
// Real m_magsqSum;
// Real m_magsqPeak;
// int m_magsqCount;
fftfilt::cmplx m_sum;
int m_undersampleCount;
int m_sumCount;
@ -440,7 +300,7 @@ private:
static const int m_levelNbSamples;
void apply();
void applySettings(const SSBModSettings& settings, bool force = false);
void pullAF(Complex& sample);
void calculateLevel(Complex& sample);
void modulateSample();

View File

@ -63,6 +63,7 @@ qint64 SSBModGUI::getCenterFrequency() const {
void SSBModGUI::setCenterFrequency(qint64 centerFrequency)
{
m_channelMarker.setCenterFrequency(centerFrequency);
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
applySettings();
}
@ -81,14 +82,14 @@ bool SSBModGUI::deserialize(const QByteArray& data)
if(m_settings.deserialize(data))
{
displaySettings();
applySettings(); // will have true
applySettings(true); // will have true
return true;
}
else
{
m_settings.resetToDefaults();
displaySettings();
applySettings(); // will have true
applySettings(true); // will have true
return false;
}
}
@ -478,7 +479,6 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
//m_channelMarker = new ChannelMarker(this);
m_channelMarker.setColor(Qt::green);
m_channelMarker.setBandwidth(m_rate);
m_channelMarker.setSidebands(ChannelMarker::usb);
@ -497,7 +497,7 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa
m_settings.setCWKeyerGUI(ui->cwKeyerGUI);
displaySettings();
applySettings();
applySettings(true);
setNewRate(m_settings.m_spanLog2);
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
@ -512,7 +512,6 @@ SSBModGUI::~SSBModGUI()
delete m_channelizer;
delete m_ssbMod;
delete m_spectrumVis;
//delete m_channelMarker;
delete ui;
}
@ -597,35 +596,16 @@ void SSBModGUI::blockApplySettings(bool block)
m_doApplySettings = !block;
}
void SSBModGUI::applySettings()
void SSBModGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
setTitleColor(m_channelMarker.getColor());
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
48000,
m_channelMarker.getCenterFrequency());
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
m_ssbMod->configure(m_ssbMod->getInputMessageQueue(),
m_settings.m_bandwidth,
m_settings.m_lowCutoff,
m_settings.m_toneFrequency,
m_settings.m_volumeFactor,
m_settings.m_spanLog2,
m_settings.m_audioBinaural,
m_settings.m_audioFlipChannels,
m_settings.m_dsb,
m_settings.m_audioMute,
m_settings.m_playLoop,
m_settings.m_agc,
m_settings.m_agcOrder,
m_settings.m_agcTime,
m_settings.m_agcThreshold,
m_settings.m_agcThresholdGate,
m_settings.m_agcThresholdDelay);
SSBMod::MsgConfigureSSBMod *msg = SSBMod::MsgConfigureSSBMod::create(m_settings, force);
m_ssbMod->getInputMessageQueue()->push(msg);
}
}

View File

@ -101,7 +101,6 @@ private:
bool m_basicSettingsShown;
bool m_doApplySettings;
int m_rate;
int m_spanLog2;
ThreadedBasebandSampleSource* m_threadedChannelizer;
UpChannelizer* m_channelizer;
@ -118,8 +117,6 @@ private:
SSBMod::SSBModInputAF m_modAFInput;
MessageQueue m_inputMessageQueue;
//static const int m_agcTimeConstant[]; //!< time constant index to value in ms
explicit SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* parent = NULL);
virtual ~SSBModGUI();
@ -127,7 +124,7 @@ private:
bool setNewRate(int spanLog2);
void blockApplySettings(bool block);
void applySettings();
void applySettings(bool force = false);
void displaySettings();
void displayAGCPowerThreshold();
void updateWithStreamData();