implement support for a silence threshold in DMR (this will help null highly degraded audio to prevent horrifying ear destroying screeching); some minor code cleanup (mostly removing magic numbers!);

pull/12/head
Bryan Biedenkapp 4 years ago
parent d778367583
commit 43f8f6e8ae

@ -41,6 +41,7 @@ protocols:
dumpCsbkData: false
callHang: 5
txHang: 8
silenceThreshold: 21
queueSize: 5000
verbose: true
debug: false
@ -92,7 +93,7 @@ system:
dmrNetId: 1
voiceChNo:
- 1
colorCode: 5
colorCode: 1
nac: 293
pSuperGroup: FFFF
netId: BB800

@ -136,12 +136,22 @@ void Control::setOptions(yaml::Node& conf, uint32_t netId, uint8_t siteId, uint8
m_slot2->setTSCC(enableTSCC, dedicatedTSCC);
break;
default:
LogError(LOG_NET, "DMR, invalid slot, TSCC disabled, slotNo = %u", m_tsccSlotNo);
LogError(LOG_DMR, "DMR, invalid slot, TSCC disabled, slotNo = %u", m_tsccSlotNo);
break;
}
uint32_t silenceThreshold = dmrProtocol["silenceThreshold"].as<uint32_t>(dmr::DEFAULT_SILENCE_THRESHOLD);
if (silenceThreshold > MAX_DMR_VOICE_ERRORS) {
LogWarning(LOG_DMR, "Silence threshold > %u, defaulting to %u", dmr::MAX_DMR_VOICE_ERRORS, dmr::DEFAULT_SILENCE_THRESHOLD);
silenceThreshold = dmr::DEFAULT_SILENCE_THRESHOLD;
}
m_slot1->setSilenceThreshold(silenceThreshold);
m_slot2->setSilenceThreshold(silenceThreshold);
if (printOptions) {
LogInfo(" TSCC Slot: %u", m_tsccSlotNo);
LogInfo(" Silence Threshold: %u (%.1f%%)", silenceThreshold, float(silenceThreshold) / 1.41F);
}
}

@ -99,6 +99,8 @@ namespace dmr
0x81U, 0x52U, 0x60U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x73U, 0x00U,
0x2AU, 0x6BU, 0xB9U, 0xE8U, 0x81U, 0x52U, 0x61U, 0x73U, 0x00U, 0x2AU, 0x6BU };
const uint8_t DMR_NULL_AMBE[] = { 0xB1U, 0xA8U, 0x22U, 0x25U, 0x6BU, 0xD1U, 0x6CU, 0xCFU, 0x67U };
const uint8_t PAYLOAD_LEFT_MASK[] = { 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U };
const uint8_t PAYLOAD_RIGHT_MASK[] = { 0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU };
@ -130,6 +132,9 @@ namespace dmr
const uint16_t DMR_LOGICAL_CH_ABSOLUTE = 0xFFFU;
const uint32_t DEFAULT_SILENCE_THRESHOLD = 21U;
const uint32_t MAX_DMR_VOICE_ERRORS = 141U;
// PDU Data Formats
const uint8_t DPF_UDT = 0x00U;
const uint8_t DPF_RESPONSE = 0x01U;

@ -142,6 +142,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz
m_minRSSI(0U),
m_aveRSSI(0U),
m_rssiCount(0U),
m_silenceThreshold(DEFAULT_SILENCE_THRESHOLD),
m_ccSeq(0U),
m_ccRunning(false),
m_enableTSCC(false),
@ -525,6 +526,15 @@ void Slot::setTSCC(bool enable, bool dedicated)
m_dedicatedTSCC = dedicated;
}
/// <summary>
/// Helper to set the voice error silence threshold.
/// </summary>
/// <param name="threshold"></param>
void Slot::setSilenceThreshold(uint32_t threshold)
{
m_silenceThreshold = threshold;
}
/// <summary>
/// Helper to initialize the DMR slot processor.
/// </summary>

@ -93,6 +93,8 @@ namespace dmr
/// <summary>Helper to enable and configure TSCC support for this slot.</summary>
void setTSCC(bool enable, bool dedicated);
/// <summary>Helper to set the voice error silence threshold.</summary>
void setSilenceThreshold(uint32_t threshold);
/// <summary>Helper to initialize the slot processor.</summary>
static void init(uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem,
@ -156,6 +158,8 @@ namespace dmr
uint32_t m_aveRSSI;
uint32_t m_rssiCount;
uint32_t m_silenceThreshold;
uint8_t m_ccSeq;
bool m_ccRunning;

@ -259,6 +259,13 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
errors, float(errors) / 1.41F);
}
if (errors > m_slot->m_silenceThreshold) {
insertNullAudio(data + 2U);
m_fec.regenerateDMR(data + 2U);
LogWarning(LOG_RF, DMR_DT_VOICE_SYNC ", exceeded lost audio threshold, filling in");
}
m_slot->m_rfErrs += errors;
}
@ -312,6 +319,20 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
m_rfN, errors, float(errors) / 1.41F);
}
if (errors > m_slot->m_silenceThreshold) {
// Get the LCSS from the EMB
data::EMB emb;
emb.decode(data + 2U);
insertNullAudio(data + 2U);
m_fec.regenerateDMR(data + 2U);
// Regenerate EMB
emb.encode(data + 2U);
LogWarning(LOG_RF, DMR_DT_VOICE ", exceeded lost audio threshold, filling in");
}
m_slot->m_rfErrs += errors;
}
@ -540,10 +561,24 @@ bool VoicePacket::process(uint8_t* data, uint32_t len)
if (fid == FID_ETSI || fid == FID_DMRA) {
errors = m_fec.regenerateDMR(data + 2U);
if (m_verbose) {
LogMessage(LOG_RF, "DMR Slot %u, DT_VOICE audio, sequence no = %u, errs = %u/141 (%.1f%%)",
LogMessage(LOG_RF, DMR_DT_VOICE ", audio, slot = %u, sequence no = %u, errs = %u/141 (%.1f%%)",
m_slot->m_slotNo, m_rfN, errors, float(errors) / 1.41F);
}
if (errors > m_slot->m_silenceThreshold) {
// Get the LCSS from the EMB
data::EMB emb;
emb.decode(data + 2U);
insertNullAudio(data + 2U);
m_fec.regenerateDMR(data + 2U);
// Regenerate EMB
emb.encode(data + 2U);
LogWarning(LOG_RF, DMR_DT_VOICE ", exceeded lost audio threshold, filling in");
}
m_slot->m_rfErrs += errors;
}
@ -1121,6 +1156,27 @@ void VoicePacket::logGPSPosition(const uint32_t srcId, const uint8_t* data)
LogMessage(LOG_DMR, "GPS position for %u [lat %f, long %f] (Position error %s)", srcId, latitude, longitude, error);
}
/// <summary>
/// Helper to insert AMBE null frames for missing audio.
/// </summary>
/// <param name="data"></param>
void VoicePacket::insertNullAudio(uint8_t* data)
{
uint8_t* ambeBuffer = new uint8_t[dmr::DMR_AMBE_LENGTH_BYTES];
::memset(ambeBuffer, 0x00U, dmr::DMR_AMBE_LENGTH_BYTES);
for (uint32_t i = 0; i < 3U; i++) {
::memcpy(ambeBuffer + (i * 9U), DMR_NULL_AMBE, 9U);
}
::memcpy(data, ambeBuffer, 13U);
data[13U] = ambeBuffer[13U] & 0xF0U;
data[19U] = ambeBuffer[13U] & 0x0FU;
::memcpy(data + 20U, ambeBuffer + 14U, 13U);
delete[] ambeBuffer;
}
/// <summary>
/// Helper to insert DMR AMBE silence frames.
/// </summary>

@ -105,6 +105,8 @@ namespace dmr
/// <summary></summary>
void logGPSPosition(const uint32_t srcId, const uint8_t* data);
/// <summary>Helper to insert AMBE null frames for missing audio.</summary>
void insertNullAudio(uint8_t* data);
/// <summary>Helper to insert DMR AMBE silence frames.</summary>
bool insertSilence(const uint8_t* data, uint8_t seqNo);
/// <summary>Helper to insert DMR AMBE silence frames.</summary>

@ -214,6 +214,10 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
m_ackTSBKRequests = control["ackRequests"].as<bool>(true);
m_voice->m_silenceThreshold = p25Protocol["silenceThreshold"].as<uint32_t>(p25::DEFAULT_SILENCE_THRESHOLD);
if (m_voice->m_silenceThreshold > MAX_P25_VOICE_ERRORS) {
LogWarning(LOG_P25, "Silence threshold > %u, defaulting to %u", p25::MAX_P25_VOICE_ERRORS, p25::DEFAULT_SILENCE_THRESHOLD);
m_voice->m_silenceThreshold = p25::DEFAULT_SILENCE_THRESHOLD;
}
m_disableNetworkHDU = p25Protocol["disableNetworkHDU"].as<bool>(false);

@ -202,6 +202,7 @@ namespace p25
const uint32_t P25_TGID_ALL = 0xFFFFU;
const uint32_t DEFAULT_SILENCE_THRESHOLD = 124U;
const uint32_t MAX_P25_VOICE_ERRORS = 1233U;
// PDU Format Type(s)
const uint8_t PDU_FMT_RSP = 0x03U;

@ -889,7 +889,7 @@ VoicePacket::VoicePacket(Control* p25, network::BaseNetwork* network, bool debug
m_hadVoice(false),
m_lastRejectId(0U),
m_lastPatchGroup(0U),
m_silenceThreshold(124U),
m_silenceThreshold(DEFAULT_SILENCE_THRESHOLD),
m_vocLDU1Count(0U),
m_verbose(verbose),
m_debug(debug)

Loading…
Cancel
Save

Powered by TurnKey Linux.