情况:
在基于GSM的调制解调器上,您可以使用ATDxxxxxxxxx启动语音呼叫;
当远程端应答时,某些调制解调器发出"CONNECT",或者其他调制解调器在诊断端口上返回"^CONN:1,0"。
但是,如果远程方拒绝呼叫,则仍会发送此连接反馈。
AT+CAS返回4(呼叫进行中)。
AT+CIND(如果支持)返回呼叫正在运行,并且该呼叫未振铃。
有些调制解调器没有在数据端口上发送数据,但另一些调制解调器有(通常发送静音或单音)。
经过长时间后,网络断开呼叫,调制解调器最终在诊断端口上发出"^CEND",或在应用程序端口上发出"HANGUP:1"。
我想尽快检测远程方何时拒绝了呼叫,而不是在网络超时之后。我该怎么做?
编辑:顺便说一句,我说的不是"自动"答录机,而是对电话的明确拒绝(这样它就不会重定向到答录机)。
此外,我希望避免"在数据端口上检测到铃声"之类的解决方案,因为这些解决方案很棘手,而且需要占用大量CPU。
我回答自己的问题,所以它在相同的情况下为其他人服务。
检测取决于网络。通常,在法国的运营商Free中,网络不会在拒绝呼叫时断开连接(而是让你听到铃声)。在德国,确实如此。因此,我认为法国网络的行为是错误的,或者至少没有帮助。
在GSM/3GPP标准中没有特定的用于检测铃音的内容,因此这种网络的唯一方法是以编程方式执行检测。它可以通过检查类似"声音"值之间的时间距离来"简单"地完成。算法是这样的:
int range = 5, value = 350, periodFound = 0; // Arbitrary
int period[16] = {};
void onDataReceived(int sampleRate, short * data, int len)
{
for (int i = 0; i < len; i++)
{
if (data[i] >= value - range && data[i] <= value + range)
{
period[periodFound++] = i;
}
if (periodFound == 16) break;
}
// Compute distance between periods (if it's the same, it's a ring tone)
float avg = 0, dev = 0;
int prev = period[0];
for (int i = 1; i < periodFound; i++)
{
avg += (period[i] - prev);
prev = period[i];
}
avg /= periodFound-1;
prev = period[0];
for (int i = 1; i < periodFound; i++)
{
dev += (period[i] - prev - avg) * (period[i] - prev - avg);
prev = period[i]
}
// Last test
if (fabs(avg - expectedPeriod) < range && dev < errorAllowed)
printf("Ring tone!");
}