1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-04 09:09:56 +00:00

add the dtmfdecode program (added to i4b with 0.71.00) to the i4b userland

This commit is contained in:
Hellmuth Michaelis 1999-03-07 17:09:03 +00:00
parent e90bc52dbe
commit bb7ca167ae
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=44554
5 changed files with 279 additions and 1 deletions

View File

@ -1,4 +1,4 @@
SUBDIR = isdntrace isdndebug isdnd alawulaw man isdntest \
isdntel isdntelctl isdnmonitor isdndecode
isdntel isdntelctl isdnmonitor isdndecode dtmfdecode
.include <bsd.subdir.mk>

View File

@ -0,0 +1,15 @@
#---------------------------------------------------------------------------
#
# $Id: Makefile,v 1.1 1999/02/15 19:13:47 hm Exp $
#
# last edit-date: [Mon Feb 15 20:04:40 1999]
#
#---------------------------------------------------------------------------
PROG = dtmfdecode
SRC = dtmfdecode.c
LDADD += -lm
CFLAGS += -Wall -g -DDEBUG
MAN1 = dtmfdecode.1
.include <bsd.prog.mk>

View File

@ -0,0 +1,44 @@
[Note: the version included in i4b does not output any data you can
plot, but will just print the values of the tones it detected. -hm]
Poul-Henning Kamp wrote:
------------------------
I remember that somebody asked about this long time ago, so I sat
down and hacked a digital filter for that.
The following piece of code will read a ".g711a" file, and output
9 columns of data. The first is the linear value of the sample,
the other 8 are strength of the 8 DTMF tones.
Try to run the "beep.g711a" file from i4b through it, and plot the
output columns with gnuplot. It seems Hellmuth pressed a '1' :-)
The implementation is a recursive resonance filter, actually 8 of
them, one for each frequency, done in floating point. With a little
attention to rounding, it can be done just as good, and much faster
in integer math, in fact 16 bit should be enough, but may not be
faster than 32bit.
The "POLRAD" quantity determines the resonance width of the filters,
if you make it too low, it will confuse tones and recognize them
where they are not. If you make it too high (never, ever >= 1.0!)
it will take longer to react and maybe not catch a slightly offbeat
tone. If you set it above or equal to 1.0 you get a tone generator.
This could also be a good basis for a 300Baud FSK modem emulation.
It seems that the .g711a files are bit-flipped, therefore the flip[]
array trick in this code. The alaw->linear converter is lifted from
sox.
Now, who writes the answering-machine to end all answering machines
for i4b ?
Poul-Henning
--
Poul-Henning Kamp FreeBSD coreteam member
phk@FreeBSD.ORG "Real hackers run -current on their laptop."
"ttyv0" -- What UNIX calls a $20K state-of-the-art, 3D, hi-res color terminal

View File

@ -0,0 +1,61 @@
.\"
.\" Copyright (c) 1999 Hellmuth Michaelis. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: dtmfdecode.1,v 1.1 1999/02/15 19:13:47 hm Exp $
.\"
.\" last edit-date: [Mon Feb 15 20:11:30 1999]
.\"
.\"
.Dd February, 15 1999
.Dt dtmfdecode 1
.Sh NAME
.Nm dtmfdecode
.Nd decodes DTMF tones from i4b .g711a files
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
.Nm dtmfdecode
is part of the isdn4bsd package and is used to detect DTMF tones in the
audio stream.
.Pp
It reads audio G.711 A-Law coded data from stdin and outputs the detected
numbers values as ASCII charcters to stdout.
.Pp
.Sh EXAMPLES
The command:
.Bd -literal -offset indent
dtmfdecode < beep.g711a
.Ed
.Pp
will print a "1" to stdout.
.Sh STANDARDS
ITU Recommendations G.711
.Sh AUTHOR
The
.Nm
utility was written by Poul-Henning Kamp, phk@freebsd.org. This man page
was written by Hellmuth Michaelis, hm@freebsd.org.

View File

@ -0,0 +1,158 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $Id: dtmfdecode.c,v 1.1 1999/02/15 19:13:47 hm Exp $
*
* Extract DTMF signalling from a .g711a file from ISDN4BSD
*
* A-Law to linear conversion from the sox package.
*
*/
#include <stdio.h>
#include <math.h>
/*
* g711.c
*
* u-law, A-law and linear PCM conversions.
*/
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
#define QUANT_MASK (0xf) /* Quantization field mask. */
#define NSEGS (8) /* Number of A-law segments. */
#define SEG_SHIFT (4) /* Left shift for segment number. */
#define SEG_MASK (0x70) /* Segment field mask. */
/*
* alaw2linear() - Convert an A-law value to 16-bit linear PCM
*
*/
int
alaw2linear(a_val)
unsigned char a_val;
{
int t;
int seg;
a_val ^= 0x55;
t = (a_val & QUANT_MASK) << 4;
seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
switch (seg) {
case 0:
t += 8;
break;
case 1:
t += 0x108;
break;
default:
t += 0x108;
t <<= seg - 1;
}
return ((a_val & SIGN_BIT) ? t : -t);
}
int flip[256];
double dtmf[8] = {697, 770, 852, 941, 1209, 1336, 1477, 1633};
double p1[8];
/* This is the Q of the filter (pole radius). must be less than 1.0 */
#define POLRAD .99
#define P2 (POLRAD*POLRAD)
#define NNN 100
char key [256];
int
main(int argc, char **argv)
{
int i, j, kk, nn, s, so = 0;
double x, a[8], b[8], c[8], d[8], e[8], f[8], g[8], h[8], k[8], l[8], m[8], n[8], y[8];
for (kk = 0; kk < 8; kk++) {
y[kk] = g[kk] = k[kk] = 0.0;
p1[kk] = (-cos(2 * 3.141592 * dtmf[kk] / 8000.0));
}
for (i=0;i<256;i++) {
key[i] = '\0';
flip[i] = (i & 1) << 7;
flip[i] |= (i & 2) << 5;
flip[i] |= (i & 4) << 3;
flip[i] |= (i & 8) << 1;
flip[i] |= (i & 16) >> 1;
flip[i] |= (i & 32) << 3;
flip[i] |= (i & 64) << 5;
flip[i] |= (i & 128) << 7;
}
key[0x00] = '\0';
key[0x11] = '1';
key[0x12] = '4';
key[0x14] = '7';
key[0x18] = '*';
key[0x21] = '2';
key[0x22] = '5';
key[0x24] = '8';
key[0x28] = '0';
key[0x41] = '3';
key[0x42] = '6';
key[0x44] = '9';
key[0x48] = '#';
key[0x81] = 'A';
key[0x82] = 'B';
key[0x84] = 'C';
key[0x88] = 'D';
x = 0.0;
nn = 0;
while ((i = getchar()) != EOF) {
i = flip[i];
j = alaw2linear(i);
x = j / 32768.0;
s = 0;
for(kk = 0; kk < 8; kk++) {
a[kk] = x;
h[kk] = g[kk];
l[kk] = k[kk];
b[kk] = a[kk] - l[kk];
c[kk] = P2 * b[kk];
d[kk] = a[kk] + c[kk];
e[kk] = d[kk] - h[kk];
f[kk] = p1[kk] * e[kk];
g[kk] = f[kk] + d[kk];
k[kk] = h[kk] + f[kk];
m[kk] = l[kk] + c[kk];
n[kk] = a[kk] - m[kk];
y[kk] += (fabs(n[kk]) - y[kk]) / 20.0;
if (y[kk] > .1)
s |= 1 << kk;
}
if (s != so)
nn = 0;
else
nn++;
if (nn == NNN) {
if (key[s])
putchar(key[s]);
}
so = s;
}
printf("\n");
return (0);
}