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 audioMute,
bool playLoop, bool playLoop,
bool agc, bool agc,
float agcOrder,
int agcTime, int agcTime,
int agcThreshold, int agcThreshold,
int agcThresholdGate, int agcThresholdGate,
@ -151,6 +152,7 @@ void SSBMod::configure(MessageQueue* messageQueue,
audioMute, audioMute,
playLoop, playLoop,
agc, agc,
agcOrder,
agcTime, agcTime,
agcThreshold, agcThreshold,
agcThresholdGate, agcThresholdGate,
@ -617,6 +619,7 @@ bool SSBMod::handleMessage(const Message& cmd)
m_config.m_agc = cfg.getAGC(); m_config.m_agc = cfg.getAGC();
m_config.m_agcTime = 48 * cfg.getAGCTime(); // ms m_config.m_agcTime = 48 * cfg.getAGCTime(); // ms
m_config.m_agcOrder = cfg.getAGCOrder();
m_config.m_agcThresholdEnable = cfg.getAGCThreshold() != -99; m_config.m_agcThresholdEnable = cfg.getAGCThreshold() != -99;
m_config.m_agcThreshold = CalcDb::powerFromdB(cfg.getAGCThreshold()); // power dB m_config.m_agcThreshold = CalcDb::powerFromdB(cfg.getAGCThreshold()); // power dB
m_config.m_agcThresholdGate = 48 * cfg.getAGCThresholdGate(); // ms 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) 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_audioMute = m_config.m_audioMute;
m_running.m_playLoop = m_config.m_playLoop; m_running.m_playLoop = m_config.m_playLoop;
m_running.m_agc = m_config.m_agc; 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_agcTime = m_config.m_agcTime;
m_running.m_agcThresholdEnable = m_config.m_agcThresholdEnable; m_running.m_agcThresholdEnable = m_config.m_agcThresholdEnable;
m_running.m_agcThreshold = m_config.m_agcThreshold; m_running.m_agcThreshold = m_config.m_agcThreshold;

View File

@ -189,6 +189,7 @@ public:
bool audioMute, bool audioMute,
bool playLoop, bool playLoop,
bool agc, bool agc,
float agcOrder,
int agcTime, int agcTime,
int agcThreshold, int agcThreshold,
int agcThresholdGate, int agcThresholdGate,
@ -231,6 +232,7 @@ private:
bool getAudioMute() const { return m_audioMute; } bool getAudioMute() const { return m_audioMute; }
bool getPlayLoop() const { return m_playLoop; } bool getPlayLoop() const { return m_playLoop; }
bool getAGC() const { return m_agc; } bool getAGC() const { return m_agc; }
float getAGCOrder() const { return m_agcOrder; }
int getAGCTime() const { return m_agcTime; } int getAGCTime() const { return m_agcTime; }
int getAGCThreshold() const { return m_agcThreshold; } int getAGCThreshold() const { return m_agcThreshold; }
int getAGCThresholdGate() const { return m_agcThresholdGate; } int getAGCThresholdGate() const { return m_agcThresholdGate; }
@ -247,6 +249,7 @@ private:
bool audioMute, bool audioMute,
bool playLoop, bool playLoop,
bool agc, bool agc,
float agcOrder,
int agcTime, int agcTime,
int agcThreshold, int agcThreshold,
int agcThresholdGate, int agcThresholdGate,
@ -263,6 +266,7 @@ private:
audioMute, audioMute,
playLoop, playLoop,
agc, agc,
agcOrder,
agcTime, agcTime,
agcThreshold, agcThreshold,
agcThresholdGate, agcThresholdGate,
@ -281,6 +285,7 @@ private:
bool m_audioMute; bool m_audioMute;
bool m_playLoop; bool m_playLoop;
bool m_agc; bool m_agc;
float m_agcOrder;
int m_agcTime; int m_agcTime;
int m_agcThreshold; int m_agcThreshold;
int m_agcThresholdGate; int m_agcThresholdGate;
@ -297,6 +302,7 @@ private:
bool audioMute, bool audioMute,
bool playLoop, bool playLoop,
bool agc, bool agc,
float agcOrder,
int agcTime, int agcTime,
int agcThreshold, int agcThreshold,
int agcThresholdGate, int agcThresholdGate,
@ -313,6 +319,7 @@ private:
m_audioMute(audioMute), m_audioMute(audioMute),
m_playLoop(playLoop), m_playLoop(playLoop),
m_agc(agc), m_agc(agc),
m_agcOrder(agcOrder),
m_agcTime(agcTime), m_agcTime(agcTime),
m_agcThreshold(agcThreshold), m_agcThreshold(agcThreshold),
m_agcThresholdGate(agcThresholdGate), m_agcThresholdGate(agcThresholdGate),
@ -349,6 +356,7 @@ private:
bool m_audioMute; bool m_audioMute;
bool m_playLoop; bool m_playLoop;
bool m_agc; bool m_agc;
float m_agcOrder;
int m_agcTime; int m_agcTime;
bool m_agcThresholdEnable; bool m_agcThresholdEnable;
double m_agcThreshold; double m_agcThreshold;
@ -371,6 +379,7 @@ private:
m_audioMute(false), m_audioMute(false),
m_playLoop(false), m_playLoop(false),
m_agc(false), m_agc(false),
m_agcOrder(0.2),
m_agcTime(9600), m_agcTime(9600),
m_agcThresholdEnable(true), m_agcThresholdEnable(true),
m_agcThreshold(1e-4), m_agcThreshold(1e-4),

View File

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

View File

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

View File

@ -475,6 +475,38 @@
</property> </property>
</widget> </widget>
</item> </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> <item>
<widget class="QDial" name="agcTime"> <widget class="QDial" name="agcTime">
<property name="maximumSize"> <property name="maximumSize">
@ -484,7 +516,7 @@
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Compressor time constant (attack)</string> <string>Compressor time constant (attack) in ms</string>
</property> </property>
<property name="minimum"> <property name="minimum">
<number>0</number> <number>0</number>
@ -528,7 +560,7 @@
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Audio squelch threshold</string> <string>Audio squelch threshold (db power)</string>
</property> </property>
<property name="minimum"> <property name="minimum">
<number>-99</number> <number>-99</number>
@ -572,7 +604,7 @@
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Audio squelch gate</string> <string>Audio squelch gate in ms</string>
</property> </property>
<property name="pageStep"> <property name="pageStep">
<number>1</number> <number>1</number>
@ -610,7 +642,7 @@
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Audio squelch delay (release)</string> <string>Audio squelch delay (release) in ms</string>
</property> </property>
<property name="pageStep"> <property name="pageStep">
<number>1</number> <number>1</number>

View File

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

View File

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