Make the low cutoff frequency of the SSB filter variable. Change spectrum overlay accordingly.

This commit is contained in:
f4exb 2015-05-12 21:50:02 +02:00
parent e15f4f26f1
commit d395ba24c7
10 changed files with 253 additions and 128 deletions

View File

@ -78,7 +78,8 @@ Done since the fork
- SSB bandwidth can now be tuned in steps of 100 Hz - SSB bandwidth can now be tuned in steps of 100 Hz
- NFM and SSB receiver in focus trigger the display of the central frequency line on the spectrum frequency scale thus facilitating its identification - NFM and SSB receiver in focus trigger the display of the central frequency line on the spectrum frequency scale thus facilitating its identification
- Added AM demod so now you can listen to air traffic! - Added AM demod so now you can listen to air traffic!
- Added the possibility to change the brightness and/or color of the grid. - Added the possibility to change the brightness and/or color of the grid.
- Make the low cutoff frequency of the SSB filter variable so it can be used for CW also.
===== =====
To Do To Do

View File

@ -54,11 +54,13 @@ private:
struct ChannelMarkerState { struct ChannelMarkerState {
ChannelMarker* m_channelMarker; ChannelMarker* m_channelMarker;
QRectF m_glRect; QRectF m_glRect;
QRectF m_glRectDsb;
QRect m_rect; QRect m_rect;
ChannelMarkerState(ChannelMarker* channelMarker) : ChannelMarkerState(ChannelMarker* channelMarker) :
m_channelMarker(channelMarker), m_channelMarker(channelMarker),
m_glRect() m_glRect(),
m_glRectDsb()
{ } { }
}; };
QList<ChannelMarkerState*> m_channelMarkerStates; QList<ChannelMarkerState*> m_channelMarkerStates;
@ -150,8 +152,6 @@ private:
void enterEvent(QEvent* event); void enterEvent(QEvent* event);
void leaveEvent(QEvent* event); void leaveEvent(QEvent* event);
float getCenterFreqLineRelPos(ChannelMarker *channelMarker);
private slots: private slots:
void tick(); void tick();
void channelMarkerChanged(); void channelMarkerChanged();

View File

@ -27,6 +27,9 @@ public:
void setBandwidth(int bandwidth); void setBandwidth(int bandwidth);
int getBandwidth() const { return m_bandwidth; } int getBandwidth() const { return m_bandwidth; }
void setLowCutoff(int lowCutoff);
int getLowCutoff() const { return m_lowCutoff; }
void setSidebands(sidebands_t sidebands); void setSidebands(sidebands_t sidebands);
sidebands_t getSidebands() const { return m_sidebands; } sidebands_t getSidebands() const { return m_sidebands; }
@ -46,6 +49,7 @@ protected:
QString m_title; QString m_title;
int m_centerFrequency; int m_centerFrequency;
int m_bandwidth; int m_bandwidth;
int m_lowCutoff;
sidebands_t m_sidebands; sidebands_t m_sidebands;
bool m_visible; bool m_visible;
bool m_highlighted; bool m_highlighted;

View File

@ -22,6 +22,8 @@
#include "audio/audiooutput.h" #include "audio/audiooutput.h"
#include "dsp/dspcommands.h" #include "dsp/dspcommands.h"
#include <iostream>
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message) MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message)
SSBDemod::SSBDemod(AudioFifo* audioFifo, SampleSink* sampleSink) : SSBDemod::SSBDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
@ -29,6 +31,7 @@ SSBDemod::SSBDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
m_audioFifo(audioFifo) m_audioFifo(audioFifo)
{ {
m_Bandwidth = 5000; m_Bandwidth = 5000;
m_LowCutoff = 300;
m_volume = 2.0; m_volume = 2.0;
m_sampleRate = 96000; m_sampleRate = 96000;
m_frequency = 0; m_frequency = 0;
@ -41,7 +44,7 @@ SSBDemod::SSBDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
m_undersampleCount = 0; m_undersampleCount = 0;
m_usb = true; m_usb = true;
SSBFilter = new fftfilt(0.01, m_Bandwidth / 48000.0, ssbFftLen); SSBFilter = new fftfilt(m_LowCutoff / 48000.0, m_Bandwidth / 48000.0, ssbFftLen);
// if (!USBFilter) segfault; // if (!USBFilter) segfault;
} }
@ -50,9 +53,9 @@ SSBDemod::~SSBDemod()
if (SSBFilter) delete SSBFilter; if (SSBFilter) delete SSBFilter;
} }
void SSBDemod::configure(MessageQueue* messageQueue, Real Bandwidth, Real volume) void SSBDemod::configure(MessageQueue* messageQueue, Real Bandwidth, Real LowCutoff, Real volume)
{ {
Message* cmd = MsgConfigureSSBDemod::create(Bandwidth, volume); Message* cmd = MsgConfigureSSBDemod::create(Bandwidth, LowCutoff, volume);
cmd->submit(messageQueue, this); cmd->submit(messageQueue, this);
} }
@ -110,7 +113,7 @@ void SSBDemod::stop()
bool SSBDemod::handleMessage(Message* cmd) bool SSBDemod::handleMessage(Message* cmd)
{ {
float band; float band, lowCutoff;
if(DSPSignalNotification::match(cmd)) { if(DSPSignalNotification::match(cmd)) {
DSPSignalNotification* signal = (DSPSignalNotification*)cmd; DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
@ -125,17 +128,26 @@ bool SSBDemod::handleMessage(Message* cmd)
MsgConfigureSSBDemod* cfg = (MsgConfigureSSBDemod*)cmd; MsgConfigureSSBDemod* cfg = (MsgConfigureSSBDemod*)cmd;
band = cfg->getBandwidth(); band = cfg->getBandwidth();
lowCutoff = cfg->getLoCutoff();
if (band < 0) { if (band < 0) {
band = -band; band = -band;
lowCutoff = -lowCutoff;
m_usb = false; m_usb = false;
} else } else
m_usb = true; m_usb = true;
if (band < 500.0f)
band = 500.0f; if (band < 100.0f)
{
band = 100.0f;
lowCutoff = 0;
}
m_Bandwidth = band; m_Bandwidth = band;
m_LowCutoff = lowCutoff;
m_interpolator.create(16, m_sampleRate, band * 2.0f); m_interpolator.create(16, m_sampleRate, band * 2.0f);
SSBFilter->create_filter(0.3f / 48.0f, m_Bandwidth / 48000.0f); SSBFilter->create_filter(m_LowCutoff / 48000.0f, m_Bandwidth / 48000.0f);
m_volume = cfg->getVolume(); m_volume = cfg->getVolume();
m_volume *= m_volume * 0.1; m_volume *= m_volume * 0.1;

View File

@ -35,7 +35,7 @@ public:
SSBDemod(AudioFifo* audioFifo, SampleSink* sampleSink); SSBDemod(AudioFifo* audioFifo, SampleSink* sampleSink);
~SSBDemod(); ~SSBDemod();
void configure(MessageQueue* messageQueue, Real Bandwidth, Real volume); void configure(MessageQueue* messageQueue, Real Bandwidth, Real LowCutoff, Real volume);
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly); void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void start(); void start();
@ -48,20 +48,23 @@ private:
public: public:
Real getBandwidth() const { return m_Bandwidth; } Real getBandwidth() const { return m_Bandwidth; }
Real getLoCutoff() const { return m_LowCutoff; }
Real getVolume() const { return m_volume; } Real getVolume() const { return m_volume; }
static MsgConfigureSSBDemod* create(Real Bandwidth, Real volume) static MsgConfigureSSBDemod* create(Real Bandwidth, Real LowCutoff, Real volume)
{ {
return new MsgConfigureSSBDemod(Bandwidth, volume); return new MsgConfigureSSBDemod(Bandwidth, LowCutoff, volume);
} }
private: private:
Real m_Bandwidth; Real m_Bandwidth;
Real m_LowCutoff;
Real m_volume; Real m_volume;
MsgConfigureSSBDemod(Real Bandwidth, Real volume) : MsgConfigureSSBDemod(Real Bandwidth, Real LowCutoff, Real volume) :
Message(), Message(),
m_Bandwidth(Bandwidth), m_Bandwidth(Bandwidth),
m_LowCutoff(LowCutoff),
m_volume(volume) m_volume(volume)
{ } { }
}; };
@ -73,6 +76,7 @@ private:
typedef std::vector<AudioSample> AudioVector; typedef std::vector<AudioSample> AudioVector;
Real m_Bandwidth; Real m_Bandwidth;
Real m_LowCutoff;
Real m_volume; Real m_volume;
int m_undersampleCount; int m_undersampleCount;
int m_sampleRate; int m_sampleRate;

View File

@ -13,6 +13,8 @@
#include "util/simpleserializer.h" #include "util/simpleserializer.h"
#include "gui/basicchannelsettingswidget.h" #include "gui/basicchannelsettingswidget.h"
#include <iostream>
SSBDemodGUI* SSBDemodGUI::create(PluginAPI* pluginAPI) SSBDemodGUI* SSBDemodGUI::create(PluginAPI* pluginAPI)
{ {
SSBDemodGUI* gui = new SSBDemodGUI(pluginAPI); SSBDemodGUI* gui = new SSBDemodGUI(pluginAPI);
@ -42,6 +44,7 @@ QByteArray SSBDemodGUI::serialize() const
SimpleSerializer s(1); SimpleSerializer s(1);
s.writeS32(1, m_channelMarker->getCenterFrequency()); s.writeS32(1, m_channelMarker->getCenterFrequency());
s.writeS32(2, ui->BW->value()); s.writeS32(2, ui->BW->value());
s.writeS32(6, ui->lowCut->value());
s.writeS32(3, ui->volume->value()); s.writeS32(3, ui->volume->value());
s.writeBlob(4, ui->spectrumGUI->serialize()); s.writeBlob(4, ui->spectrumGUI->serialize());
s.writeU32(5, m_channelMarker->getColor().rgb()); s.writeU32(5, m_channelMarker->getColor().rgb());
@ -63,8 +66,10 @@ bool SSBDemodGUI::deserialize(const QByteArray& data)
qint32 tmp; qint32 tmp;
d.readS32(1, &tmp, 0); d.readS32(1, &tmp, 0);
m_channelMarker->setCenterFrequency(tmp); m_channelMarker->setCenterFrequency(tmp);
d.readS32(2, &tmp, 3); d.readS32(2, &tmp, 30);
ui->BW->setValue(tmp); ui->BW->setValue(tmp);
d.readS32(6, &tmp, 3);
ui->lowCut->setValue(tmp);
d.readS32(3, &tmp, 20); d.readS32(3, &tmp, 20);
ui->volume->setValue(tmp); ui->volume->setValue(tmp);
d.readBlob(4, &bytetmp); d.readBlob(4, &bytetmp);
@ -114,11 +119,48 @@ void SSBDemodGUI::on_BW_valueChanged(int value)
QString s = QString::number(value/10.0, 'f', 1); QString s = QString::number(value/10.0, 'f', 1);
ui->BWText->setText(s); ui->BWText->setText(s);
m_channelMarker->setBandwidth(value * 100 * 2); m_channelMarker->setBandwidth(value * 100 * 2);
if (value < 0) { if (value < 0) {
m_channelMarker->setSidebands(ChannelMarker::lsb); m_channelMarker->setSidebands(ChannelMarker::lsb);
} else { } else {
m_channelMarker->setSidebands(ChannelMarker::usb); m_channelMarker->setSidebands(ChannelMarker::usb);
} }
on_lowCut_valueChanged(m_channelMarker->getLowCutoff()/100);
}
int SSBDemodGUI::getEffectiveLowCutoff(int lowCutoff)
{
int ssbBW = m_channelMarker->getBandwidth() / 2;
int effectiveLowCutoff = lowCutoff;
const int guard = 100;
if (ssbBW < 0) {
if (effectiveLowCutoff < ssbBW + guard) {
effectiveLowCutoff = ssbBW + guard;
}
if (effectiveLowCutoff > 0) {
effectiveLowCutoff = 0;
}
} else {
if (effectiveLowCutoff > ssbBW - guard) {
effectiveLowCutoff = ssbBW - guard;
}
if (effectiveLowCutoff < 0) {
effectiveLowCutoff = 0;
}
}
return effectiveLowCutoff;
}
void SSBDemodGUI::on_lowCut_valueChanged(int value)
{
int lowCutoff = getEffectiveLowCutoff(value * 100);
m_channelMarker->setLowCutoff(lowCutoff);
QString s = QString::number(lowCutoff/1000.0, 'f', 1);
ui->lowCutText->setText(s);
ui->lowCut->setValue(lowCutoff/100);
applySettings(); applySettings();
} }
@ -207,6 +249,7 @@ void SSBDemodGUI::applySettings()
m_channelMarker->getCenterFrequency()); m_channelMarker->getCenterFrequency());
m_ssbDemod->configure(m_threadedSampleSink->getMessageQueue(), m_ssbDemod->configure(m_threadedSampleSink->getMessageQueue(),
ui->BW->value() * 100.0, ui->BW->value() * 100.0,
ui->lowCut->value() * 100.0,
ui->volume->value() / 10.0 ); ui->volume->value() / 10.0 );
} }

View File

@ -37,6 +37,7 @@ private slots:
void on_deltaFrequency_changed(quint64 value); void on_deltaFrequency_changed(quint64 value);
void on_deltaMinus_clicked(bool minus); void on_deltaMinus_clicked(bool minus);
void on_BW_valueChanged(int value); void on_BW_valueChanged(int value);
void on_lowCut_valueChanged(int value);
void on_volume_valueChanged(int value); void on_volume_valueChanged(int value);
void onWidgetRolled(QWidget* widget, bool rollDown); void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDoubleClicked(); void onMenuDoubleClicked();
@ -56,6 +57,7 @@ private:
explicit SSBDemodGUI(PluginAPI* pluginAPI, QWidget* parent = NULL); explicit SSBDemodGUI(PluginAPI* pluginAPI, QWidget* parent = NULL);
~SSBDemodGUI(); ~SSBDemodGUI();
int getEffectiveLowCutoff(int lowCutoff);
void applySettings(); void applySettings();
void leaveEvent(QEvent*); void leaveEvent(QEvent*);

View File

@ -41,6 +41,41 @@
<property name="spacing"> <property name="spacing">
<number>3</number> <number>3</number>
</property> </property>
<item row="1" column="1">
<widget class="QSlider" name="BW">
<property name="minimum">
<number>-60</number>
</property>
<property name="maximum">
<number>60</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>30</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="volumeText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>2.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2"> <item row="1" column="2">
<widget class="QLabel" name="BWText"> <widget class="QLabel" name="BWText">
<property name="minimumSize"> <property name="minimumSize">
@ -57,7 +92,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="3" column="1">
<widget class="QSlider" name="volume"> <widget class="QSlider" name="volume">
<property name="maximum"> <property name="maximum">
<number>100</number> <number>100</number>
@ -70,65 +105,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QSlider" name="BW">
<property name="minimum">
<number>-60</number>
</property>
<property name="maximum">
<number>60</number>
</property>
<property name="pageStep">
<number>10</number>
</property>
<property name="value">
<number>30</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Volume</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="volumeText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>2.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Bandwidth</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="deltaMinus">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Minus</string>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="ValueDial" name="deltaFrequency" native="true"> <widget class="ValueDial" name="deltaFrequency" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
@ -160,6 +136,20 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="BWLabel">
<property name="text">
<string>Bandwidth</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="volumeLabel">
<property name="text">
<string>Volume</string>
</property>
</widget>
</item>
<item row="0" column="2"> <item row="0" column="2">
<widget class="QLabel" name="deltaUnits"> <widget class="QLabel" name="deltaUnits">
<property name="text"> <property name="text">
@ -167,6 +157,58 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QRadioButton" name="deltaMinus">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Minus</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lowCutLabel">
<property name="text">
<string>Low cutoff</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="lowCut">
<property name="minimum">
<number>-60</number>
</property>
<property name="maximum">
<number>60</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>3</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="lowCutText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>0.3 kHz</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="spectrumContainer" native="true"> <widget class="QWidget" name="spectrumContainer" native="true">
@ -214,18 +256,6 @@
</widget> </widget>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>GLSpectrum</class>
<extends>QWidget</extends>
<header>gui/glspectrum.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLSpectrumGUI</class>
<extends>QWidget</extends>
<header>gui/glspectrumgui.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>RollupWidget</class> <class>RollupWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
@ -238,6 +268,18 @@
<header>gui/valuedial.h</header> <header>gui/valuedial.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>GLSpectrum</class>
<extends>QWidget</extends>
<header>gui/glspectrum.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLSpectrumGUI</class>
<extends>QWidget</extends>
<header>gui/glspectrumgui.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -1,5 +1,7 @@
#include "dsp/channelmarker.h" #include "dsp/channelmarker.h"
#include <iostream>
QRgb ChannelMarker::m_colorTable[] = { QRgb ChannelMarker::m_colorTable[] = {
qRgb(0xc0, 0x00, 0x00), qRgb(0xc0, 0x00, 0x00),
qRgb(0x00, 0xc0, 0x00), qRgb(0x00, 0xc0, 0x00),
@ -29,6 +31,7 @@ ChannelMarker::ChannelMarker(QObject* parent) :
QObject(parent), QObject(parent),
m_centerFrequency(0), m_centerFrequency(0),
m_bandwidth(0), m_bandwidth(0),
m_lowCutoff(0),
m_sidebands(dsb), m_sidebands(dsb),
m_visible(false), m_visible(false),
m_highlighted(false), m_highlighted(false),
@ -57,6 +60,12 @@ void ChannelMarker::setBandwidth(int bandwidth)
emit changed(); emit changed();
} }
void ChannelMarker::setLowCutoff(int lowCutoff)
{
m_lowCutoff = lowCutoff;
emit changed();
}
void ChannelMarker::setSidebands(sidebands_t sidebands) void ChannelMarker::setSidebands(sidebands_t sidebands)
{ {
m_sidebands = sidebands; m_sidebands = sidebands;

View File

@ -551,20 +551,10 @@ void GLSpectrum::paintGL()
// paint channels // paint channels
if(m_mouseInside) { if(m_mouseInside) {
// Effective BW overlays
for(int i = 0; i < m_channelMarkerStates.size(); ++i) { for(int i = 0; i < m_channelMarkerStates.size(); ++i) {
ChannelMarkerState* dv = m_channelMarkerStates[i]; ChannelMarkerState* dv = m_channelMarkerStates[i];
if(dv->m_channelMarker->getVisible()) { if(dv->m_channelMarker->getVisible()) {
/*
ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands();
float fcLineRelativePos;
if (sidebands == ChannelMarker::usb) {
fcLineRelativePos = 0.0;
} else if (sidebands == ChannelMarker::lsb) {
fcLineRelativePos = 1.0;
} else {
fcLineRelativePos = 0.5;
}
*/
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f); glColor4f(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f);
@ -577,11 +567,22 @@ void GLSpectrum::paintGL()
glVertex2f(1, 1); glVertex2f(1, 1);
glVertex2f(0, 1); glVertex2f(0, 1);
glEnd(); glEnd();
glPopMatrix();
}
}
// Center line overlays based on DSB enveloppe
for(int i = 0; i < m_channelMarkerStates.size(); ++i) {
ChannelMarkerState* dv = m_channelMarkerStates[i];
if(dv->m_channelMarker->getVisible()) {
glDisable(GL_BLEND); glDisable(GL_BLEND);
glColor3f(0.8f, 0.8f, 0.6f); glColor3f(0.8f, 0.8f, 0.6f);
glPushMatrix();
glTranslatef(dv->m_glRectDsb.x(), dv->m_glRectDsb.y(), 0);
glScalef(dv->m_glRectDsb.width(), dv->m_glRectDsb.height(), 1);
glBegin(GL_LINE_LOOP); glBegin(GL_LINE_LOOP);
glVertex2f(getCenterFreqLineRelPos(dv->m_channelMarker), 0); glVertex2f(0.5, 0);
glVertex2f(getCenterFreqLineRelPos(dv->m_channelMarker), 1); glVertex2f(0.5, 1);
glEnd(); glEnd();
glPopMatrix(); glPopMatrix();
} }
@ -662,6 +663,8 @@ void GLSpectrum::paintGL()
glPushMatrix(); glPushMatrix();
glTranslatef(m_glWaterfallRect.x(), m_glFrequencyScaleRect.y(), 0); glTranslatef(m_glWaterfallRect.x(), m_glFrequencyScaleRect.y(), 0);
glScalef(m_glWaterfallRect.width(), m_glFrequencyScaleRect.height(), 1); glScalef(m_glWaterfallRect.width(), m_glFrequencyScaleRect.height(), 1);
// Effective bandwidth overlays
for(int i = 0; i < m_channelMarkerStates.size(); ++i) { for(int i = 0; i < m_channelMarkerStates.size(); ++i) {
ChannelMarkerState* dv = m_channelMarkerStates[i]; ChannelMarkerState* dv = m_channelMarkerStates[i];
if(dv->m_channelMarker->getVisible()) { if(dv->m_channelMarker->getVisible()) {
@ -677,19 +680,29 @@ void GLSpectrum::paintGL()
glVertex2f(1, 0.5); glVertex2f(1, 0.5);
glVertex2f(0, 0.5); glVertex2f(0, 0.5);
glEnd(); glEnd();
if (dv->m_channelMarker->getHighlighted()) {
glColor3f(0.8f, 0.8f, 0.6f);
glBegin(GL_LINE_LOOP);
glVertex2f(getCenterFreqLineRelPos(dv->m_channelMarker), 0);
glVertex2f(getCenterFreqLineRelPos(dv->m_channelMarker), 1);
glEnd();
}
glDisable(GL_BLEND); glDisable(GL_BLEND);
glPopMatrix(); glPopMatrix();
} }
} }
// Center frequency mark on highlighted channels based on DSB enveloppe
for(int i = 0; i < m_channelMarkerStates.size(); ++i) {
ChannelMarkerState* dv = m_channelMarkerStates[i];
if(dv->m_channelMarker->getVisible()) {
if (dv->m_channelMarker->getHighlighted()) {
glColor3f(0.8f, 0.8f, 0.6f);
glPushMatrix();
glTranslatef(dv->m_glRectDsb.x(), dv->m_glRectDsb.y(), 0);
glScalef(dv->m_glRectDsb.width(), dv->m_glRectDsb.height(), 1);
glBegin(GL_LINE_LOOP);
glVertex2f(0.5, 0);
glVertex2f(0.5, 1);
glEnd();
glPopMatrix();
}
}
}
glPopMatrix(); glPopMatrix();
} }
@ -1026,23 +1039,31 @@ void GLSpectrum::applyChanges()
for(int i = 0; i < m_channelMarkerStates.size(); ++i) { for(int i = 0; i < m_channelMarkerStates.size(); ++i) {
ChannelMarkerState* dv = m_channelMarkerStates[i]; ChannelMarkerState* dv = m_channelMarkerStates[i];
qreal xc, pw, nw; qreal xc, pw, nw, dsbw;
ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands(); ChannelMarker::sidebands_t sidebands = dv->m_channelMarker->getSidebands();
xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency xc = m_centerFrequency + dv->m_channelMarker->getCenterFrequency(); // marker center frequency
dsbw = dv->m_channelMarker->getBandwidth();
if (sidebands == ChannelMarker::usb) { if (sidebands == ChannelMarker::usb) {
nw = 0; // negative bandwidth nw = dv->m_channelMarker->getLowCutoff(); // negative bandwidth
pw = dv->m_channelMarker->getBandwidth() / 2; // positive bandwidth pw = dv->m_channelMarker->getBandwidth() / 2; // positive bandwidth
} else if (sidebands == ChannelMarker::lsb) { } else if (sidebands == ChannelMarker::lsb) {
pw = 0; pw = dv->m_channelMarker->getLowCutoff();
nw = dv->m_channelMarker->getBandwidth() / 2; nw = dv->m_channelMarker->getBandwidth() / 2;
} else { } else {
pw = dv->m_channelMarker->getBandwidth() / 2; pw = dsbw / 2;
nw = -pw; nw = -pw;
} }
//std::cerr << xc << "; " << nw << "; " << pw << std::endl;
// draw the DSB rectangle
dv->m_glRectDsb.setRect(
m_frequencyScale.getPosFromValue(xc - (dsbw/2)) / (float)(width() - leftMargin - rightMargin),
0,
dsbw / (float)m_sampleRate,
1);
// draw the effective BW rectangle
dv->m_glRect.setRect( dv->m_glRect.setRect(
m_frequencyScale.getPosFromValue(xc + nw) / (float)(width() - leftMargin - rightMargin), m_frequencyScale.getPosFromValue(xc + nw) / (float)(width() - leftMargin - rightMargin),
0, 0,
@ -1366,16 +1387,3 @@ void GLSpectrum::channelMarkerDestroyed(QObject* object)
{ {
removeChannelMarker((ChannelMarker*)object); removeChannelMarker((ChannelMarker*)object);
} }
float GLSpectrum::getCenterFreqLineRelPos(ChannelMarker *channelMarker)
{
ChannelMarker::sidebands_t sidebands = channelMarker->getSidebands();
if (sidebands == ChannelMarker::usb) {
return 0.0;
} else if (sidebands == ChannelMarker::lsb) {
return 1.0;
} else {
return 0.5;
}
}