Added a continuity check tone detector.

git-svn-id: http://voip.null.ro/svn/yate@3210 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2010-04-19 14:12:31 +00:00
parent 9e7255048f
commit 4f19894de6
1 changed files with 56 additions and 4 deletions

View File

@ -38,6 +38,8 @@ namespace { // anonymous
#define THRESHOLD2_ABS 1e+06
// relative square of spectral power from total signal power
#define THRESHOLD2_REL_FAX 0.95
// same for continuity test tones
#define THRESHOLD2_REL_COT 0.90
// sum of tones (low+high) from total
#define THRESHOLD2_REL_ALL 0.60
// each tone from threshold from total
@ -106,6 +108,7 @@ public:
private:
void checkDtmf();
void checkFax();
void checkCont();
String m_id;
String m_name;
String m_divert;
@ -115,6 +118,7 @@ private:
String m_dnis;
Mode m_mode;
bool m_detFax;
bool m_detCont;
bool m_detDtmf;
bool m_detDnis;
char m_dtmfTone;
@ -122,6 +126,7 @@ private:
double m_xv[3];
double m_pwr;
Tone2PoleFilter m_fax;
Tone2PoleFilter m_cont;
Tone2PoleFilter m_dtmfL[4];
Tone2PoleFilter m_dtmfH[4];
};
@ -170,6 +175,18 @@ static Params2Pole s_paramsCNG =
static Params2Pole s_paramsCED =
{ 8.587870006e+01, -0.9767113407, -0.1551017476 }; // 2100Hz
// generated continuity test verified detector (2010Hz) filter parameters
// mkfilter -Bu -Bp -o 1 -a 2.5025000000e-01 2.5225000000e-01
// -> 2-pole butterworth bandpass, 2010Hz +-8Hz @ -3dB
static Params2Pole s_paramsCOTv =
{ 1.601528486e+02, -0.9875119299, -0.0156100298 }; // 2010Hz
// generated continuity test send detector (1780Hz) filter parameters
// mkfilter -Bu -Bp -o 1 -a 2.1875000000e-01 2.2625000000e-01
// -> 2-pole butterworth bandpass, 1780Hz +-30Hz @ -3dB
static Params2Pole s_paramsCOTs =
{ 4.343337207e+01, -0.9539525559, 0.3360345780 }; // 1780Hz
// generated DTMF component filter parameters
// 2-pole butterworth bandpass, +-1% @ -3dB
static Params2Pole s_paramsDtmfL[] = {
@ -209,8 +226,8 @@ void Tone2PoleFilter::update(double xd)
ToneConsumer::ToneConsumer(const String& id, const String& name)
: m_id(id), m_name(name), m_mode(Mono),
m_detFax(true), m_detDtmf(true), m_detDnis(false),
m_fax(s_paramsCNG)
m_detFax(true), m_detCont(false), m_detDtmf(true), m_detDnis(false),
m_fax(s_paramsCNG), m_cont(s_paramsCOTv)
{
Debug(&plugin,DebugAll,"ToneConsumer::ToneConsumer(%s,'%s') [%p]",
id.c_str(),name.c_str(),this);
@ -232,19 +249,25 @@ ToneConsumer::ToneConsumer(const String& id, const String& name)
m_format = "2*slin";
if (tmp && (tmp != "*")) {
// individual detection requested
m_detFax = m_detDtmf = m_detDnis = false;
m_detFax = m_detCont = m_detDtmf = m_detDnis = false;
ObjList* k = tmp.split(',',false);
for (ObjList* l = k; l; l = l->next()) {
String* s = static_cast<String*>(l->get());
if (!s)
continue;
m_detFax = m_detFax || (*s == "fax");
m_detCont = m_detCont || (*s == "cotv");
m_detDtmf = m_detDtmf || (*s == "dtmf");
if (*s == "rfax") {
// detection of receiving Fax requested
m_fax.assign(s_paramsCED);
m_detFax = true;
}
else if (*s == "cots") {
// detection of COT Send tone requested
m_cont.assign(s_paramsCOTs);
m_detCont = true;
}
else if (*s == "callsetup") {
// call setup info in the form *ANI*DNIS*
m_detDnis = true;
@ -271,6 +294,7 @@ void ToneConsumer::init()
m_xv[1] = m_xv[2] = 0.0;
m_pwr = 0.0;
m_fax.init();
m_cont.init();
for (int i = 0; i < 4; i++) {
m_dtmfL[i].init();
m_dtmfH[i].init();
@ -359,7 +383,7 @@ void ToneConsumer::checkDtmf()
}
}
// Check if we detected a Fax CNG tone
// Check if we detected a Fax CNG or CED tone
void ToneConsumer::checkFax()
{
if (m_fax.value() < m_pwr*THRESHOLD2_REL_FAX)
@ -391,6 +415,30 @@ void ToneConsumer::checkFax()
Engine::enqueue(m);
}
// Check if we detected a Continuity Test tone
void ToneConsumer::checkCont()
{
if (m_cont.value() < m_pwr*THRESHOLD2_REL_COT)
return;
if (m_cont.value() > m_pwr) {
DDebug(&plugin,DebugNote,"Overshoot on %s, signal=%0.2f, total=%0.2f",
m_id.c_str(),m_cont.value(),m_pwr);
init();
return;
}
DDebug(&plugin,DebugInfo,"Continuity detected on %s, signal=%0.1f, total=%0.1f",
m_id.c_str(),m_cont.value(),m_pwr);
// prepare for new detection
init();
m_detCont = false;
Message* m = new Message("chan.masquerade");
m->addParam("id",m_id);
m->addParam("message","chan.dtmf");
m->addParam("text","O");
m->addParam("detected","inband");
Engine::enqueue(m);
}
// Feed samples to the filter(s)
unsigned long ToneConsumer::Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags)
{
@ -429,6 +477,8 @@ unsigned long ToneConsumer::Consume(const DataBlock& data, unsigned long tStamp,
// update all active detectors
if (m_detFax)
m_fax.update(dx);
if (m_detCont)
m_cont.update(dx);
if (m_detDtmf || m_detDnis) {
for (int j = 0; j < 4; j++) {
m_dtmfL[j].update(dx);
@ -444,6 +494,8 @@ unsigned long ToneConsumer::Consume(const DataBlock& data, unsigned long tStamp,
checkDtmf();
if (m_detFax)
checkFax();
if (m_detCont)
checkCont();
}
else {
m_dtmfTone = '\0';