SSB modulator: added compression (AGC) volume order control

This commit is contained in:
f4exb 2017-08-05 23:11:05 +02:00
parent d8f7dcebdc
commit 428d22579d
7 changed files with 77 additions and 11 deletions

View File

@ -135,6 +135,7 @@ void SSBMod::configure(MessageQueue* messageQueue,
bool audioMute,
bool playLoop,
bool agc,
float agcOrder,
int agcTime,
int agcThreshold,
int agcThresholdGate,
@ -151,6 +152,7 @@ void SSBMod::configure(MessageQueue* messageQueue,
audioMute,
playLoop,
agc,
agcOrder,
agcTime,
agcThreshold,
agcThresholdGate,
@ -617,6 +619,7 @@ bool SSBMod::handleMessage(const Message& cmd)
m_config.m_agc = cfg.getAGC();
m_config.m_agcTime = 48 * cfg.getAGCTime(); // ms
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 = 48 * cfg.getAGCThresholdGate(); // ms
@ -752,9 +755,9 @@ void SSBMod::apply()
}
}
if (m_config.m_agcTime != m_running.m_agcTime)
if ((m_config.m_agcTime != m_running.m_agcTime) || (m_config.m_agcOrder != m_running.m_agcOrder))
{
m_inAGC.resize(m_config.m_agcTime, 0.2);
m_inAGC.resize(m_config.m_agcTime, m_config.m_agcOrder);
}
if (m_config.m_agcThresholdEnable != m_running.m_agcThresholdEnable)
@ -792,6 +795,7 @@ void SSBMod::apply()
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;

View File

@ -189,6 +189,7 @@ public:
bool audioMute,
bool playLoop,
bool agc,
float agcOrder,
int agcTime,
int agcThreshold,
int agcThresholdGate,
@ -231,6 +232,7 @@ private:
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; }
@ -247,6 +249,7 @@ private:
bool audioMute,
bool playLoop,
bool agc,
float agcOrder,
int agcTime,
int agcThreshold,
int agcThresholdGate,
@ -263,6 +266,7 @@ private:
audioMute,
playLoop,
agc,
agcOrder,
agcTime,
agcThreshold,
agcThresholdGate,
@ -281,6 +285,7 @@ private:
bool m_audioMute;
bool m_playLoop;
bool m_agc;
float m_agcOrder;
int m_agcTime;
int m_agcThreshold;
int m_agcThresholdGate;
@ -297,6 +302,7 @@ private:
bool audioMute,
bool playLoop,
bool agc,
float agcOrder,
int agcTime,
int agcThreshold,
int agcThresholdGate,
@ -313,6 +319,7 @@ private:
m_audioMute(audioMute),
m_playLoop(playLoop),
m_agc(agc),
m_agcOrder(agcOrder),
m_agcTime(agcTime),
m_agcThreshold(agcThreshold),
m_agcThresholdGate(agcThresholdGate),
@ -349,6 +356,7 @@ private:
bool m_audioMute;
bool m_playLoop;
bool m_agc;
float m_agcOrder;
int m_agcTime;
bool m_agcThresholdEnable;
double m_agcThreshold;
@ -371,6 +379,7 @@ private:
m_audioMute(false),
m_playLoop(false),
m_agc(false),
m_agcOrder(0.2),
m_agcTime(9600),
m_agcThresholdEnable(true),
m_agcThreshold(1e-4),

View File

@ -122,6 +122,7 @@ QByteArray SSBModGUI::serialize() const
s.writeS32(14, ui->agcThreshold->value());
s.writeS32(15, ui->agcThresholdGate->value());
s.writeS32(16, ui->agcThresholdDelay->value());
s.writeS32(17, ui->agcOrder->value());
return s.final();
}
@ -185,6 +186,8 @@ bool SSBModGUI::deserialize(const QByteArray& data)
ui->agcThresholdGate->setValue(tmp);
d.readS32(16, &tmp, 5);
ui->agcThresholdDelay->setValue(tmp);
d.readS32(17, &tmp, 20);
ui->agcOrder->setValue(tmp);
displaySettings();
@ -433,6 +436,12 @@ void SSBModGUI::on_agc_stateChanged(int state __attribute((__unused__)))
applySettings();
}
void SSBModGUI::on_agcOrder_valueChanged(int value){
QString s = QString::number(value / 100.0, 'f', 2);
ui->agcOrderText->setText(s);
applySettings();
}
void SSBModGUI::on_agcTime_valueChanged(int value){
QString s = QString::number(m_agcTimeConstant[value], 'f', 0);
ui->agcTimeText->setText(s);
@ -692,6 +701,7 @@ void SSBModGUI::applySettings()
ui->audioMute->isChecked(),
ui->playLoop->isChecked(),
ui->agc->isChecked(),
ui->agcOrder->value() / 100.0,
m_agcTimeConstant[ui->agcTime->value()],
ui->agcThreshold->value(),
ui->agcThresholdGate->value(),
@ -708,6 +718,8 @@ void SSBModGUI::displaySettings()
ui->agcThresholdGateText->setText(s);
s = QString::number(ui->agcThresholdDelay->value() * 10, 'f', 0);
ui->agcThresholdDelayText->setText(s);
s = QString::number(ui->agcOrder->value() / 100.0, 'f', 2);
ui->agcOrderText->setText(s);
}
void SSBModGUI::displayAGCPowerThreshold(int value)

View File

@ -72,6 +72,7 @@ private slots:
void on_toneFrequency_valueChanged(int value);
void on_mic_toggled(bool checked);
void on_agc_stateChanged(int state);
void on_agcOrder_valueChanged(int value);
void on_agcTime_valueChanged(int value);
void on_agcThreshold_valueChanged(int value);
void on_agcThresholdGate_valueChanged(int value);

View File

@ -475,6 +475,38 @@
</property>
</widget>
</item>
<item>
<widget class="QDial" name="agcOrder">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>AGC volume order in faraction of maximum amplitude</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="agcOrderText">
<property name="toolTip">
<string>AGC volume order in faraction of maximum amplitude</string>
</property>
<property name="text">
<string>0.00</string>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="agcTime">
<property name="maximumSize">
@ -484,7 +516,7 @@
</size>
</property>
<property name="toolTip">
<string>Compressor time constant (attack)</string>
<string>Compressor time constant (attack) in ms</string>
</property>
<property name="minimum">
<number>0</number>
@ -528,7 +560,7 @@
</size>
</property>
<property name="toolTip">
<string>Audio squelch threshold</string>
<string>Audio squelch threshold (db power)</string>
</property>
<property name="minimum">
<number>-99</number>
@ -572,7 +604,7 @@
</size>
</property>
<property name="toolTip">
<string>Audio squelch gate</string>
<string>Audio squelch gate in ms</string>
</property>
<property name="pageStep">
<number>1</number>
@ -610,7 +642,7 @@
</size>
</property>
<property name="toolTip">
<string>Audio squelch delay (release)</string>
<string>Audio squelch delay (release) in ms</string>
</property>
<property name="pageStep">
<number>1</number>

View File

@ -12,7 +12,7 @@
#define StepLengthMax 2400 // 50ms
AGC::AGC(int historySize, Real R) :
AGC::AGC(int historySize, double R) :
m_u0(1.0),
m_R(R),
m_moving_average(historySize, m_R),
@ -23,7 +23,7 @@ AGC::AGC(int historySize, Real R) :
AGC::~AGC()
{}
void AGC::resize(int historySize, Real R)
void AGC::resize(int historySize, double R)
{
m_R = R;
m_moving_average.resize(historySize, R);
@ -73,6 +73,12 @@ void MagAGC::resize(int historySize, Real R)
AGC::resize(historySize, R);
}
void MagAGC::setOrder(double R)
{
m_R2 = R*R;
AGC::setOrder(R);
}
void MagAGC::setThresholdEnable(bool enable)
{
if (m_thresholdEnable != enable)

View File

@ -13,10 +13,11 @@
class AGC
{
public:
AGC(int historySize, Real R);
AGC(int historySize, double R);
virtual ~AGC();
void resize(int historySize, Real R);
void resize(int historySize, double R);
void setOrder(double R) { m_R = R; }
Real getValue();
Real getAverage();
virtual void feed(Complex& ci) = 0;
@ -37,9 +38,10 @@ public:
virtual ~MagAGC();
void setSquared(bool squared) { m_squared = squared; }
void resize(int historySize, Real R);
void setOrder(double R);
virtual void feed(Complex& ci);
double feedAndGetValue(const Complex& ci);
Real getMagSq() const { return m_magsq; }
double getMagSq() const { return m_magsq; }
void setThreshold(double threshold) { m_threshold = threshold; }
void setThresholdEnable(bool enable);
void setGate(int gate) { m_gate = gate; }