Merge remote-tracking branch 'sm0svx/master' into coder-init

This commit is contained in:
Adi Bier / DL1HRC 2020-12-25 16:16:11 +01:00
commit e7f68a27b5
9 changed files with 104 additions and 33 deletions

View File

@ -918,6 +918,14 @@ close it when it does not have to be open anymore. This may cause problems in
some applications or with some sound hardware. Set this variable to 1 to force
SvxLink to keep the audio device open from application start to exit.
.TP
.B LIMITER_THRESH
Set the threshold, in dBFS, for the audio limiter. The audio limiter really is
a compressor with a very steep compression ratio like 10:1. The limiter is
used to help keeping down the audio level for overmodulating stations. For a
properly calibrated SvxLink node max FM deviation is -6dBFS. A good value to
start with for this parameter is then -6 but try to lower it further (like -9
to -12) if it does not affect audio quality negatively.
.TP
.B SQL_DET
Specify the type of squelch detector to use. Possible values are: VOX, CTCSS,
SERIAL, EVDEV, SIGLEV, PTY, GPIO, HIDRAW or COMBINE.
@ -2001,6 +2009,14 @@ close it when it does not have to be open anymore. This may cause problems in
some applications or with some sound hardware. Set this variable to 1 to force
SvxLink to keep the audio device open from application start to exit.
.TP
.B LIMITER_THRESH
Set the threshold, in dBFS, for the audio limiter. The audio limiter really is
a compressor with a very steep compression ratio like 10:1. The limiter is
used to help keeping down the audio level to not overmodulate the transmitter.
For a properly calibrated SvxLink node max FM deviation is -6dBFS. A good value
to start with for this parameter is then -6 but try to lower it further (like
-9 to -12) if it does not affect audio quality negatively.
.TP
.B PTT_TYPE
Use this configuration variable to specify which type of hardware to use to
control the PTT. Specify "SerialPin" for using a pin in the serial port,

View File

@ -84,6 +84,23 @@
* Use the new configuration variable COMMAND_PTY to set up a PTY that can be
used to send commands to a logic core.
* Filter out CTCSS band for voice output. Interference on CTCSS transmission
could be caused by low frequency content in audio clips or incoming audio on
Echolink for example.
* Ignore prioritized talkgroups qfter QSY if there have been local node
activity prior to the QSY. This fix a problem where a node would switch to a
prioritized talkgroup after a QSY to a lower priority talkgroup, if there
have been no local activity after the QSY. Priority will be honored again
after the node have switched to TG#0.
* Make the audio limiter threshold in the receiver configurable using the
LIMITER_THRESH configuration variable in a receiver configuration section.
* Add an audio limiter to the transmitted audio path. The threshold may be set
using the LIMITER_THRESH configuration variable in a TX configuration
section.
1.7.0 -- 01 Sep 2019

View File

@ -53,6 +53,7 @@ TYPE=Local
#RX_ID=?
AUDIO_DEV=alsa:plughw:0
AUDIO_CHANNEL=0
LIMITER_THRESH=-6
SQL_DET=VOX
SQL_START_DELAY=0
SQL_DELAY=0
@ -121,6 +122,7 @@ DTMF_SERIAL=/dev/ttyS0
TYPE=Local
AUDIO_DEV=alsa:plughw:0
AUDIO_CHANNEL=0
LIMITER_THRESH=-6
PTT_TYPE=NONE
PTT_PORT=/dev/ttyS0
PTT_PIN=DTRRTS

View File

@ -138,7 +138,7 @@ ReflectorLogic::ReflectorLogic(Async::Config& cfg, const std::string& name)
m_tg_local_activity(false), m_last_qsy(0), m_logic_con_in_valve(0),
m_mute_first_tx_loc(true), m_mute_first_tx_rem(false),
m_tmp_monitor_timer(1000, Async::Timer::TYPE_PERIODIC),
m_tmp_monitor_timeout(DEFAULT_TMP_MONITOR_TIMEOUT)
m_tmp_monitor_timeout(DEFAULT_TMP_MONITOR_TIMEOUT), m_use_prio(true)
{
m_reconnect_timer.expired.connect(
sigc::hide(mem_fun(*this, &ReflectorLogic::reconnect)));
@ -400,6 +400,7 @@ void ReflectorLogic::remoteCmdReceived(LogicBase* src_logic,
{
selectTg(tg, "tg_command_activation", true);
m_tg_local_activity = true;
m_use_prio = false;
}
else
{
@ -410,6 +411,7 @@ void ReflectorLogic::remoteCmdReceived(LogicBase* src_logic,
{
selectTg(m_previous_tg, "tg_command_activation", true);
m_tg_local_activity = true;
m_use_prio = false;
}
}
else if (cmd[0] == '2') // QSY
@ -448,6 +450,7 @@ void ReflectorLogic::remoteCmdReceived(LogicBase* src_logic,
{
selectTg(m_last_qsy, "tg_command_activation", true);
m_tg_local_activity = true;
m_use_prio = false;
}
else
{
@ -510,6 +513,7 @@ void ReflectorLogic::remoteReceivedTgUpdated(LogicBase *logic, uint32_t tg)
{
selectTg(tg, "tg_local_activation", !m_mute_first_tx_loc);
m_tg_local_activity = true;
m_use_prio = false;
}
} /* ReflectorLogic::remoteReceivedTgUpdated */
@ -1051,7 +1055,7 @@ void ReflectorLogic::handleMsgTalkerStart(std::istream& is)
{
selectTg(msg.tg(), "tg_remote_activation", !m_mute_first_tx_rem);
}
else
else if (m_use_prio)
{
uint32_t selected_tg_prio = 0;
MonitorTgsSet::const_iterator selected_tg_it =
@ -1063,8 +1067,7 @@ void ReflectorLogic::handleMsgTalkerStart(std::istream& is)
MonitorTgsSet::const_iterator talker_tg_it =
m_monitor_tgs.find(MonitorTgEntry(msg.tg()));
if ((talker_tg_it != m_monitor_tgs.end()) &&
(talker_tg_it->prio > selected_tg_prio) &&
!m_tg_local_activity)
(talker_tg_it->prio > selected_tg_prio))
{
std::cout << name() << ": Activity on prioritized TG #"
<< msg.tg() << ". Switching!" << std::endl;
@ -1516,6 +1519,7 @@ void ReflectorLogic::onLogicConInStreamStateChanged(bool is_active,
}
}
m_tg_local_activity = true;
m_use_prio = false;
m_tg_select_timeout_cnt = m_tg_select_timeout;
}
@ -1580,7 +1584,15 @@ void ReflectorLogic::selectTg(uint32_t tg, const std::string& event, bool unmute
m_previous_tg = m_selected_tg;
}
m_selected_tg = tg;
m_tg_local_activity = false;
if (tg == 0)
{
m_tg_local_activity = false;
m_use_prio = true;
}
else
{
m_tg_local_activity = !m_logic_con_in->isIdle();
}
m_event_handler->setVariable(name() + "::selected_tg", m_selected_tg);
m_event_handler->setVariable(name() + "::previous_tg", m_previous_tg);
}

View File

@ -254,6 +254,7 @@ class ReflectorLogic : public LogicBase
bool m_mute_first_tx_rem;
Async::Timer m_tmp_monitor_timer;
int m_tmp_monitor_timeout;
bool m_use_prio;
ReflectorLogic(const ReflectorLogic&);
ReflectorLogic& operator=(const ReflectorLogic&);

View File

@ -186,6 +186,7 @@ TYPE=Local
AUDIO_DEV=alsa:plughw:0
AUDIO_CHANNEL=0
#AUDIO_DEV_KEEP_OPEN=0
LIMITER_THRESH=-6
SQL_DET=VOX
SQL_START_DELAY=0
SQL_DELAY=0
@ -258,6 +259,7 @@ TX_ID=T
AUDIO_DEV=alsa:plughw:0
AUDIO_CHANNEL=0
#AUDIO_DEV_KEEP_OPEN=0
LIMITER_THRESH=-6
PTT_TYPE=NONE
PTT_PORT=/dev/ttyS0
PTT_PIN=DTRRTS

View File

@ -103,9 +103,10 @@ using namespace Async;
*
****************************************************************************/
#define DTMF_MUTING_POST 200
#define TONE_1750_MUTING_PRE 75
#define TONE_1750_MUTING_POST 100
#define DTMF_MUTING_POST 200
#define TONE_1750_MUTING_PRE 75
#define TONE_1750_MUTING_POST 100
#define DEFAULT_LIMITER_THRESH -1.0
/****************************************************************************
@ -593,15 +594,20 @@ bool LocalRxBase::initialize(void)
prev_src = delay;
}
// Add a limiter to smoothly limiting the audio before hard clipping it
AudioCompressor *limit = new AudioCompressor;
limit->setThreshold(-1);
limit->setRatio(0.1);
limit->setAttack(2);
limit->setDecay(20);
limit->setOutputGain(1);
prev_src->registerSink(limit, true);
prev_src = limit;
// Add a limiter to smoothly limit the audio before hard clipping it
double limiter_thresh = DEFAULT_LIMITER_THRESH;
cfg().getValue(name(), "LIMITER_THRESH", limiter_thresh);
if (limiter_thresh != 0.0)
{
AudioCompressor *limit = new AudioCompressor;
limit->setThreshold(limiter_thresh);
limit->setRatio(0.1);
limit->setAttack(2);
limit->setDecay(20);
limit->setOutputGain(1);
prev_src->registerSink(limit, true);
prev_src = limit;
}
// Clip audio to limit its amplitude
AudioClipper *clipper = new AudioClipper;

View File

@ -112,7 +112,8 @@ using namespace SvxLink;
*
****************************************************************************/
#define USE_AUDIO_VALVE 0
#define USE_AUDIO_VALVE 0
#define DEFAULT_LIMITER_THRESH 0.0
/****************************************************************************
@ -471,24 +472,28 @@ bool LocalTx::initialize(void)
prev_src->registerSink(preemph, true);
prev_src = preemph;
}
/*
AudioCompressor *limit = new AudioCompressor;
limit->setThreshold(-1);
limit->setRatio(0.1);
limit->setAttack(2);
limit->setDecay(20);
limit->setOutputGain(1);
prev_src->registerSink(limit, true);
prev_src = limit;
*/
// Add a limiter to smoothly limit the audio before hard clipping it
double limiter_thresh = DEFAULT_LIMITER_THRESH;
cfg.getValue(name(), "LIMITER_THRESH", limiter_thresh);
if (limiter_thresh != 0.0)
{
AudioCompressor *limit = new AudioCompressor;
limit->setThreshold(limiter_thresh);
limit->setRatio(0.1);
limit->setAttack(2);
limit->setDecay(20);
limit->setOutputGain(1);
prev_src->registerSink(limit, true);
prev_src = limit;
}
// Clip audio to limit its amplitude
AudioClipper *clipper = new AudioClipper;
prev_src->registerSink(clipper, true);
prev_src = clipper;
#if 1
#if 0
// Filter out high frequencies generated by the previous clipping
#if (INTERNAL_SAMPLE_RATE == 16000)
//AudioFilter *splatter_filter = new AudioFilter("LpBu10/5500");
@ -499,7 +504,17 @@ bool LocalTx::initialize(void)
prev_src->registerSink(splatter_filter, true);
prev_src = splatter_filter;
#endif
#if (INTERNAL_SAMPLE_RATE == 16000)
AudioFilter *voiceband_filter =
new AudioFilter("LpCh9/-0.05/5500 x HpCh12/-0.05/300");
#else
AudioFilter *voiceband_filter =
new AudioFilter("LpBu20/3500 x HpCh12/-0.05/300");
#endif
prev_src->registerSink(voiceband_filter, true);
prev_src = voiceband_filter;
// Create a valve so that we can control when to transmit audio
#if USE_AUDIO_VALVE
audio_valve = new AudioValve;

View File

@ -11,7 +11,7 @@ LIBECHOLIB=1.3.3
LIBASYNC=1.6.0.99.11
# SvxLink versions
SVXLINK=1.7.99.26
SVXLINK=1.7.99.29
MODULE_HELP=1.0.0
MODULE_PARROT=1.1.1
MODULE_ECHO_LINK=1.5.99.0