diff options
author | hm <hm@FreeBSD.org> | 1999-03-07 17:09:03 +0000 |
---|---|---|
committer | hm <hm@FreeBSD.org> | 1999-03-07 17:09:03 +0000 |
commit | d3cdfce5f6a0a4d9c1806d24c9a9bd5e5ee676a6 (patch) | |
tree | 4651172a60edd6afc0f607f4e3ec4adeb513a676 | |
parent | 36b481d4f3a44d80e63d9ab230c89bdc520fb8c2 (diff) | |
download | FreeBSD-src-d3cdfce5f6a0a4d9c1806d24c9a9bd5e5ee676a6.zip FreeBSD-src-d3cdfce5f6a0a4d9c1806d24c9a9bd5e5ee676a6.tar.gz |
add the dtmfdecode program (added to i4b with 0.71.00) to the i4b userland
-rw-r--r-- | usr.sbin/i4b/Makefile | 2 | ||||
-rw-r--r-- | usr.sbin/i4b/dtmfdecode/Makefile | 15 | ||||
-rw-r--r-- | usr.sbin/i4b/dtmfdecode/README | 44 | ||||
-rw-r--r-- | usr.sbin/i4b/dtmfdecode/dtmfdecode.1 | 61 | ||||
-rw-r--r-- | usr.sbin/i4b/dtmfdecode/dtmfdecode.c | 158 |
5 files changed, 279 insertions, 1 deletions
diff --git a/usr.sbin/i4b/Makefile b/usr.sbin/i4b/Makefile index 3c12d78..c1d71e7 100644 --- a/usr.sbin/i4b/Makefile +++ b/usr.sbin/i4b/Makefile @@ -1,4 +1,4 @@ SUBDIR = isdntrace isdndebug isdnd alawulaw man isdntest \ - isdntel isdntelctl isdnmonitor isdndecode + isdntel isdntelctl isdnmonitor isdndecode dtmfdecode .include <bsd.subdir.mk> diff --git a/usr.sbin/i4b/dtmfdecode/Makefile b/usr.sbin/i4b/dtmfdecode/Makefile new file mode 100644 index 0000000..e814285 --- /dev/null +++ b/usr.sbin/i4b/dtmfdecode/Makefile @@ -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> diff --git a/usr.sbin/i4b/dtmfdecode/README b/usr.sbin/i4b/dtmfdecode/README new file mode 100644 index 0000000..d25cbd2 --- /dev/null +++ b/usr.sbin/i4b/dtmfdecode/README @@ -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 diff --git a/usr.sbin/i4b/dtmfdecode/dtmfdecode.1 b/usr.sbin/i4b/dtmfdecode/dtmfdecode.1 new file mode 100644 index 0000000..64c6fb3 --- /dev/null +++ b/usr.sbin/i4b/dtmfdecode/dtmfdecode.1 @@ -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. diff --git a/usr.sbin/i4b/dtmfdecode/dtmfdecode.c b/usr.sbin/i4b/dtmfdecode/dtmfdecode.c new file mode 100644 index 0000000..2b53fa6 --- /dev/null +++ b/usr.sbin/i4b/dtmfdecode/dtmfdecode.c @@ -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); +} |