1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-06-25 05:25:27 -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" #include "util/db.h"
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureSSBMod, Message) MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureSSBMod, Message)
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureChannelizer, Message)
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureFileSourceName, Message) MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureFileSourceName, Message)
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureFileSourceSeek, Message) MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureFileSourceSeek, Message)
MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureAFInput, Message) MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureAFInput, Message)
@ -59,26 +60,16 @@ SSBMod::SSBMod(BasebandSampleSink* sampleSink) :
{ {
setObjectName("SSBMod"); 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_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_config.m_bandwidth) / m_config.m_audioSampleRate, 2 * 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_SSBFilterBuffer = new Complex[m_ssbFftLen>>1]; // filter returns data exactly half of its size
m_DSBFilterBuffer = new Complex[m_ssbFftLen]; m_DSBFilterBuffer = new Complex[m_ssbFftLen];
memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1)); memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1));
memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen)); 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_audioBuffer.resize(1<<14);
m_audioBufferFill = 0; 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.real(0.0f);
m_sum.imag(0.0f); m_sum.imag(0.0f);
m_undersampleCount = 0; m_undersampleCount = 0;
@ -87,18 +78,18 @@ SSBMod::SSBMod(BasebandSampleSink* sampleSink) :
m_movingAverage.resize(16, 0); m_movingAverage.resize(16, 0);
m_magsq = 0.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); DSPEngine::instance()->addAudioSource(&m_audioFifo);
// CW keyer // CW keyer
m_cwKeyer.setSampleRate(m_config.m_audioSampleRate); m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
m_cwKeyer.setWPM(13); m_cwKeyer.setWPM(13);
m_cwKeyer.setMode(CWKeyer::CWNone); m_cwKeyer.setMode(CWKeyer::CWNone);
m_inAGC.setGate(m_config.m_agcThresholdGate); m_inAGC.setGate(m_settings.m_agcThresholdGate);
m_inAGC.setStepDownDelay(m_config.m_agcThresholdDelay); m_inAGC.setStepDownDelay(m_settings.m_agcThresholdDelay);
m_inAGC.setClamping(true); m_inAGC.setClamping(true);
apply(); applySettings(m_settings, true);
} }
SSBMod::~SSBMod() SSBMod::~SSBMod()
@ -122,43 +113,6 @@ SSBMod::~SSBMod()
DSPEngine::instance()->removeAudioSource(&m_audioFifo); 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) void SSBMod::pull(Sample& sample)
{ {
Complex ci; Complex ci;
@ -200,7 +154,7 @@ void SSBMod::pull(Sample& sample)
void SSBMod::pullAudio(int nbSamples) 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()) if (nbSamplesAudio > m_audioBuffer.size())
{ {
@ -220,7 +174,7 @@ void SSBMod::modulateSample()
void SSBMod::pullAF(Complex& sample) void SSBMod::pullAF(Complex& sample)
{ {
if (m_running.m_audioMute) if (m_settings.m_audioMute)
{ {
sample.real(0.0f); sample.real(0.0f);
sample.imag(0.0f); sample.imag(0.0f);
@ -231,13 +185,13 @@ void SSBMod::pullAF(Complex& sample)
fftfilt::cmplx *filtered; fftfilt::cmplx *filtered;
int n_out = 0; 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) unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
switch (m_afInput) switch (m_afInput)
{ {
case SSBModInputTone: case SSBModInputTone:
if (m_running.m_dsb) if (m_settings.m_dsb)
{ {
Real t = m_toneNco.next()/1.25; Real t = m_toneNco.next()/1.25;
sample.real(t); sample.real(t);
@ -245,7 +199,7 @@ void SSBMod::pullAF(Complex& sample)
} }
else else
{ {
if (m_running.m_usb) { if (m_settings.m_usb) {
sample = m_toneNco.nextIQ(); sample = m_toneNco.nextIQ();
} else { } else {
sample = m_toneNco.nextQI(); sample = m_toneNco.nextQI();
@ -263,7 +217,7 @@ void SSBMod::pullAF(Complex& sample)
{ {
if (m_ifstream.eof()) if (m_ifstream.eof())
{ {
if (m_running.m_playLoop) if (m_settings.m_playLoop)
{ {
m_ifstream.clear(); m_ifstream.clear();
m_ifstream.seekg(0, std::ios::beg); m_ifstream.seekg(0, std::ios::beg);
@ -277,19 +231,19 @@ void SSBMod::pullAF(Complex& sample)
} }
else else
{ {
if (m_running.m_audioBinaural) if (m_settings.m_audioBinaural)
{ {
Complex c; Complex c;
m_ifstream.read(reinterpret_cast<char*>(&c), sizeof(Complex)); 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.real(c.imag() * m_settings.m_volumeFactor);
ci.imag(c.real() * m_running.m_volumeFactor); ci.imag(c.real() * m_settings.m_volumeFactor);
} }
else else
{ {
ci = c * m_running.m_volumeFactor; ci = c * m_settings.m_volumeFactor;
} }
} }
else else
@ -297,16 +251,16 @@ void SSBMod::pullAF(Complex& sample)
Real real; Real real;
m_ifstream.read(reinterpret_cast<char*>(&real), sizeof(Real)); m_ifstream.read(reinterpret_cast<char*>(&real), sizeof(Real));
if (m_running.m_agc) if (m_settings.m_agc)
{ {
ci.real(real); ci.real(real);
ci.imag(0.0f); ci.imag(0.0f);
m_inAGC.feed(ci); m_inAGC.feed(ci);
ci *= m_running.m_volumeFactor; ci *= m_settings.m_volumeFactor;
} }
else else
{ {
ci.real(real * m_running.m_volumeFactor); ci.real(real * m_settings.m_volumeFactor);
ci.imag(0.0f); ci.imag(0.0f);
} }
} }
@ -319,31 +273,31 @@ void SSBMod::pullAF(Complex& sample)
} }
break; break;
case SSBModInputAudio: 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.real((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_settings.m_volumeFactor);
ci.imag((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_running.m_volumeFactor); ci.imag((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_settings.m_volumeFactor);
} }
else else
{ {
ci.real((m_audioBuffer[m_audioBufferFill].l / 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_running.m_volumeFactor); ci.imag((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_settings.m_volumeFactor);
} }
} }
else 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.real(((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f));
ci.imag(0.0f); ci.imag(0.0f);
m_inAGC.feed(ci); m_inAGC.feed(ci);
ci *= m_running.m_volumeFactor; ci *= m_settings.m_volumeFactor;
} }
else 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); ci.imag(0.0f);
} }
} }
@ -356,7 +310,7 @@ void SSBMod::pullAF(Complex& sample)
{ {
m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor); m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
if (m_running.m_dsb) if (m_settings.m_dsb)
{ {
Real t = m_toneNco.next() * fadeFactor; Real t = m_toneNco.next() * fadeFactor;
sample.real(t); sample.real(t);
@ -364,7 +318,7 @@ void SSBMod::pullAF(Complex& sample)
} }
else else
{ {
if (m_running.m_usb) { if (m_settings.m_usb) {
sample = m_toneNco.nextIQ() * fadeFactor; sample = m_toneNco.nextIQ() * fadeFactor;
} else { } else {
sample = m_toneNco.nextQI() * fadeFactor; sample = m_toneNco.nextQI() * fadeFactor;
@ -375,7 +329,7 @@ void SSBMod::pullAF(Complex& sample)
{ {
if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor)) 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; Real t = (m_toneNco.next() * fadeFactor)/1.25;
sample.real(t); sample.real(t);
@ -383,7 +337,7 @@ void SSBMod::pullAF(Complex& sample)
} }
else else
{ {
if (m_running.m_usb) { if (m_settings.m_usb) {
sample = m_toneNco.nextIQ() * fadeFactor; sample = m_toneNco.nextIQ() * fadeFactor;
} else { } else {
sample = m_toneNco.nextQI() * fadeFactor; 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_afInput == SSBModInputFile) || (m_afInput == SSBModInputAudio)) // real audio
{ {
if (m_running.m_dsb) if (m_settings.m_dsb)
{ {
n_out = m_DSBFilter->runDSB(ci, &filtered); n_out = m_DSBFilter->runDSB(ci, &filtered);
@ -421,7 +375,7 @@ void SSBMod::pullAF(Complex& sample)
} }
else 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) if (n_out > 0)
{ {
@ -457,7 +411,7 @@ void SSBMod::pullAF(Complex& sample)
// //
// m_magsqCount++; // m_magsqCount++;
if (!m_running.m_dsb & !m_running.m_usb) if (!m_settings.m_dsb & !m_settings.m_usb)
{ // invert spectrum for LSB { // invert spectrum for LSB
m_sampleBuffer.push_back(Sample(avgi, avgr)); m_sampleBuffer.push_back(Sample(avgi, avgr));
} }
@ -491,7 +445,7 @@ void SSBMod::pullAF(Complex& sample)
// //
// m_magsqCount++; // m_magsqCount++;
if (!m_running.m_dsb & !m_running.m_usb) if (!m_settings.m_dsb & !m_settings.m_usb)
{ // invert spectrum for LSB { // invert spectrum for LSB
m_sampleBuffer.push_back(Sample(avgi, avgr)); m_sampleBuffer.push_back(Sample(avgi, avgr));
} }
@ -504,7 +458,7 @@ void SSBMod::pullAF(Complex& sample)
m_sum.imag(0.0); 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; n_out = 0;
m_sumCount++; m_sumCount++;
@ -520,7 +474,7 @@ void SSBMod::pullAF(Complex& sample)
{ {
if (m_sampleSink != 0) 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(); m_sampleBuffer.clear();
@ -550,8 +504,8 @@ void SSBMod::calculateLevel(Complex& sample)
void SSBMod::start() void SSBMod::start()
{ {
qDebug() << "SSBMod::start: m_outputSampleRate: " << m_config.m_outputSampleRate qDebug() << "SSBMod::start: m_outputSampleRate: " << m_settings.m_outputSampleRate
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; << " m_inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset;
m_audioFifo.clear(); m_audioFifo.clear();
} }
@ -566,91 +520,82 @@ bool SSBMod::handleMessage(const Message& cmd)
{ {
UpChannelizer::MsgChannelizerNotification& notif = (UpChannelizer::MsgChannelizerNotification&) cmd; UpChannelizer::MsgChannelizerNotification& notif = (UpChannelizer::MsgChannelizerNotification&) cmd;
m_config.m_basebandSampleRate = notif.getBasebandSampleRate(); SSBModSettings settings = m_settings;
m_config.m_outputSampleRate = notif.getSampleRate();
m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
apply(); settings.m_basebandSampleRate = notif.getBasebandSampleRate();
settings.m_outputSampleRate = notif.getSampleRate();
settings.m_inputFrequencyOffset = notif.getFrequencyOffset();
applySettings(settings);
qDebug() << "SSBMod::handleMessage: MsgChannelizerNotification:" qDebug() << "SSBMod::handleMessage: MsgChannelizerNotification:"
<< " m_basebandSampleRate: " << m_config.m_basebandSampleRate << " m_basebandSampleRate: " << settings.m_basebandSampleRate
<< " m_outputSampleRate: " << m_config.m_outputSampleRate << " m_outputSampleRate: " << settings.m_outputSampleRate
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset;
return true; return true;
} }
else if (MsgConfigureSSBMod::match(cmd)) else if (MsgConfigureSSBMod::match(cmd))
{ {
float band, lowCutoff; float band, lowCutoff;
MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd;
MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd; SSBModSettings settings = cfg.getSettings();
m_settingsMutex.lock();
band = cfg.getBandwidth(); // These settings are set with UpChannelizer::MsgChannelizerNotification
lowCutoff = cfg.getLowCutoff(); 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 = settings.m_bandwidth;
{ lowCutoff = settings.m_lowCutoff;
band = -band; // turn to positive
lowCutoff = -lowCutoff;
m_config.m_usb = false; // and take note of side band
}
else
{
m_config.m_usb = true;
}
if (band < 100.0f) // at least 100 Hz if (band < 0) // negative means LSB
{ {
band = 100.0f; band = -band; // turn to positive
lowCutoff = 0; lowCutoff = -lowCutoff;
} settings.m_usb = false; // and take note of side band
}
else
{
settings.m_usb = true;
}
m_config.m_bandwidth = band; if (band < 100.0f) // at least 100 Hz
m_config.m_lowCutoff = lowCutoff; {
band = 100.0f;
lowCutoff = 0;
}
m_config.m_toneFrequency = cfg.getToneFrequency(); settings.m_bandwidth = band;
m_config.m_volumeFactor = cfg.getVolumeFactor(); settings.m_lowCutoff = lowCutoff;
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();
m_config.m_agcTime = cfg.getAGCTime(); // ms applySettings(settings, cfg.getForce());
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
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(); return true;
}
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;
}
else if (MsgConfigureFileSourceName::match(cmd)) else if (MsgConfigureFileSourceName::match(cmd))
{ {
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) 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() void SSBMod::openFileStream()
{ {
if (m_ifstream.is_open()) { if (m_ifstream.is_open()) {
@ -838,3 +674,93 @@ void SSBMod::seekFileStream(int seekPercentage)
m_ifstream.seekg(seekPoint, std::ios::beg); 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 "audio/audiofifo.h"
#include "util/message.h" #include "util/message.h"
#include "ssbmodsettings.h"
class SSBMod : public BasebandSampleSource { class SSBMod : public BasebandSampleSource {
Q_OBJECT Q_OBJECT
@ -46,6 +48,52 @@ public:
SSBModInputCWTone SSBModInputCWTone
} SSBModInputAF; } 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 class MsgConfigureFileSourceName : public Message
{ {
MESSAGE_CLASS_DECLARATION MESSAGE_CLASS_DECLARATION
@ -177,24 +225,6 @@ public:
SSBMod(BasebandSampleSink* sampleSink); SSBMod(BasebandSampleSink* sampleSink);
~SSBMod(); ~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 pull(Sample& sample);
virtual void pullAudio(int nbSamples); virtual void pullAudio(int nbSamples);
virtual void start(); virtual void start();
@ -216,178 +246,12 @@ signals:
private: 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 { enum RateState {
RSInitialFill, RSInitialFill,
RSRunning RSRunning
}; };
struct Config { SSBModSettings m_settings;
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;
NCOF m_carrierNco; NCOF m_carrierNco;
NCOF m_toneNco; NCOF m_toneNco;
@ -407,10 +271,6 @@ private:
BasebandSampleSink* m_sampleSink; BasebandSampleSink* m_sampleSink;
SampleVector m_sampleBuffer; SampleVector m_sampleBuffer;
// Real m_magsqSpectrum;
// Real m_magsqSum;
// Real m_magsqPeak;
// int m_magsqCount;
fftfilt::cmplx m_sum; fftfilt::cmplx m_sum;
int m_undersampleCount; int m_undersampleCount;
int m_sumCount; int m_sumCount;
@ -440,7 +300,7 @@ private:
static const int m_levelNbSamples; static const int m_levelNbSamples;
void apply(); void applySettings(const SSBModSettings& settings, bool force = false);
void pullAF(Complex& sample); void pullAF(Complex& sample);
void calculateLevel(Complex& sample); void calculateLevel(Complex& sample);
void modulateSample(); void modulateSample();

View File

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

View File

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