mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-18 22:31:48 -05:00
SSB demod: implemented DSB option
This commit is contained in:
parent
f512503dc1
commit
5e0e3a01e1
@ -50,20 +50,20 @@ SSBDemod::SSBDemod(SampleSink* sampleSink) :
|
|||||||
m_audioBuffer.resize(1<<9);
|
m_audioBuffer.resize(1<<9);
|
||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
m_undersampleCount = 0;
|
m_undersampleCount = 0;
|
||||||
|
m_sum = 0;
|
||||||
|
|
||||||
m_usb = true;
|
m_usb = true;
|
||||||
m_magsq = 0.0f;
|
m_magsq = 0.0f;
|
||||||
SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, ssbFftLen);
|
SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, ssbFftLen);
|
||||||
|
DSBFilter = new fftfilt((2*m_Bandwidth) / m_sampleRate, 2*ssbFftLen);
|
||||||
|
|
||||||
DSPEngine::instance()->addAudioSink(&m_audioFifo);
|
DSPEngine::instance()->addAudioSink(&m_audioFifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSBDemod::~SSBDemod()
|
SSBDemod::~SSBDemod()
|
||||||
{
|
{
|
||||||
if (SSBFilter)
|
if (SSBFilter) delete SSBFilter;
|
||||||
{
|
if (DSBFilter) delete DSBFilter;
|
||||||
delete SSBFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
DSPEngine::instance()->removeAudioSink(&m_audioFifo);
|
DSPEngine::instance()->removeAudioSink(&m_audioFifo);
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ void SSBDemod::configure(MessageQueue* messageQueue,
|
|||||||
void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly)
|
void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly)
|
||||||
{
|
{
|
||||||
Complex ci;
|
Complex ci;
|
||||||
fftfilt::cmplx *sideband, sum;
|
fftfilt::cmplx *sideband;
|
||||||
Real avg;
|
Real avg;
|
||||||
int n_out;
|
int n_out;
|
||||||
|
|
||||||
@ -101,12 +101,13 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
|||||||
|
|
||||||
if(m_interpolator.interpolate(&m_sampleDistanceRemain, c, &ci))
|
if(m_interpolator.interpolate(&m_sampleDistanceRemain, c, &ci))
|
||||||
{
|
{
|
||||||
n_out = SSBFilter->runSSB(ci, &sideband, m_usb);
|
if (m_dsb)
|
||||||
m_sampleDistanceRemain += (Real)m_sampleRate / m_audioSampleRate;
|
{
|
||||||
|
n_out = DSBFilter->runDSB(ci, &sideband);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
n_out = 0;
|
n_out = SSBFilter->runSSB(ci, &sideband, m_usb);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < n_out; i++)
|
for (int i = 0; i < n_out; i++)
|
||||||
@ -114,18 +115,23 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
|||||||
// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
|
// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
|
||||||
// smart decimation with bit gain using float arithmetic (23 bits significand)
|
// smart decimation with bit gain using float arithmetic (23 bits significand)
|
||||||
|
|
||||||
sum += sideband[i];
|
m_sum += sideband[i];
|
||||||
|
|
||||||
if (!(m_undersampleCount++ & decim_mask))
|
if (!(m_undersampleCount++ & decim_mask))
|
||||||
{
|
{
|
||||||
Real avgr = sum.real() / decim;
|
m_sum /= decim;
|
||||||
Real avgi = sum.imag() / decim;
|
m_magsq = (m_sum.real() * m_sum.real() + m_sum.imag() * m_sum.imag())/ (1<<30);
|
||||||
m_magsq = (avgr * avgr + avgi * avgi) / (1<<30);
|
|
||||||
//avg = (sum.real() + sum.imag()) * 0.7 * 32768.0 / decim;
|
if (!m_dsb & !m_usb)
|
||||||
avg = (avgr + avgi) * 0.7;
|
{ // invert spectrum for LSB
|
||||||
m_sampleBuffer.push_back(Sample(avg, 0.0));
|
m_sampleBuffer.push_back(Sample(m_sum.imag(), m_sum.real()));
|
||||||
sum.real() = 0.0;
|
}
|
||||||
sum.imag() = 0.0;
|
else
|
||||||
|
{
|
||||||
|
m_sampleBuffer.push_back(Sample(m_sum.real(), m_sum.imag()));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_audioBinaual)
|
if (m_audioBinaual)
|
||||||
@ -163,6 +169,13 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
|||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_sampleDistanceRemain += (Real)m_sampleRate / m_audioSampleRate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n_out = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 0) != m_audioBufferFill)
|
if (m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 0) != m_audioBufferFill)
|
||||||
@ -173,7 +186,7 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
|||||||
|
|
||||||
if(m_sampleSink != 0)
|
if(m_sampleSink != 0)
|
||||||
{
|
{
|
||||||
m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), true);
|
m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), !m_dsb);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sampleBuffer.clear();
|
m_sampleBuffer.clear();
|
||||||
@ -239,6 +252,7 @@ bool SSBDemod::handleMessage(const Message& cmd)
|
|||||||
|
|
||||||
m_interpolator.create(16, m_sampleRate, band * 2.0f);
|
m_interpolator.create(16, m_sampleRate, band * 2.0f);
|
||||||
SSBFilter->create_filter(m_LowCutoff / (float) m_audioSampleRate, m_Bandwidth / (float) m_audioSampleRate);
|
SSBFilter->create_filter(m_LowCutoff / (float) m_audioSampleRate, m_Bandwidth / (float) m_audioSampleRate);
|
||||||
|
DSBFilter->create_dsb_filter((2*m_Bandwidth) / m_sampleRate);
|
||||||
|
|
||||||
m_volume = cfg.getVolume();
|
m_volume = cfg.getVolume();
|
||||||
m_volume *= m_volume * 0.1;
|
m_volume *= m_volume * 0.1;
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
bool audioFlipChannels,
|
bool audioFlipChannels,
|
||||||
bool dsb);
|
bool dsb);
|
||||||
|
|
||||||
|
int getSampleRate() const { return m_sampleRate; }
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
||||||
virtual void start();
|
virtual void start();
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
@ -112,6 +113,7 @@ private:
|
|||||||
Real m_LowCutoff;
|
Real m_LowCutoff;
|
||||||
Real m_volume;
|
Real m_volume;
|
||||||
int m_spanLog2;
|
int m_spanLog2;
|
||||||
|
fftfilt::cmplx m_sum;
|
||||||
int m_undersampleCount;
|
int m_undersampleCount;
|
||||||
int m_sampleRate;
|
int m_sampleRate;
|
||||||
int m_frequency;
|
int m_frequency;
|
||||||
@ -125,6 +127,7 @@ private:
|
|||||||
Interpolator m_interpolator;
|
Interpolator m_interpolator;
|
||||||
Real m_sampleDistanceRemain;
|
Real m_sampleDistanceRemain;
|
||||||
fftfilt* SSBFilter;
|
fftfilt* SSBFilter;
|
||||||
|
fftfilt* DSBFilter;
|
||||||
|
|
||||||
SampleSink* m_sampleSink;
|
SampleSink* m_sampleSink;
|
||||||
SampleVector m_sampleBuffer;
|
SampleVector m_sampleBuffer;
|
||||||
|
@ -167,7 +167,31 @@ void SSBDemodGUI::on_audioFlipChannels_toggled(bool flip)
|
|||||||
void SSBDemodGUI::on_dsb_toggled(bool dsb)
|
void SSBDemodGUI::on_dsb_toggled(bool dsb)
|
||||||
{
|
{
|
||||||
m_dsb = dsb;
|
m_dsb = dsb;
|
||||||
|
|
||||||
|
if (!m_dsb)
|
||||||
|
{
|
||||||
|
if (ui->BW->value() < 0) {
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
||||||
|
} else {
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::usb);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->glSpectrum->setCenterFrequency(m_rate/4);
|
||||||
|
ui->glSpectrum->setSampleRate(m_rate/2);
|
||||||
|
ui->glSpectrum->setSsbSpectrum(true);
|
||||||
|
|
||||||
|
on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
||||||
|
|
||||||
|
ui->glSpectrum->setCenterFrequency(0);
|
||||||
|
ui->glSpectrum->setSampleRate(m_rate);
|
||||||
|
ui->glSpectrum->setSsbSpectrum(false);
|
||||||
|
|
||||||
applySettings();
|
applySettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_deltaFrequency_changed(quint64 value)
|
void SSBDemodGUI::on_deltaFrequency_changed(quint64 value)
|
||||||
@ -188,13 +212,17 @@ void SSBDemodGUI::on_BW_valueChanged(int value)
|
|||||||
ui->BWText->setText(tr("%1k").arg(s));
|
ui->BWText->setText(tr("%1k").arg(s));
|
||||||
m_channelMarker.setBandwidth(value * 100 * 2);
|
m_channelMarker.setBandwidth(value * 100 * 2);
|
||||||
|
|
||||||
if (value < 0)
|
if (!m_dsb)
|
||||||
{
|
{
|
||||||
|
if (value < 0) {
|
||||||
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
||||||
|
} else {
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::usb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_channelMarker.setSidebands(ChannelMarker::usb);
|
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
||||||
}
|
}
|
||||||
|
|
||||||
on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100);
|
on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100);
|
||||||
@ -206,25 +234,18 @@ int SSBDemodGUI::getEffectiveLowCutoff(int lowCutoff)
|
|||||||
int effectiveLowCutoff = lowCutoff;
|
int effectiveLowCutoff = lowCutoff;
|
||||||
const int guard = 100;
|
const int guard = 100;
|
||||||
|
|
||||||
if (ssbBW < 0)
|
if (ssbBW < 0) {
|
||||||
{
|
if (effectiveLowCutoff < ssbBW + guard) {
|
||||||
if (effectiveLowCutoff < ssbBW + guard)
|
|
||||||
{
|
|
||||||
effectiveLowCutoff = ssbBW + guard;
|
effectiveLowCutoff = ssbBW + guard;
|
||||||
}
|
}
|
||||||
if (effectiveLowCutoff > 0)
|
if (effectiveLowCutoff > 0) {
|
||||||
{
|
|
||||||
effectiveLowCutoff = 0;
|
effectiveLowCutoff = 0;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (effectiveLowCutoff > ssbBW - guard) {
|
||||||
{
|
|
||||||
if (effectiveLowCutoff > ssbBW - guard)
|
|
||||||
{
|
|
||||||
effectiveLowCutoff = ssbBW - guard;
|
effectiveLowCutoff = ssbBW - guard;
|
||||||
}
|
}
|
||||||
if (effectiveLowCutoff < 0)
|
if (effectiveLowCutoff < 0) {
|
||||||
{
|
|
||||||
effectiveLowCutoff = 0;
|
effectiveLowCutoff = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -323,6 +344,7 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||||
|
|
||||||
applySettings();
|
applySettings();
|
||||||
|
setNewRate(m_spanLog2);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSBDemodGUI::~SSBDemodGUI()
|
SSBDemodGUI::~SSBDemodGUI()
|
||||||
@ -339,32 +361,26 @@ SSBDemodGUI::~SSBDemodGUI()
|
|||||||
|
|
||||||
bool SSBDemodGUI::setNewRate(int spanLog2)
|
bool SSBDemodGUI::setNewRate(int spanLog2)
|
||||||
{
|
{
|
||||||
if ((spanLog2 < 1) || (spanLog2 > 5))
|
if ((spanLog2 < 0) || (spanLog2 > 6)) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_spanLog2 = spanLog2;
|
m_spanLog2 = spanLog2;
|
||||||
m_rate = 48000 / (1<<spanLog2);
|
//m_rate = 48000 / (1<<spanLog2);
|
||||||
|
m_rate = m_ssbDemod->getSampleRate() / (1<<spanLog2);
|
||||||
|
|
||||||
if (ui->BW->value() < -m_rate/100)
|
if (ui->BW->value() < -m_rate/100) {
|
||||||
{
|
|
||||||
ui->BW->setValue(-m_rate/100);
|
ui->BW->setValue(-m_rate/100);
|
||||||
m_channelMarker.setBandwidth(-m_rate*2);
|
m_channelMarker.setBandwidth(-m_rate*2);
|
||||||
}
|
} else if (ui->BW->value() > m_rate/100) {
|
||||||
else if (ui->BW->value() > m_rate/100)
|
|
||||||
{
|
|
||||||
ui->BW->setValue(m_rate/100);
|
ui->BW->setValue(m_rate/100);
|
||||||
m_channelMarker.setBandwidth(m_rate*2);
|
m_channelMarker.setBandwidth(m_rate*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ui->lowCut->value() < -m_rate/100)
|
if (ui->lowCut->value() < -m_rate/100) {
|
||||||
{
|
|
||||||
ui->lowCut->setValue(-m_rate/100);
|
ui->lowCut->setValue(-m_rate/100);
|
||||||
m_channelMarker.setLowCutoff(-m_rate);
|
m_channelMarker.setLowCutoff(-m_rate);
|
||||||
}
|
} else if (ui->lowCut->value() > m_rate/100) {
|
||||||
else if (ui->lowCut->value() > m_rate/100)
|
|
||||||
{
|
|
||||||
ui->lowCut->setValue(m_rate/100);
|
ui->lowCut->setValue(m_rate/100);
|
||||||
m_channelMarker.setLowCutoff(m_rate);
|
m_channelMarker.setLowCutoff(m_rate);
|
||||||
}
|
}
|
||||||
@ -377,8 +393,26 @@ bool SSBDemodGUI::setNewRate(int spanLog2)
|
|||||||
QString s = QString::number(m_rate/1000.0, 'f', 1);
|
QString s = QString::number(m_rate/1000.0, 'f', 1);
|
||||||
ui->spanText->setText(tr("%1k").arg(s));
|
ui->spanText->setText(tr("%1k").arg(s));
|
||||||
|
|
||||||
ui->glSpectrum->setCenterFrequency(m_rate/2);
|
if (!m_dsb)
|
||||||
|
{
|
||||||
|
if (ui->BW->value() < 0) {
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
||||||
|
} else {
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::usb);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->glSpectrum->setCenterFrequency(m_rate/4);
|
||||||
|
ui->glSpectrum->setSampleRate(m_rate/2);
|
||||||
|
ui->glSpectrum->setSsbSpectrum(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
||||||
|
|
||||||
|
ui->glSpectrum->setCenterFrequency(0);
|
||||||
ui->glSpectrum->setSampleRate(m_rate);
|
ui->glSpectrum->setSampleRate(m_rate);
|
||||||
|
ui->glSpectrum->setSsbSpectrum(false);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -201,6 +201,9 @@
|
|||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
Loading…
Reference in New Issue
Block a user