Added silence detection in voice receive mode.

This commit is contained in:
Armin Schindler 1998-07-26 18:48:45 +00:00
parent 3cfb46944c
commit 724fa0901a
5 changed files with 153 additions and 31 deletions

View File

@ -50,10 +50,11 @@ The following commands are supported:
the application. See below for data format
AT+VSD=x,y Set silence-detection parameters.
NO EFFECT, supported for compatibility
only. Possible parameters:
x = 0 ... 31
y = 0 ... 255
Possible parameters:
x = 0 ... 31 sensitivity threshold level.
(default 0 , deactivated)
y = 0 ... 255 range of interval in units
of 0.1 second. (default 70)
AT+VSD=? Report possible parameters.
AT+VSD? Show current parameters.
@ -102,13 +103,14 @@ General behavior and description of data formats/protocol.
<DLE>C Touchtone "C" received.
<DLE>D Touchtone "D" received.
<DLE>q quiet. Silence detected after non-silence.
<DLE>s silence. Silence detected from the
start of recording.
Currently unsupported DLE sequences:
<DLE>c FAX calling tone received.
<DLE>b busy tone received.
<DLE>q quiet. Silence detected after non-silence.
<DLE>s silence. Silence detected from the
start of recording.
Audio playback.

View File

@ -4,6 +4,7 @@
*
* Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
* DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
* Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,6 +21,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.11 1998/04/10 10:35:10 paul
* fixed (silly?) warnings from egcs on Alpha.
*
* Revision 1.10 1998/02/20 17:09:40 fritz
* Changes for recent kernels.
*
@ -660,3 +664,92 @@ isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
len -= c;
}
}
silence_state *
isdn_audio_silence_init(silence_state * s)
{
if (!s)
s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
if (s) {
s->idx = 0;
s->state = 0;
}
return s;
}
void
isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
{
silence_state *s = info->silence_state;
int i;
signed char c;
if (!info->emu.vpar[1]) return;
for (i = 0; i < len; i++) {
if (fmt)
c = isdn_audio_alaw_to_ulaw[*buf++];
else
c = *buf++;
if (c > 0) c -= 128;
c = abs(c);
if (c > (info->emu.vpar[1] * 4)) {
s->idx = 0;
s->state = 1;
} else {
if (s->idx < 210000) s->idx++;
}
}
}
void
isdn_audio_eval_silence(modem_info * info)
{
silence_state *s = info->silence_state;
struct sk_buff *skb;
unsigned long flags;
int di;
int ch;
char what;
char *p;
what = ' ';
if (s->idx > (info->emu.vpar[2] * 800)) {
s->idx = 0;
if (!s->state) { /* silence from beginning of rec */
what = 's';
} else {
what = 'q';
}
}
if ((what == 's') || (what == 'q')) {
printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
(what=='s') ? "silence":"quiet");
skb = dev_alloc_skb(2);
p = (char *) skb_put(skb, 2);
p[0] = 0x10;
p[1] = what;
if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
printk(KERN_WARNING
"isdn_audio: insufficient skb_headroom, dropping\n");
kfree_skb(skb);
return;
}
ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
ISDN_AUDIO_SKB_LOCK(skb) = 0;
save_flags(flags);
cli();
di = info->isdn_driver;
ch = info->isdn_channel;
__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
dev->drv[di]->rcvcount[ch] += 2;
restore_flags(flags);
/* Schedule dequeuing */
if ((dev->modempoll) && (info->rcvsched))
isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
}
}

View File

@ -19,6 +19,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.5 1997/02/03 22:45:21 fritz
* Reformatted according CodingStyle
*
* Revision 1.4 1996/06/06 14:43:32 fritz
* Changed to support DTMF decoding on audio playback also.
*
@ -48,6 +51,11 @@ typedef struct dtmf_state {
int buf[DTMF_NPOINTS];
} dtmf_state;
typedef struct silence_state {
int state;
unsigned int idx;
} silence_state;
extern void isdn_audio_ulaw2alaw(unsigned char *, unsigned long);
extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long);
extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int);
@ -57,3 +65,6 @@ extern int isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out);
extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
extern void isdn_audio_eval_dtmf(modem_info *);
dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int);
extern void isdn_audio_eval_silence(modem_info *);
silence_state *isdn_audio_silence_init(silence_state *);

View File

@ -20,6 +20,11 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.57 1998/06/26 15:12:36 fritz
* Added handling of STAT_ICALL with incomplete CPN.
* Added AT&L for ttyI emulator.
* Added more locking stuff in tty_write.
*
* Revision 1.56 1998/06/18 23:31:51 fritz
* Replaced cli()/restore_flags() in isdn_tty_write() by locking.
* Removed direct-senddown feature in isdn_tty_write because it will
@ -425,6 +430,8 @@ isdn_tty_readmodem(void)
r = 0;
#ifdef CONFIG_ISDN_AUDIO
isdn_audio_eval_dtmf(info);
if (info->emu.vpar[1])
isdn_audio_eval_silence(info);
#endif
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
@ -481,6 +488,8 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
if (info->vonline)
isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
if ((info->vonline & 1) && (info->emu.vpar[1]))
isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
#endif
if ((info->online < 2)
#ifdef CONFIG_ISDN_AUDIO
@ -3462,6 +3471,11 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info)
printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
PARSE_ERROR1;
}
info->silence_state = isdn_audio_silence_init(info->silence_state);
if (!info->silence_state) {
printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n");
PARSE_ERROR1;
}
if (m->vpar[3] < 5) {
info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
if (!info->adpcmr) {
@ -3488,31 +3502,27 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info)
break;
case '=':
p[0]++;
switch (*p[0]) {
case '0':
case '1':
case '2':
case '3':
par1 = isdn_getnum(p);
if ((par1 < 0) || (par1 > 31))
PARSE_ERROR1;
if (*p[0] != ',')
PARSE_ERROR1;
p[0]++;
par2 = isdn_getnum(p);
if ((par2 < 0) || (par2 > 255))
PARSE_ERROR1;
m->vpar[1] = par1;
m->vpar[2] = par2;
break;
case '?':
p[0]++;
isdn_tty_at_cout("\r\n<0-31>,<0-255>",
info);
break;
default:
if ((*p[0]>='0') && (*p[0]<='9')) {
par1 = isdn_getnum(p);
if ((par1 < 0) || (par1 > 31))
PARSE_ERROR1;
}
if (*p[0] != ',')
PARSE_ERROR1;
p[0]++;
par2 = isdn_getnum(p);
if ((par2 < 0) || (par2 > 255))
PARSE_ERROR1;
m->vpar[1] = par1;
m->vpar[2] = par2;
break;
} else
if (*p[0] == '?') {
p[0]++;
isdn_tty_at_cout("\r\n<0-31>,<0-255>",
info);
break;
} else
PARSE_ERROR1;
break;
default:
PARSE_ERROR1;

View File

@ -21,6 +21,11 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.55 1998/06/26 15:13:17 fritz
* Added handling of STAT_ICALL with incomplete CPN.
* Added AT&L for ttyI emulator.
* Added more locking stuff in tty_write.
*
* Revision 1.54 1998/06/18 23:32:01 fritz
* Replaced cli()/restore_flags() in isdn_tty_write() by locking.
* Removed direct-senddown feature in isdn_tty_write because it will
@ -716,6 +721,7 @@ typedef struct modem_info {
void *adpcms; /* state for adpcm decompression */
void *adpcmr; /* state for adpcm compression */
void *dtmf_state; /* state for dtmf decoder */
void *silence_state; /* state for silence detection */
#endif
struct tty_struct *tty; /* Pointer to corresponding tty */
atemu emu; /* AT-emulator data */