diff --git a/plugins/channeltx/modssb/ssbmod.cpp b/plugins/channeltx/modssb/ssbmod.cpp index c21fa8d69..0ace158d7 100644 --- a/plugins/channeltx/modssb/ssbmod.cpp +++ b/plugins/channeltx/modssb/ssbmod.cpp @@ -50,7 +50,7 @@ SSBMod::SSBMod() : m_config.m_outputSampleRate = 48000; m_config.m_inputFrequencyOffset = 0; - m_config.m_rfBandwidth = 12500; + m_config.m_bandwidth = 12500; m_config.m_toneFrequency = 1000.0f; m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); @@ -78,13 +78,27 @@ SSBMod::~SSBMod() } void SSBMod::configure(MessageQueue* messageQueue, - Real rfBandwidth, + Real bandwidth, + Real lowCutoff, float toneFrequency, float volumeFactor, + int spanLog2, + bool audioBinaural, + bool audioFlipChannels, + bool dsb, bool audioMute, bool playLoop) { - Message* cmd = MsgConfigureSSBMod::create(rfBandwidth, toneFrequency, volumeFactor, audioMute, playLoop); + Message* cmd = MsgConfigureSSBMod::create(bandwidth, + lowCutoff, + toneFrequency, + volumeFactor, + spanLog2, + audioBinaural, + audioFlipChannels, + dsb, + audioMute, + playLoop); messageQueue->push(cmd); } @@ -247,20 +261,60 @@ bool SSBMod::handleMessage(const Message& cmd) } else if (MsgConfigureSSBMod::match(cmd)) { - MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd; + float band, lowCutoff; + + MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd; + m_settingsMutex.lock(); + + band = cfg.getBandwidth(); + lowCutoff = cfg.getLoCutoff(); + + 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; + } + + if (band < 100.0f) // at least 100 Hz + { + band = 100.0f; + lowCutoff = 0; + } + + m_config.m_bandwidth = band; + m_config.m_lowCutoff = lowCutoff; + + // TODO: move to apply + SSBFilter->create_filter(m_config.m_lowCutoff / (float) m_config.m_audioSampleRate, m_config.m_bandwidth / (float) m_config.m_audioSampleRate); + DSBFilter->create_dsb_filter((2.0f * m_config.m_bandwidth) / (float) m_config.m_audioSampleRate); - m_config.m_rfBandwidth = cfg.getRFBandwidth(); 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(); apply(); + m_settingsMutex.unlock(); + qDebug() << "SSBMod::handleMessage: MsgConfigureSSBMod:" - << " m_rfBandwidth: " << m_config.m_rfBandwidth + << " 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; @@ -322,14 +376,14 @@ void SSBMod::apply() } if((m_config.m_outputSampleRate != m_running.m_outputSampleRate) || - (m_config.m_rfBandwidth != m_running.m_rfBandwidth) || + (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_rfBandwidth / 2.2, 3.0); + m_interpolator.create(48, m_config.m_audioSampleRate, m_config.m_bandwidth / 2.2, 3.0); m_settingsMutex.unlock(); } @@ -348,10 +402,15 @@ void SSBMod::apply() m_running.m_outputSampleRate = m_config.m_outputSampleRate; m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset; - m_running.m_rfBandwidth = m_config.m_rfBandwidth; + m_running.m_bandwidth = m_config.m_bandwidth; + m_running.m_lowCutoff = m_config.m_lowCutoff; 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; } diff --git a/plugins/channeltx/modssb/ssbmod.h b/plugins/channeltx/modssb/ssbmod.h index 787823a71..41a7a5cdc 100644 --- a/plugins/channeltx/modssb/ssbmod.h +++ b/plugins/channeltx/modssb/ssbmod.h @@ -27,6 +27,7 @@ #include "dsp/interpolator.h" #include "dsp/movingaverage.h" #include "dsp/agc.h" +#include "dsp/fftfilt.h" #include "dsp/cwkeyer.h" #include "audio/audiofifo.h" #include "util/message.h" @@ -176,10 +177,15 @@ public: ~SSBMod(); void configure(MessageQueue* messageQueue, - Real rfBandwidth, + Real bandwidth, + Real lowCutoff, float toneFrequency, float volumeFactor, - bool audioMute, + int spanLog2, + bool audioBinaural, + bool audioFlipChannels, + bool dsb, + bool audioMute, bool playLoop); virtual void pull(Sample& sample); @@ -207,29 +213,71 @@ private: MESSAGE_CLASS_DECLARATION public: - Real getRFBandwidth() const { return m_rfBandwidth; } + 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; } - static MsgConfigureSSBMod* create(Real rfBandwidth, float toneFreqeuncy, float volumeFactor, bool audioMute, bool playLoop) + static MsgConfigureSSBMod* create(Real bandwidth, + Real lowCutoff, + float toneFrequency, + float volumeFactor, + int spanLog2, + bool audioBinaural, + bool audioFlipChannels, + bool dsb, + bool audioMute, + bool playLoop) { - return new MsgConfigureSSBMod(rfBandwidth, toneFreqeuncy, volumeFactor, audioMute, playLoop); + return new MsgConfigureSSBMod(bandwidth, + lowCutoff, + toneFrequency, + volumeFactor, + spanLog2, + audioBinaural, + audioFlipChannels, + dsb, + audioMute, + playLoop); } private: - Real m_rfBandwidth; + 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; - MsgConfigureSSBMod(Real rfBandwidth, float toneFrequency, float volumeFactor, bool audioMute, bool playLoop) : + MsgConfigureSSBMod(Real bandwidth, + Real lowCutoff, + float toneFrequency, + float volumeFactor, + int spanLog2, + bool audioBinaural, + bool audioFlipChannels, + bool dsb, + bool audioMute, + bool playLoop) : Message(), - m_rfBandwidth(rfBandwidth), + 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) { } @@ -251,20 +299,32 @@ private: struct Config { int m_outputSampleRate; qint64 m_inputFrequencyOffset; - Real m_rfBandwidth; + Real m_bandwidth; + Real m_lowCutoff; + bool m_usb; float m_toneFrequency; float m_volumeFactor; quint32 m_audioSampleRate; - bool m_audioMute; + int m_spanLog2; + bool m_audioBinaural; + bool m_audioFlipChannels; + bool m_dsb; + bool m_audioMute; bool m_playLoop; Config() : - m_outputSampleRate(-1), + m_outputSampleRate(0), m_inputFrequencyOffset(0), - m_rfBandwidth(-1), - m_toneFrequency(100), + 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) { } @@ -282,6 +342,8 @@ private: Real m_interpolatorDistance; Real m_interpolatorDistanceRemain; bool m_interpolatorConsumed; + fftfilt* SSBFilter; + fftfilt* DSBFilter; Real m_magsq; MovingAverage m_movingAverage; diff --git a/plugins/channeltx/modssb/ssbmodgui.cpp b/plugins/channeltx/modssb/ssbmodgui.cpp index e31035919..fafb87f78 100644 --- a/plugins/channeltx/modssb/ssbmodgui.cpp +++ b/plugins/channeltx/modssb/ssbmodgui.cpp @@ -73,14 +73,21 @@ void SSBModGUI::resetToDefaults() ui->BW->setValue(30); ui->lowCut->setValue(3); ui->spanLog2->setValue(3); + m_spanLog2 = 3; ui->toneFrequency->setValue(100); ui->deltaFrequency->setValue(0); - m_audioBinaural = false; - m_audioFlipChannels = false; - m_dsb = false; + ui->audioBinaural->setChecked(false); + ui->audioFlipChannels->setChecked(false); + ui->dsb->setChecked(false); + ui->audioMute->setChecked(false); + + ui->play->setEnabled(false); + ui->play->setChecked(false); + ui->tone->setChecked(false); + ui->morseKeyer->setChecked(false); + ui->mic->setChecked(false); blockApplySettings(false); - applySettings(); } QByteArray SSBModGUI::serialize() const @@ -95,9 +102,9 @@ QByteArray SSBModGUI::serialize() const s.writeBlob(6, ui->cwKeyerGUI->serialize()); s.writeS32(7, ui->lowCut->value()); s.writeS32(8, ui->spanLog2->value()); - s.writeBool(9, m_audioBinaural); - s.writeBool(10, m_audioFlipChannels); - s.writeBool(11, m_dsb); + s.writeBool(9, ui->audioBinaural->isChecked()); + s.writeBool(10, ui->audioFlipChannels->isChecked()); + s.writeBool(11, ui->dsb->isChecked()); return s.final(); } @@ -109,6 +116,7 @@ bool SSBModGUI::deserialize(const QByteArray& data) if(!d.isValid()) { resetToDefaults(); + applySettings(); return false; } @@ -117,13 +125,14 @@ bool SSBModGUI::deserialize(const QByteArray& data) QByteArray bytetmp; quint32 u32tmp; qint32 tmp; + bool booltmp; blockApplySettings(true); m_channelMarker.blockSignals(true); d.readS32(1, &tmp, 0); m_channelMarker.setCenterFrequency(tmp); - d.readS32(2, &tmp, 4); + d.readS32(2, &tmp, 30); ui->BW->setValue(tmp); d.readS32(3, &tmp, 100); ui->toneFrequency->setValue(tmp); @@ -140,15 +149,15 @@ bool SSBModGUI::deserialize(const QByteArray& data) d.readS32(7, &tmp, 3); ui->lowCut->setValue(tmp); - d.readS32(8, &tmp, 20); + d.readS32(8, &tmp, 3); ui->spanLog2->setValue(tmp); setNewRate(tmp); - d.readBool(9, &m_audioBinaural); - ui->audioBinaural->setChecked(m_audioBinaural); - d.readBool(10, &m_audioFlipChannels); - ui->audioFlipChannels->setChecked(m_audioFlipChannels); - d.readBool(11, &m_dsb); - ui->dsb->setChecked(m_dsb); + d.readBool(9, &booltmp); + ui->audioBinaural->setChecked(booltmp); + d.readBool(10, &booltmp); + ui->audioFlipChannels->setChecked(booltmp); + d.readBool(11, &booltmp); + ui->dsb->setChecked(booltmp); blockApplySettings(false); m_channelMarker.blockSignals(false); @@ -159,6 +168,7 @@ bool SSBModGUI::deserialize(const QByteArray& data) else { resetToDefaults(); + applySettings(); return false; } } @@ -370,6 +380,8 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa //m_pluginAPI->addThreadedSink(m_threadedChannelizer); m_deviceAPI->addThreadedSource(m_threadedChannelizer); + resetToDefaults(); + ui->glSpectrum->setCenterFrequency(m_rate/2); ui->glSpectrum->setSampleRate(m_rate); ui->glSpectrum->setDisplayWaterfall(true); @@ -394,12 +406,6 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa m_deviceAPI->addChannelMarker(&m_channelMarker); m_deviceAPI->addRollupWidget(this); - ui->play->setEnabled(false); - ui->play->setChecked(false); - ui->tone->setChecked(false); - ui->morseKeyer->setChecked(false); - ui->mic->setChecked(false); - ui->cwKeyerGUI->setBuddies(m_ssbMod->getInputMessageQueue(), m_ssbMod->getCWKeyer()); applySettings(); @@ -462,7 +468,7 @@ bool SSBModGUI::setNewRate(int spanLog2) //ui->glSpectrum->setCenterFrequency(m_rate/2); //ui->glSpectrum->setSampleRate(m_rate); - if (!m_dsb) + if (!ui->dsb->isChecked()) { if (ui->BW->value() < 0) { m_channelMarker.setSidebands(ChannelMarker::lsb); @@ -505,9 +511,14 @@ void SSBModGUI::applySettings() ui->deltaMinus->setChecked(m_channelMarker.getCenterFrequency() < 0); m_ssbMod->configure(m_ssbMod->getInputMessageQueue(), - ui->BW->value() * 100.0, + ui->BW->value() * 100.0f, + ui->lowCut->value() * 100.0f, ui->toneFrequency->value() * 10.0f, - ui->volume->value() / 10.0f , + ui->volume->value() / 10.0f, + m_spanLog2, + ui->audioBinaural->isChecked(), + ui->audioFlipChannels->isChecked(), + ui->dsb->isChecked(), ui->audioMute->isChecked(), ui->playLoop->isChecked()); } diff --git a/plugins/channeltx/modssb/ssbmodgui.h b/plugins/channeltx/modssb/ssbmodgui.h index f0c0e6a51..418245ca6 100644 --- a/plugins/channeltx/modssb/ssbmodgui.h +++ b/plugins/channeltx/modssb/ssbmodgui.h @@ -102,10 +102,6 @@ private: bool m_enableNavTime; SSBMod::SSBModInputAF m_modAFInput; - bool m_audioBinaural; - bool m_audioFlipChannels; - bool m_dsb; - explicit SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* parent = NULL); virtual ~SSBModGUI();