mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-09-05 14:47:50 -04:00
SSB demod: use settings class in demod
This commit is contained in:
parent
9b53041eea
commit
673047c7e2
@ -31,6 +31,7 @@
|
|||||||
#include "ssbdemod.h"
|
#include "ssbdemod.h"
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message)
|
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemod, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureSSBDemodPrivate, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureChannelizer, Message)
|
MESSAGE_CLASS_DEFINITION(SSBDemod::MsgConfigureChannelizer, Message)
|
||||||
|
|
||||||
SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) :
|
SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) :
|
||||||
@ -86,6 +87,8 @@ SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) :
|
|||||||
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
|
||||||
|
|
||||||
DSPEngine::instance()->addAudioSink(&m_audioFifo);
|
DSPEngine::instance()->addAudioSink(&m_audioFifo);
|
||||||
|
|
||||||
|
applySettings(m_settings, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSBDemod::~SSBDemod()
|
SSBDemod::~SSBDemod()
|
||||||
@ -115,7 +118,7 @@ void SSBDemod::configure(MessageQueue* messageQueue,
|
|||||||
int agcPowerThreshold,
|
int agcPowerThreshold,
|
||||||
int agcThresholdGate)
|
int agcThresholdGate)
|
||||||
{
|
{
|
||||||
Message* cmd = MsgConfigureSSBDemod::create(
|
Message* cmd = MsgConfigureSSBDemodPrivate::create(
|
||||||
Bandwidth,
|
Bandwidth,
|
||||||
LowCutoff,
|
LowCutoff,
|
||||||
volume,
|
volume,
|
||||||
@ -276,10 +279,6 @@ void SSBDemod::stop()
|
|||||||
|
|
||||||
bool SSBDemod::handleMessage(const Message& cmd)
|
bool SSBDemod::handleMessage(const Message& cmd)
|
||||||
{
|
{
|
||||||
float band, lowCutoff;
|
|
||||||
|
|
||||||
qDebug() << "SSBDemod::handleMessage";
|
|
||||||
|
|
||||||
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
|
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
|
||||||
{
|
{
|
||||||
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
|
||||||
@ -306,16 +305,72 @@ bool SSBDemod::handleMessage(const Message& cmd)
|
|||||||
cfg.getSampleRate(),
|
cfg.getSampleRate(),
|
||||||
cfg.getCenterFrequency());
|
cfg.getCenterFrequency());
|
||||||
|
|
||||||
|
qDebug() << "SSBDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.getSampleRate()
|
||||||
|
<< " centerFrequency: " << cfg.getCenterFrequency();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (MsgConfigureSSBDemod::match(cmd))
|
else if (MsgConfigureSSBDemod::match(cmd))
|
||||||
{
|
{
|
||||||
MsgConfigureSSBDemod& cfg = (MsgConfigureSSBDemod&) cmd;
|
MsgConfigureSSBDemod& cfg = (MsgConfigureSSBDemod&) cmd;
|
||||||
|
|
||||||
m_settingsMutex.lock();
|
SSBDemodSettings settings = cfg.getSettings();
|
||||||
|
|
||||||
band = cfg.getBandwidth();
|
// These settings are set with DownChannelizer::MsgChannelizerNotification
|
||||||
lowCutoff = cfg.getLoCutoff();
|
settings.m_inputSampleRate = m_settings.m_inputSampleRate;
|
||||||
|
settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset;
|
||||||
|
|
||||||
|
applySettings(settings, cfg.getForce());
|
||||||
|
|
||||||
|
qDebug() << "SSBDemod::handleMessage: MsgConfigureSSBDemod:"
|
||||||
|
<< " m_rfBandwidth: " << settings.m_rfBandwidth
|
||||||
|
<< " m_lowCutoff: " << settings.m_lowCutoff
|
||||||
|
<< " m_volume: " << settings.m_volume
|
||||||
|
<< " m_spanLog2: " << settings.m_spanLog2
|
||||||
|
<< " m_audioBinaual: " << settings.m_audioBinaural
|
||||||
|
<< " m_audioFlipChannels: " << settings.m_audioFlipChannels
|
||||||
|
<< " m_dsb: " << settings.m_dsb
|
||||||
|
<< " m_audioMute: " << settings.m_audioMute
|
||||||
|
<< " m_agcActive: " << settings.m_agc
|
||||||
|
<< " m_agcClamping: " << settings.m_agcClamping
|
||||||
|
<< " m_agcTimeLog2: " << settings.m_agcTimeLog2
|
||||||
|
<< " agcPowerThreshold: " << settings.m_agcPowerThreshold
|
||||||
|
<< " agcThresholdGate: " << settings.m_agcThresholdGate;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_sampleSink != 0)
|
||||||
|
{
|
||||||
|
return m_sampleSink->handleMessage(cmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSBDemod::applySettings(const SSBDemodSettings& settings, bool force)
|
||||||
|
{
|
||||||
|
if ((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) ||
|
||||||
|
(m_settings.m_inputSampleRate != settings.m_inputSampleRate) || force)
|
||||||
|
{
|
||||||
|
m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if((m_settings.m_inputSampleRate != settings.m_inputSampleRate) ||
|
||||||
|
(m_settings.m_rfBandwidth != settings.m_rfBandwidth) ||
|
||||||
|
(m_settings.m_lowCutoff != settings.m_lowCutoff) ||
|
||||||
|
(m_settings.m_audioSampleRate != settings.m_audioSampleRate) || force)
|
||||||
|
{
|
||||||
|
float band, lowCutoff;
|
||||||
|
|
||||||
|
band = settings.m_rfBandwidth;
|
||||||
|
lowCutoff = settings.m_lowCutoff;
|
||||||
|
m_audioSampleRate = settings.m_audioSampleRate;
|
||||||
|
|
||||||
if (band < 0) {
|
if (band < 0) {
|
||||||
band = -band;
|
band = -band;
|
||||||
@ -329,35 +384,41 @@ bool SSBDemod::handleMessage(const Message& cmd)
|
|||||||
band = 100.0f;
|
band = 100.0f;
|
||||||
lowCutoff = 0;
|
lowCutoff = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Bandwidth = band;
|
m_Bandwidth = band;
|
||||||
m_LowCutoff = lowCutoff;
|
m_LowCutoff = lowCutoff;
|
||||||
|
|
||||||
|
m_settingsMutex.lock();
|
||||||
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.0f * m_Bandwidth) / (float) m_audioSampleRate);
|
DSBFilter->create_dsb_filter((2.0f * m_Bandwidth) / (float) m_audioSampleRate);
|
||||||
|
m_settingsMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
m_volume = cfg.getVolume();
|
if ((m_settings.m_volume != settings.m_volume) || force)
|
||||||
//m_volume *= 2.0; // for 327.68
|
{
|
||||||
|
m_volume = settings.m_volume;
|
||||||
m_volume /= 4.0; // for 3276.8
|
m_volume /= 4.0; // for 3276.8
|
||||||
|
}
|
||||||
|
|
||||||
m_spanLog2 = cfg.getSpanLog2();
|
if ((m_settings.m_agcTimeLog2 != settings.m_agcTimeLog2) ||
|
||||||
m_audioBinaual = cfg.getAudioBinaural();
|
(m_settings.m_agcPowerThreshold != settings.m_agcPowerThreshold) ||
|
||||||
m_audioFlipChannels = cfg.getAudioFlipChannels();
|
(m_settings.m_agcThresholdGate != settings.m_agcThresholdGate) ||
|
||||||
m_dsb = cfg.getDSB();
|
(m_settings.m_agcClamping != settings.m_agcClamping) || force)
|
||||||
m_audioMute = cfg.getAudioMute();
|
{
|
||||||
m_agcActive = cfg.getAGC();
|
int agcNbSamples = 48 * (1<<settings.m_agcTimeLog2);
|
||||||
|
m_agc.setThresholdEnable(settings.m_agcPowerThreshold != -99);
|
||||||
int agcNbSamples = 48 * (1<<cfg.getAGCTimeLog2());
|
double agcPowerThreshold = CalcDb::powerFromdB(settings.m_agcPowerThreshold) * (1<<30);
|
||||||
m_agc.setThresholdEnable(cfg.getAGCPowerThershold() != -99);
|
int agcThresholdGate = 48 * settings.m_agcThresholdGate; // ms
|
||||||
double agcPowerThreshold = CalcDb::powerFromdB(cfg.getAGCPowerThershold()) * (1<<30);
|
bool agcClamping = settings.m_agcClamping;
|
||||||
int agcThresholdGate = 48 * cfg.getAGCThersholdGate(); // ms
|
|
||||||
bool agcClamping = cfg.getAGCClamping();
|
|
||||||
|
|
||||||
if (m_agcNbSamples != agcNbSamples)
|
if (m_agcNbSamples != agcNbSamples)
|
||||||
{
|
{
|
||||||
|
m_settingsMutex.lock();
|
||||||
m_agc.resize(agcNbSamples, agcTarget);
|
m_agc.resize(agcNbSamples, agcTarget);
|
||||||
m_agc.setStepDownDelay(agcNbSamples);
|
m_agc.setStepDownDelay(agcNbSamples);
|
||||||
m_agcNbSamples = agcNbSamples;
|
m_agcNbSamples = agcNbSamples;
|
||||||
|
m_settingsMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_agcPowerThreshold != agcPowerThreshold)
|
if (m_agcPowerThreshold != agcPowerThreshold)
|
||||||
@ -378,33 +439,28 @@ bool SSBDemod::handleMessage(const Message& cmd)
|
|||||||
m_agcClamping = agcClamping;
|
m_agcClamping = agcClamping;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_settingsMutex.unlock();
|
qDebug() << "SBDemod::applySettings: AGC:"
|
||||||
|
|
||||||
qDebug() << "SBDemod::handleMessage: MsgConfigureSSBDemod: m_Bandwidth: " << m_Bandwidth
|
|
||||||
<< " m_LowCutoff: " << m_LowCutoff
|
|
||||||
<< " m_volume: " << m_volume
|
|
||||||
<< " m_spanLog2: " << m_spanLog2
|
|
||||||
<< " m_audioBinaual: " << m_audioBinaual
|
|
||||||
<< " m_audioFlipChannels: " << m_audioFlipChannels
|
|
||||||
<< " m_dsb: " << m_dsb
|
|
||||||
<< " m_audioMute: " << m_audioMute
|
|
||||||
<< " m_agcActive: " << m_agcActive
|
|
||||||
<< " m_agcClamping: " << m_agcClamping
|
|
||||||
<< " agcNbSamples: " << agcNbSamples
|
<< " agcNbSamples: " << agcNbSamples
|
||||||
<< " agcPowerThreshold: " << agcPowerThreshold
|
<< " agcPowerThreshold: " << agcPowerThreshold
|
||||||
<< " agcThresholdGate: " << agcThresholdGate;
|
<< " agcThresholdGate: " << agcThresholdGate
|
||||||
|
<< " agcClamping: " << agcClamping;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
// TODO:
|
||||||
}
|
// if ((m_settings.m_udpAddress != settings.m_udpAddress)
|
||||||
else
|
// || (m_settings.m_udpPort != settings.m_udpPort) || force)
|
||||||
{
|
// {
|
||||||
if(m_sampleSink != 0)
|
// m_udpBufferAudio->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
||||||
{
|
// m_udpBufferAudio->setPort(settings.m_udpPort);
|
||||||
return m_sampleSink->handleMessage(cmd);
|
// }
|
||||||
}
|
|
||||||
else
|
m_spanLog2 = settings.m_spanLog2;
|
||||||
{
|
m_audioBinaual = settings.m_audioBinaural;
|
||||||
return false;
|
m_audioFlipChannels = settings.m_audioFlipChannels;
|
||||||
}
|
m_dsb = settings.m_dsb;
|
||||||
}
|
m_audioMute = settings.m_audioMute;
|
||||||
|
m_agcActive = settings.m_agc;
|
||||||
|
|
||||||
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +18,10 @@
|
|||||||
#ifndef INCLUDE_SSBDEMOD_H
|
#ifndef INCLUDE_SSBDEMOD_H
|
||||||
#define INCLUDE_SSBDEMOD_H
|
#define INCLUDE_SSBDEMOD_H
|
||||||
|
|
||||||
#include <dsp/basebandsamplesink.h>
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <dsp/basebandsamplesink.h>
|
||||||
#include "dsp/ncof.h"
|
#include "dsp/ncof.h"
|
||||||
#include "dsp/interpolator.h"
|
#include "dsp/interpolator.h"
|
||||||
#include "dsp/fftfilt.h"
|
#include "dsp/fftfilt.h"
|
||||||
@ -28,6 +29,8 @@
|
|||||||
#include "audio/audiofifo.h"
|
#include "audio/audiofifo.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
|
||||||
|
#include "ssbdemodsettings.h"
|
||||||
|
|
||||||
#define ssbFftLen 1024
|
#define ssbFftLen 1024
|
||||||
#define agcTarget 3276.8 // -10 dB amplitude => -20 dB power: center of normal signal
|
#define agcTarget 3276.8 // -10 dB amplitude => -20 dB power: center of normal signal
|
||||||
|
|
||||||
@ -37,6 +40,29 @@ class DownChannelizer;
|
|||||||
|
|
||||||
class SSBDemod : public BasebandSampleSink {
|
class SSBDemod : public BasebandSampleSink {
|
||||||
public:
|
public:
|
||||||
|
class MsgConfigureSSBDemod : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
const SSBDemodSettings& getSettings() const { return m_settings; }
|
||||||
|
bool getForce() const { return m_force; }
|
||||||
|
|
||||||
|
static MsgConfigureSSBDemod* create(const SSBDemodSettings& settings, bool force)
|
||||||
|
{
|
||||||
|
return new MsgConfigureSSBDemod(settings, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SSBDemodSettings m_settings;
|
||||||
|
bool m_force;
|
||||||
|
|
||||||
|
MsgConfigureSSBDemod(const SSBDemodSettings& settings, bool force) :
|
||||||
|
Message(),
|
||||||
|
m_settings(settings),
|
||||||
|
m_force(force)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
class MsgConfigureChannelizer : public Message {
|
class MsgConfigureChannelizer : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
@ -99,7 +125,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class MsgConfigureSSBDemod : public Message {
|
class MsgConfigureSSBDemodPrivate : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -117,7 +143,7 @@ private:
|
|||||||
int getAGCPowerThershold() const { return m_agcPowerThreshold; }
|
int getAGCPowerThershold() const { return m_agcPowerThreshold; }
|
||||||
int getAGCThersholdGate() const { return m_agcThresholdGate; }
|
int getAGCThersholdGate() const { return m_agcThresholdGate; }
|
||||||
|
|
||||||
static MsgConfigureSSBDemod* create(Real Bandwidth,
|
static MsgConfigureSSBDemodPrivate* create(Real Bandwidth,
|
||||||
Real LowCutoff,
|
Real LowCutoff,
|
||||||
Real volume,
|
Real volume,
|
||||||
int spanLog2,
|
int spanLog2,
|
||||||
@ -131,7 +157,7 @@ private:
|
|||||||
int agcPowerThreshold,
|
int agcPowerThreshold,
|
||||||
int agcThresholdGate)
|
int agcThresholdGate)
|
||||||
{
|
{
|
||||||
return new MsgConfigureSSBDemod(
|
return new MsgConfigureSSBDemodPrivate(
|
||||||
Bandwidth,
|
Bandwidth,
|
||||||
LowCutoff,
|
LowCutoff,
|
||||||
volume,
|
volume,
|
||||||
@ -162,7 +188,7 @@ private:
|
|||||||
int m_agcPowerThreshold;
|
int m_agcPowerThreshold;
|
||||||
int m_agcThresholdGate;
|
int m_agcThresholdGate;
|
||||||
|
|
||||||
MsgConfigureSSBDemod(Real Bandwidth,
|
MsgConfigureSSBDemodPrivate(Real Bandwidth,
|
||||||
Real LowCutoff,
|
Real LowCutoff,
|
||||||
Real volume,
|
Real volume,
|
||||||
int spanLog2,
|
int spanLog2,
|
||||||
@ -195,6 +221,7 @@ private:
|
|||||||
DeviceSourceAPI *m_deviceAPI;
|
DeviceSourceAPI *m_deviceAPI;
|
||||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||||
DownChannelizer* m_channelizer;
|
DownChannelizer* m_channelizer;
|
||||||
|
SSBDemodSettings m_settings;
|
||||||
|
|
||||||
Real m_Bandwidth;
|
Real m_Bandwidth;
|
||||||
Real m_LowCutoff;
|
Real m_LowCutoff;
|
||||||
@ -236,6 +263,8 @@ private:
|
|||||||
quint32 m_audioSampleRate;
|
quint32 m_audioSampleRate;
|
||||||
|
|
||||||
QMutex m_settingsMutex;
|
QMutex m_settingsMutex;
|
||||||
|
|
||||||
|
void applySettings(const SSBDemodSettings& settings, bool force = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_SSBDEMOD_H
|
#endif // INCLUDE_SSBDEMOD_H
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
||||||
#include "ui_ssbdemodgui.h"
|
|
||||||
#include "ui_ssbdemodgui.h"
|
#include "ui_ssbdemodgui.h"
|
||||||
#include "dsp/spectrumvis.h"
|
#include "dsp/spectrumvis.h"
|
||||||
#include "gui/glspectrum.h"
|
#include "gui/glspectrum.h"
|
||||||
@ -48,111 +47,34 @@ qint64 SSBDemodGUI::getCenterFrequency() const
|
|||||||
void SSBDemodGUI::setCenterFrequency(qint64 centerFrequency)
|
void SSBDemodGUI::setCenterFrequency(qint64 centerFrequency)
|
||||||
{
|
{
|
||||||
m_channelMarker.setCenterFrequency(centerFrequency);
|
m_channelMarker.setCenterFrequency(centerFrequency);
|
||||||
|
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::resetToDefaults()
|
void SSBDemodGUI::resetToDefaults()
|
||||||
{
|
{
|
||||||
blockApplySettings(true);
|
m_settings.resetToDefaults();
|
||||||
|
|
||||||
ui->BW->setValue(30);
|
|
||||||
ui->volume->setValue(30);
|
|
||||||
ui->deltaFrequency->setValue(0);
|
|
||||||
ui->spanLog2->setValue(3);
|
|
||||||
ui->agc->setChecked(false);
|
|
||||||
ui->agcTimeLog2->setValue(7);
|
|
||||||
ui->agcPowerThreshold->setValue(-40);
|
|
||||||
ui->agcThresholdGate->setValue(4);
|
|
||||||
|
|
||||||
blockApplySettings(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SSBDemodGUI::serialize() const
|
QByteArray SSBDemodGUI::serialize() const
|
||||||
{
|
{
|
||||||
SimpleSerializer s(1);
|
return m_settings.serialize();
|
||||||
s.writeS32(1, m_channelMarker.getCenterFrequency());
|
|
||||||
s.writeS32(2, ui->BW->value());
|
|
||||||
s.writeS32(3, ui->volume->value());
|
|
||||||
s.writeBlob(4, ui->spectrumGUI->serialize());
|
|
||||||
s.writeU32(5, m_channelMarker.getColor().rgb());
|
|
||||||
s.writeS32(6, ui->lowCut->value());
|
|
||||||
s.writeS32(7, ui->spanLog2->value());
|
|
||||||
s.writeBool(8, m_audioBinaural);
|
|
||||||
s.writeBool(9, m_audioFlipChannels);
|
|
||||||
s.writeBool(10, m_dsb);
|
|
||||||
s.writeBool(11, ui->agc->isChecked());
|
|
||||||
s.writeS32(12, ui->agcTimeLog2->value());
|
|
||||||
s.writeS32(13, ui->agcPowerThreshold->value());
|
|
||||||
s.writeS32(14, ui->agcThresholdGate->value());
|
|
||||||
s.writeBool(15, ui->agcClamping->isChecked());
|
|
||||||
return s.final();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SSBDemodGUI::deserialize(const QByteArray& data)
|
bool SSBDemodGUI::deserialize(const QByteArray& data)
|
||||||
{
|
{
|
||||||
SimpleDeserializer d(data);
|
if(m_settings.deserialize(data))
|
||||||
|
|
||||||
if (!d.isValid())
|
|
||||||
{
|
{
|
||||||
resetToDefaults();
|
updateChannelMarker();
|
||||||
applySettings();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.getVersion() == 1)
|
|
||||||
{
|
|
||||||
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, 30);
|
|
||||||
ui->BW->setValue(tmp);
|
|
||||||
d.readS32(3, &tmp, 30);
|
|
||||||
ui->volume->setValue(tmp);
|
|
||||||
d.readBlob(4, &bytetmp);
|
|
||||||
ui->spectrumGUI->deserialize(bytetmp);
|
|
||||||
if(d.readU32(5, &u32tmp))
|
|
||||||
m_channelMarker.setColor(u32tmp);
|
|
||||||
d.readS32(6, &tmp, 3);
|
|
||||||
ui->lowCut->setValue(tmp);
|
|
||||||
d.readS32(7, &tmp, 20);
|
|
||||||
ui->spanLog2->setValue(tmp);
|
|
||||||
setNewRate(tmp);
|
|
||||||
d.readBool(8, &m_audioBinaural);
|
|
||||||
ui->audioBinaural->setChecked(m_audioBinaural);
|
|
||||||
d.readBool(9, &m_audioFlipChannels);
|
|
||||||
ui->audioFlipChannels->setChecked(m_audioFlipChannels);
|
|
||||||
d.readBool(10, &m_dsb);
|
|
||||||
ui->dsb->setChecked(m_dsb);
|
|
||||||
d.readBool(11, &booltmp, false);
|
|
||||||
ui->agc->setChecked(booltmp);
|
|
||||||
d.readS32(12, &tmp, 7);
|
|
||||||
ui->agcTimeLog2->setValue(tmp);
|
|
||||||
d.readS32(13, &tmp, -40);
|
|
||||||
ui->agcPowerThreshold->setValue(tmp);
|
|
||||||
d.readS32(14, &tmp, 4);
|
|
||||||
ui->agcThresholdGate->setValue(tmp);
|
|
||||||
d.readBool(15, &booltmp, false);
|
|
||||||
ui->agcClamping->setChecked(booltmp);
|
|
||||||
|
|
||||||
displaySettings();
|
displaySettings();
|
||||||
|
applySettings(true); // will have true
|
||||||
blockApplySettings(false);
|
|
||||||
m_channelMarker.blockSignals(false);
|
|
||||||
|
|
||||||
applySettings();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resetToDefaults();
|
m_settings.resetToDefaults();
|
||||||
applySettings();
|
displaySettings();
|
||||||
|
applySettings(true); // will have true
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,18 +92,21 @@ void SSBDemodGUI::viewChanged()
|
|||||||
void SSBDemodGUI::on_audioBinaural_toggled(bool binaural)
|
void SSBDemodGUI::on_audioBinaural_toggled(bool binaural)
|
||||||
{
|
{
|
||||||
m_audioBinaural = binaural;
|
m_audioBinaural = binaural;
|
||||||
|
m_settings.m_audioBinaural = binaural;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_audioFlipChannels_toggled(bool flip)
|
void SSBDemodGUI::on_audioFlipChannels_toggled(bool flip)
|
||||||
{
|
{
|
||||||
m_audioFlipChannels = flip;
|
m_audioFlipChannels = flip;
|
||||||
|
m_settings.m_audioFlipChannels = flip;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_dsb_toggled(bool dsb)
|
void SSBDemodGUI::on_dsb_toggled(bool dsb)
|
||||||
{
|
{
|
||||||
m_dsb = dsb;
|
m_dsb = dsb;
|
||||||
|
m_settings.m_dsb = dsb;
|
||||||
|
|
||||||
if (m_dsb)
|
if (m_dsb)
|
||||||
{
|
{
|
||||||
@ -218,6 +143,8 @@ void SSBDemodGUI::on_dsb_toggled(bool dsb)
|
|||||||
void SSBDemodGUI::on_deltaFrequency_changed(qint64 value)
|
void SSBDemodGUI::on_deltaFrequency_changed(qint64 value)
|
||||||
{
|
{
|
||||||
m_channelMarker.setCenterFrequency(value);
|
m_channelMarker.setCenterFrequency(value);
|
||||||
|
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||||
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_BW_valueChanged(int value)
|
void SSBDemodGUI::on_BW_valueChanged(int value)
|
||||||
@ -234,6 +161,7 @@ void SSBDemodGUI::on_BW_valueChanged(int value)
|
|||||||
ui->BWText->setText(tr("%1k").arg(s));
|
ui->BWText->setText(tr("%1k").arg(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_settings.m_rfBandwidth = value * 100;
|
||||||
on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100);
|
on_lowCut_valueChanged(m_channelMarker.getLowCutoff()/100);
|
||||||
setNewRate(m_spanLog2);
|
setNewRate(m_spanLog2);
|
||||||
}
|
}
|
||||||
@ -277,22 +205,26 @@ void SSBDemodGUI::on_lowCut_valueChanged(int value)
|
|||||||
QString s = QString::number(lowCutoff/1000.0, 'f', 1);
|
QString s = QString::number(lowCutoff/1000.0, 'f', 1);
|
||||||
ui->lowCutText->setText(tr("%1k").arg(s));
|
ui->lowCutText->setText(tr("%1k").arg(s));
|
||||||
ui->lowCut->setValue(lowCutoff/100);
|
ui->lowCut->setValue(lowCutoff/100);
|
||||||
|
m_settings.m_lowCutoff = lowCutoff;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_volume_valueChanged(int value)
|
void SSBDemodGUI::on_volume_valueChanged(int value)
|
||||||
{
|
{
|
||||||
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||||
|
m_settings.m_volume = value / 10.0;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_agc_toggled(bool checked __attribute((__unused__)))
|
void SSBDemodGUI::on_agc_toggled(bool checked)
|
||||||
{
|
{
|
||||||
|
m_settings.m_agc = checked;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_agcClamping_toggled(bool checked __attribute((__unused__)))
|
void SSBDemodGUI::on_agcClamping_toggled(bool checked)
|
||||||
{
|
{
|
||||||
|
m_settings.m_agcClamping = checked;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,12 +232,14 @@ void SSBDemodGUI::on_agcTimeLog2_valueChanged(int value)
|
|||||||
{
|
{
|
||||||
QString s = QString::number((1<<value), 'f', 0);
|
QString s = QString::number((1<<value), 'f', 0);
|
||||||
ui->agcTimeText->setText(s);
|
ui->agcTimeText->setText(s);
|
||||||
|
m_settings.m_agcTimeLog2 = value;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_agcPowerThreshold_valueChanged(int value)
|
void SSBDemodGUI::on_agcPowerThreshold_valueChanged(int value)
|
||||||
{
|
{
|
||||||
displayAGCPowerThreshold(value);
|
displayAGCPowerThreshold(value);
|
||||||
|
m_settings.m_agcPowerThreshold = value;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,12 +247,14 @@ void SSBDemodGUI::on_agcThresholdGate_valueChanged(int value)
|
|||||||
{
|
{
|
||||||
QString s = QString::number(value, 'f', 0);
|
QString s = QString::number(value, 'f', 0);
|
||||||
ui->agcThresholdGateText->setText(s);
|
ui->agcThresholdGateText->setText(s);
|
||||||
|
m_settings.m_agcThresholdGate = value;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::on_audioMute_toggled(bool checked)
|
void SSBDemodGUI::on_audioMute_toggled(bool checked)
|
||||||
{
|
{
|
||||||
m_audioMute = checked;
|
m_audioMute = checked;
|
||||||
|
m_settings.m_audioMute = checked;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,6 +262,7 @@ void SSBDemodGUI::on_spanLog2_valueChanged(int value)
|
|||||||
{
|
{
|
||||||
if (setNewRate(value))
|
if (setNewRate(value))
|
||||||
{
|
{
|
||||||
|
m_settings.m_spanLog2 = value;
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,12 +323,11 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
|||||||
|
|
||||||
connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
connect(&m_pluginAPI->getMainWindow()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
||||||
|
|
||||||
m_channelMarker.setColor(Qt::green);
|
|
||||||
m_channelMarker.setBandwidth(m_rate);
|
|
||||||
m_channelMarker.setSidebands(ChannelMarker::usb);
|
|
||||||
m_channelMarker.setCenterFrequency(0);
|
|
||||||
m_channelMarker.setVisible(true);
|
m_channelMarker.setVisible(true);
|
||||||
|
|
||||||
|
m_settings.setChannelMarker(&m_channelMarker);
|
||||||
|
m_settings.setSpectrumGUI(ui->spectrumGUI);
|
||||||
|
|
||||||
connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
connect(&m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||||
|
|
||||||
m_deviceAPI->registerChannelInstance(m_channelID, this);
|
m_deviceAPI->registerChannelInstance(m_channelID, this);
|
||||||
@ -400,9 +336,8 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidg
|
|||||||
|
|
||||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||||
|
|
||||||
resetToDefaults();
|
|
||||||
displaySettings();
|
displaySettings();
|
||||||
applySettings();
|
applySettings(true);
|
||||||
setNewRate(m_spanLog2);
|
setNewRate(m_spanLog2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +381,6 @@ bool SSBDemodGUI::setNewRate(int spanLog2)
|
|||||||
m_channelMarker.setLowCutoff(m_rate);
|
m_channelMarker.setLowCutoff(m_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString s = QString::number(m_rate/1000.0, 'f', 1);
|
QString s = QString::number(m_rate/1000.0, 'f', 1);
|
||||||
|
|
||||||
if (m_dsb)
|
if (m_dsb)
|
||||||
@ -496,7 +430,7 @@ void SSBDemodGUI::blockApplySettings(bool block)
|
|||||||
m_doApplySettings = !block;
|
m_doApplySettings = !block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::applySettings()
|
void SSBDemodGUI::applySettings(bool force)
|
||||||
{
|
{
|
||||||
if (m_doApplySettings)
|
if (m_doApplySettings)
|
||||||
{
|
{
|
||||||
@ -507,30 +441,90 @@ void SSBDemodGUI::applySettings()
|
|||||||
48000, m_channelMarker.getCenterFrequency());
|
48000, m_channelMarker.getCenterFrequency());
|
||||||
m_ssbDemod->getInputMessageQueue()->push(channelConfigMsg);
|
m_ssbDemod->getInputMessageQueue()->push(channelConfigMsg);
|
||||||
|
|
||||||
m_ssbDemod->configure(m_ssbDemod->getInputMessageQueue(),
|
SSBDemod::MsgConfigureSSBDemod* message = SSBDemod::MsgConfigureSSBDemod::create( m_settings, force);
|
||||||
ui->BW->value() * 100.0,
|
m_ssbDemod->getInputMessageQueue()->push(message);
|
||||||
ui->lowCut->value() * 100.0,
|
|
||||||
ui->volume->value() / 10.0,
|
|
||||||
m_spanLog2,
|
|
||||||
m_audioBinaural,
|
|
||||||
m_audioFlipChannels,
|
|
||||||
m_dsb,
|
|
||||||
ui->audioMute->isChecked(),
|
|
||||||
ui->agc->isChecked(),
|
|
||||||
ui->agcClamping->isChecked(),
|
|
||||||
ui->agcTimeLog2->value(),
|
|
||||||
ui->agcPowerThreshold->value(),
|
|
||||||
ui->agcThresholdGate->value());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::displaySettings()
|
void SSBDemodGUI::displaySettings()
|
||||||
{
|
{
|
||||||
QString s = QString::number((1<<ui->agcTimeLog2->value()), 'f', 0);
|
m_channelMarker.blockSignals(true);
|
||||||
|
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||||
|
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth * 2);
|
||||||
|
m_channelMarker.setLowCutoff(m_settings.m_lowCutoff);
|
||||||
|
m_channelMarker.setUDPAddress(m_settings.m_udpAddress);
|
||||||
|
m_channelMarker.setUDPSendPort(m_settings.m_udpPort);
|
||||||
|
m_channelMarker.setColor(m_settings.m_rgbColor);
|
||||||
|
setTitleColor(m_settings.m_rgbColor);
|
||||||
|
|
||||||
|
if (m_settings.m_dsb) {
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::dsb);
|
||||||
|
} else {
|
||||||
|
if (m_settings.m_rfBandwidth < 0) {
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::lsb);
|
||||||
|
} else {
|
||||||
|
m_channelMarker.setSidebands(ChannelMarker::usb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_channelMarker.blockSignals(false);
|
||||||
|
|
||||||
|
blockApplySettings(true);
|
||||||
|
|
||||||
|
ui->agc->setChecked(m_settings.m_agc);
|
||||||
|
ui->agcClamping->setChecked(m_settings.m_agcClamping);
|
||||||
|
ui->audioBinaural->setChecked(m_settings.m_audioBinaural);
|
||||||
|
ui->audioFlipChannels->setChecked(m_settings.m_audioFlipChannels);
|
||||||
|
ui->audioMute->setChecked(m_settings.m_audioMute);
|
||||||
|
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||||
|
ui->dsb->setChecked(m_settings.m_dsb);
|
||||||
|
ui->spanLog2->setValue(m_settings.m_spanLog2);
|
||||||
|
|
||||||
|
ui->BW->setValue(m_settings.m_rfBandwidth / 100.0);
|
||||||
|
QString s = QString::number(m_settings.m_rfBandwidth/1000.0, 'f', 1);
|
||||||
|
|
||||||
|
if (m_settings.m_dsb)
|
||||||
|
{
|
||||||
|
ui->BWText->setText(tr("%1%2k").arg(QChar(0xB1, 0x00)).arg(s));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->BWText->setText(tr("%1k").arg(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->lowCut->setValue(m_settings.m_lowCutoff / 100.0);
|
||||||
|
ui->lowCutText->setText(tr("%1k").arg(m_settings.m_lowCutoff / 1000.0));
|
||||||
|
|
||||||
|
ui->volume->setValue(m_settings.m_volume * 10.0);
|
||||||
|
ui->volumeText->setText(QString("%1").arg(m_settings.m_volume, 0, 'f', 1));
|
||||||
|
|
||||||
|
ui->agcTimeLog2->setValue(m_settings.m_agcTimeLog2);
|
||||||
|
s = QString::number((1<<ui->agcTimeLog2->value()), 'f', 0);
|
||||||
ui->agcTimeText->setText(s);
|
ui->agcTimeText->setText(s);
|
||||||
|
|
||||||
|
ui->agcPowerThreshold->setValue(m_settings.m_agcPowerThreshold);
|
||||||
displayAGCPowerThreshold(ui->agcPowerThreshold->value());
|
displayAGCPowerThreshold(ui->agcPowerThreshold->value());
|
||||||
|
|
||||||
|
ui->agcThresholdGate->setValue(m_settings.m_agcThresholdGate);
|
||||||
s = QString::number(ui->agcThresholdGate->value(), 'f', 0);
|
s = QString::number(ui->agcThresholdGate->value(), 'f', 0);
|
||||||
ui->agcThresholdGateText->setText(s);
|
ui->agcThresholdGateText->setText(s);
|
||||||
|
|
||||||
|
blockApplySettings(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSBDemodGUI::displayUDPAddress()
|
||||||
|
{
|
||||||
|
//TODO: ui->copyAudioToUDP->setToolTip(QString("Copy audio output to UDP %1:%2").arg(m_channelMarker.getUDPAddress()).arg(m_channelMarker.getUDPSendPort()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSBDemodGUI::updateChannelMarker()
|
||||||
|
{
|
||||||
|
m_channelMarker.blockSignals(true);
|
||||||
|
|
||||||
|
//m_channelMarker.deserialize(m_settings.m_channelMarkerBytes);
|
||||||
|
this->setWindowTitle(m_channelMarker.getTitle());
|
||||||
|
|
||||||
|
m_channelMarker.blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSBDemodGUI::displayAGCPowerThreshold(int value)
|
void SSBDemodGUI::displayAGCPowerThreshold(int value)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "dsp/channelmarker.h"
|
#include "dsp/channelmarker.h"
|
||||||
#include "dsp/movingaverage.h"
|
#include "dsp/movingaverage.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
|
#include "ssbdemodsettings.h"
|
||||||
|
|
||||||
class PluginAPI;
|
class PluginAPI;
|
||||||
class DeviceSourceAPI;
|
class DeviceSourceAPI;
|
||||||
@ -63,6 +64,7 @@ private:
|
|||||||
PluginAPI* m_pluginAPI;
|
PluginAPI* m_pluginAPI;
|
||||||
DeviceSourceAPI* m_deviceAPI;
|
DeviceSourceAPI* m_deviceAPI;
|
||||||
ChannelMarker m_channelMarker;
|
ChannelMarker m_channelMarker;
|
||||||
|
SSBDemodSettings m_settings;
|
||||||
bool m_basicSettingsShown;
|
bool m_basicSettingsShown;
|
||||||
bool m_doApplySettings;
|
bool m_doApplySettings;
|
||||||
int m_rate;
|
int m_rate;
|
||||||
@ -85,8 +87,10 @@ 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 displayUDPAddress();
|
||||||
|
void updateChannelMarker();
|
||||||
|
|
||||||
void displayAGCPowerThreshold(int value);
|
void displayAGCPowerThreshold(int value);
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
#include "dsp/dspengine.h"
|
#include "dsp/dspengine.h"
|
||||||
#include "util/simpleserializer.h"
|
#include "util/simpleserializer.h"
|
||||||
#include "settings/serializable.h"
|
#include "settings/serializable.h"
|
||||||
@ -43,6 +45,8 @@ void SSBDemodSettings::resetToDefaults()
|
|||||||
m_spanLog2 = 3;
|
m_spanLog2 = 3;
|
||||||
m_inputSampleRate = 96000;
|
m_inputSampleRate = 96000;
|
||||||
m_inputFrequencyOffset = 0;
|
m_inputFrequencyOffset = 0;
|
||||||
|
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
|
||||||
|
m_rgbColor = QColor(0, 255, 0).rgb();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SSBDemodSettings::serialize() const
|
QByteArray SSBDemodSettings::serialize() const
|
||||||
|
@ -25,6 +25,7 @@ struct SSBDemodSettings
|
|||||||
{
|
{
|
||||||
int m_inputSampleRate;
|
int m_inputSampleRate;
|
||||||
qint32 m_inputFrequencyOffset;
|
qint32 m_inputFrequencyOffset;
|
||||||
|
quint32 m_audioSampleRate;
|
||||||
Real m_rfBandwidth;
|
Real m_rfBandwidth;
|
||||||
Real m_lowCutoff;
|
Real m_lowCutoff;
|
||||||
Real m_volume;
|
Real m_volume;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user