1/* $Id: isdn_audio.c,v 1.1.1.1 2007/08/03 18:52:36 Exp $ 2 * 3 * Linux ISDN subsystem, audio conversion and compression (linklevel). 4 * 5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) 6 * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at) 7 * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de) 8 * 9 * This software may be used and distributed according to the terms 10 * of the GNU General Public License, incorporated herein by reference. 11 * 12 */ 13 14#include <linux/isdn.h> 15#include "isdn_audio.h" 16#include "isdn_common.h" 17 18char *isdn_audio_revision = "$Revision: 1.1.1.1 $"; 19 20/* 21 * Misc. lookup-tables. 22 */ 23 24/* ulaw -> signed 16-bit */ 25static short isdn_audio_ulaw_to_s16[] = 26{ 27 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84, 28 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84, 29 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84, 30 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84, 31 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804, 32 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004, 33 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444, 34 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844, 35 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64, 36 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64, 37 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74, 38 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74, 39 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc, 40 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c, 41 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0, 42 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000, 43 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c, 44 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c, 45 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c, 46 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c, 47 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc, 48 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc, 49 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc, 50 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc, 51 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c, 52 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c, 53 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c, 54 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c, 55 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 56 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084, 57 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 58 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000 59}; 60 61/* alaw -> signed 16-bit */ 62static short isdn_audio_alaw_to_s16[] = 63{ 64 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4, 65 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74, 66 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4, 67 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64, 68 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4, 69 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4, 70 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4, 71 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4, 72 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64, 73 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34, 74 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844, 75 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24, 76 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64, 77 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4, 78 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964, 79 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4, 80 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24, 81 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94, 82 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924, 83 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94, 84 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24, 85 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14, 86 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24, 87 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14, 88 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4, 89 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54, 90 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4, 91 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64, 92 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4, 93 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4, 94 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4, 95 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4 96}; 97 98/* alaw -> ulaw */ 99static char isdn_audio_alaw_to_ulaw[] = 100{ 101 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49, 102 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57, 103 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41, 104 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f, 105 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d, 106 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b, 107 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45, 108 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53, 109 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47, 110 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55, 111 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f, 112 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e, 113 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b, 114 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59, 115 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43, 116 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51, 117 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a, 118 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58, 119 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42, 120 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50, 121 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e, 122 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c, 123 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46, 124 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54, 125 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48, 126 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56, 127 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40, 128 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f, 129 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c, 130 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a, 131 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44, 132 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52 133}; 134 135/* ulaw -> alaw */ 136static char isdn_audio_ulaw_to_alaw[] = 137{ 138 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35, 139 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25, 140 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d, 141 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d, 142 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31, 143 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21, 144 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9, 145 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9, 146 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47, 147 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf, 148 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f, 149 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33, 150 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23, 151 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b, 152 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b, 153 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b, 154 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34, 155 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24, 156 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c, 157 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c, 158 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30, 159 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20, 160 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8, 161 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8, 162 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46, 163 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde, 164 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e, 165 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32, 166 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22, 167 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a, 168 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a, 169 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a 170}; 171 172#define NCOEFF 8 /* number of frequencies to be analyzed */ 173#define DTMF_TRESH 4000 /* above this is dtmf */ 174#define SILENCE_TRESH 200 /* below this is silence */ 175#define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */ 176#define LOGRP 0 177#define HIGRP 1 178 179/* For DTMF recognition: 180 * 2 * cos(2 * PI * k / N) precalculated for all k 181 */ 182static int cos2pik[NCOEFF] = 183{ 184 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332 185}; 186 187static char dtmf_matrix[4][4] = 188{ 189 {'1', '2', '3', 'A'}, 190 {'4', '5', '6', 'B'}, 191 {'7', '8', '9', 'C'}, 192 {'*', '0', '#', 'D'} 193}; 194 195static inline void 196isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n) 197{ 198#ifdef __i386__ 199 unsigned long d0, d1, d2, d3; 200 __asm__ __volatile__( 201 "cld\n" 202 "1:\tlodsb\n\t" 203 "xlatb\n\t" 204 "stosb\n\t" 205 "loop 1b\n\t" 206 : "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3) 207 : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff) 208 : "memory", "ax"); 209#else 210 while (n--) 211 *buff = table[*(unsigned char *)buff], buff++; 212#endif 213} 214 215void 216isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len) 217{ 218 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len); 219} 220 221void 222isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len) 223{ 224 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len); 225} 226 227/* 228 * linear <-> adpcm conversion stuff 229 * Most parts from the mgetty-package. 230 * (C) by Gert Doering and Klaus Weidner 231 * Used by permission of Gert Doering 232 */ 233 234 235#define ZEROTRAP /* turn on the trap as per the MIL-STD */ 236#undef ZEROTRAP 237#define BIAS 0x84 /* define the add-in bias for 16 bit samples */ 238#define CLIP 32635 239 240static unsigned char 241isdn_audio_linear2ulaw(int sample) 242{ 243 static int exp_lut[256] = 244 { 245 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 246 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 247 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 248 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 249 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 250 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 251 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 252 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 253 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 254 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 255 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 256 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 257 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 258 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 259 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 260 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 261 }; 262 int sign, 263 exponent, 264 mantissa; 265 unsigned char ulawbyte; 266 267 /* Get the sample into sign-magnitude. */ 268 sign = (sample >> 8) & 0x80; /* set aside the sign */ 269 if (sign != 0) 270 sample = -sample; /* get magnitude */ 271 if (sample > CLIP) 272 sample = CLIP; /* clip the magnitude */ 273 274 /* Convert from 16 bit linear to ulaw. */ 275 sample = sample + BIAS; 276 exponent = exp_lut[(sample >> 7) & 0xFF]; 277 mantissa = (sample >> (exponent + 3)) & 0x0F; 278 ulawbyte = ~(sign | (exponent << 4) | mantissa); 279#ifdef ZEROTRAP 280 /* optional CCITT trap */ 281 if (ulawbyte == 0) 282 ulawbyte = 0x02; 283#endif 284 return (ulawbyte); 285} 286 287 288static int Mx[3][8] = 289{ 290 {0x3800, 0x5600, 0, 0, 0, 0, 0, 0}, 291 {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0}, 292 {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607}, 293}; 294 295static int bitmask[9] = 296{ 297 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff 298}; 299 300static int 301isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len) 302{ 303 while (s->nleft < s->nbits) { 304 int d = *((*in)++); 305 (*len)--; 306 s->word = (s->word << 8) | d; 307 s->nleft += 8; 308 } 309 s->nleft -= s->nbits; 310 return (s->word >> s->nleft) & bitmask[s->nbits]; 311} 312 313static void 314isdn_audio_put_bits(int data, int nbits, adpcm_state * s, 315 unsigned char **out, int *len) 316{ 317 s->word = (s->word << nbits) | (data & bitmask[nbits]); 318 s->nleft += nbits; 319 while (s->nleft >= 8) { 320 int d = (s->word >> (s->nleft - 8)); 321 *(out[0]++) = d & 255; 322 (*len)++; 323 s->nleft -= 8; 324 } 325} 326 327adpcm_state * 328isdn_audio_adpcm_init(adpcm_state * s, int nbits) 329{ 330 if (!s) 331 s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC); 332 if (s) { 333 s->a = 0; 334 s->d = 5; 335 s->word = 0; 336 s->nleft = 0; 337 s->nbits = nbits; 338 } 339 return s; 340} 341 342dtmf_state * 343isdn_audio_dtmf_init(dtmf_state * s) 344{ 345 if (!s) 346 s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC); 347 if (s) { 348 s->idx = 0; 349 s->last = ' '; 350 } 351 return s; 352} 353 354/* 355 * Decompression of adpcm data to a/u-law 356 * 357 */ 358 359int 360isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in, 361 unsigned char *out, int len) 362{ 363 int a = s->a; 364 int d = s->d; 365 int nbits = s->nbits; 366 int olen = 0; 367 368 while (len) { 369 int e = isdn_audio_get_bits(s, &in, &len); 370 int sign; 371 372 if (nbits == 4 && e == 0) 373 d = 4; 374 sign = (e >> (nbits - 1)) ? -1 : 1; 375 e &= bitmask[nbits - 1]; 376 a += sign * ((e << 1) + 1) * d >> 1; 377 if (d & 1) 378 a++; 379 if (fmt) 380 *out++ = isdn_audio_ulaw_to_alaw[ 381 isdn_audio_linear2ulaw(a << 2)]; 382 else 383 *out++ = isdn_audio_linear2ulaw(a << 2); 384 olen++; 385 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14; 386 if (d < 5) 387 d = 5; 388 } 389 s->a = a; 390 s->d = d; 391 return olen; 392} 393 394int 395isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in, 396 unsigned char *out, int len) 397{ 398 int a = s->a; 399 int d = s->d; 400 int nbits = s->nbits; 401 int olen = 0; 402 403 while (len--) { 404 int e = 0, 405 nmax = 1 << (nbits - 1); 406 int sign, 407 delta; 408 409 if (fmt) 410 delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a; 411 else 412 delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a; 413 if (delta < 0) { 414 e = nmax; 415 delta = -delta; 416 } 417 while (--nmax && delta > d) { 418 delta -= d; 419 e++; 420 } 421 if (nbits == 4 && ((e & 0x0f) == 0)) 422 e = 8; 423 isdn_audio_put_bits(e, nbits, s, &out, &olen); 424 sign = (e >> (nbits - 1)) ? -1 : 1; 425 e &= bitmask[nbits - 1]; 426 427 a += sign * ((e << 1) + 1) * d >> 1; 428 if (d & 1) 429 a++; 430 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14; 431 if (d < 5) 432 d = 5; 433 } 434 s->a = a; 435 s->d = d; 436 return olen; 437} 438 439/* 440 * Goertzel algorithm. 441 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/ 442 * for more info. 443 * Result is stored into an sk_buff and queued up for later 444 * evaluation. 445 */ 446static void 447isdn_audio_goertzel(int *sample, modem_info * info) 448{ 449 int sk, 450 sk1, 451 sk2; 452 int k, 453 n; 454 struct sk_buff *skb; 455 int *result; 456 457 skb = dev_alloc_skb(sizeof(int) * NCOEFF); 458 if (!skb) { 459 printk(KERN_WARNING 460 "isdn_audio: Could not alloc DTMF result for ttyI%d\n", 461 info->line); 462 return; 463 } 464 result = (int *) skb_put(skb, sizeof(int) * NCOEFF); 465 for (k = 0; k < NCOEFF; k++) { 466 sk = sk1 = sk2 = 0; 467 for (n = 0; n < DTMF_NPOINTS; n++) { 468 sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2; 469 sk2 = sk1; 470 sk1 = sk; 471 } 472 /* Avoid overflows */ 473 sk >>= 1; 474 sk2 >>= 1; 475 /* compute |X(k)|**2 */ 476 /* report overflows. This should not happen. */ 477 /* Comment this out if desired */ 478 if (sk < -32768 || sk > 32767) 479 printk(KERN_DEBUG 480 "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk); 481 if (sk2 < -32768 || sk2 > 32767) 482 printk(KERN_DEBUG 483 "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2); 484 result[k] = 485 ((sk * sk) >> AMP_BITS) - 486 ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) + 487 ((sk2 * sk2) >> AMP_BITS); 488 } 489 skb_queue_tail(&info->dtmf_queue, skb); 490 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); 491} 492 493void 494isdn_audio_eval_dtmf(modem_info * info) 495{ 496 struct sk_buff *skb; 497 int *result; 498 dtmf_state *s; 499 int silence; 500 int i; 501 int di; 502 int ch; 503 int grp[2]; 504 char what; 505 char *p; 506 int thresh; 507 508 while ((skb = skb_dequeue(&info->dtmf_queue))) { 509 result = (int *) skb->data; 510 s = info->dtmf_state; 511 grp[LOGRP] = grp[HIGRP] = -1; 512 silence = 0; 513 thresh = 0; 514 for (i = 0; i < NCOEFF; i++) { 515 if (result[i] > DTMF_TRESH) { 516 if (result[i] > thresh) 517 thresh = result[i]; 518 } 519 else if (result[i] < SILENCE_TRESH) 520 silence++; 521 } 522 if (silence == NCOEFF) 523 what = ' '; 524 else { 525 if (thresh > 0) { 526 thresh = thresh >> 4; /* touchtones must match within 12 dB */ 527 for (i = 0; i < NCOEFF; i++) { 528 if (result[i] < thresh) 529 continue; /* ignore */ 530 /* good level found. This is allowed only one time per group */ 531 if (i < NCOEFF / 2) { 532 /* lowgroup*/ 533 if (grp[LOGRP] >= 0) { 534 // Bad. Another tone found. */ 535 grp[LOGRP] = -1; 536 break; 537 } 538 else 539 grp[LOGRP] = i; 540 } 541 else { /* higroup */ 542 if (grp[HIGRP] >= 0) { // Bad. Another tone found. */ 543 grp[HIGRP] = -1; 544 break; 545 } 546 else 547 grp[HIGRP] = i - NCOEFF/2; 548 } 549 } 550 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) { 551 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]]; 552 if (s->last != ' ' && s->last != '.') 553 s->last = what; /* min. 1 non-DTMF between DTMF */ 554 } else 555 what = '.'; 556 } 557 else 558 what = '.'; 559 } 560 if ((what != s->last) && (what != ' ') && (what != '.')) { 561 printk(KERN_DEBUG "dtmf: tt='%c'\n", what); 562 p = skb->data; 563 *p++ = 0x10; 564 *p = what; 565 skb_trim(skb, 2); 566 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; 567 ISDN_AUDIO_SKB_LOCK(skb) = 0; 568 di = info->isdn_driver; 569 ch = info->isdn_channel; 570 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); 571 dev->drv[di]->rcvcount[ch] += 2; 572 /* Schedule dequeuing */ 573 if ((dev->modempoll) && (info->rcvsched)) 574 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); 575 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); 576 } else 577 kfree_skb(skb); 578 s->last = what; 579 } 580} 581 582/* 583 * Decode DTMF tones, queue result in separate sk_buf for 584 * later examination. 585 * Parameters: 586 * s = pointer to state-struct. 587 * buf = input audio data 588 * len = size of audio data. 589 * fmt = audio data format (0 = ulaw, 1 = alaw) 590 */ 591void 592isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt) 593{ 594 dtmf_state *s = info->dtmf_state; 595 int i; 596 int c; 597 598 while (len) { 599 c = DTMF_NPOINTS - s->idx; 600 if (c > len) 601 c = len; 602 if (c <= 0) 603 break; 604 for (i = 0; i < c; i++) { 605 if (fmt) 606 s->buf[s->idx++] = 607 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS); 608 else 609 s->buf[s->idx++] = 610 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS); 611 } 612 if (s->idx == DTMF_NPOINTS) { 613 isdn_audio_goertzel(s->buf, info); 614 s->idx = 0; 615 } 616 len -= c; 617 } 618} 619 620silence_state * 621isdn_audio_silence_init(silence_state * s) 622{ 623 if (!s) 624 s = kmalloc(sizeof(silence_state), GFP_ATOMIC); 625 if (s) { 626 s->idx = 0; 627 s->state = 0; 628 } 629 return s; 630} 631 632void 633isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt) 634{ 635 silence_state *s = info->silence_state; 636 int i; 637 signed char c; 638 639 if (!info->emu.vpar[1]) return; 640 641 for (i = 0; i < len; i++) { 642 if (fmt) 643 c = isdn_audio_alaw_to_ulaw[*buf++]; 644 else 645 c = *buf++; 646 647 if (c > 0) c -= 128; 648 c = abs(c); 649 650 if (c > (info->emu.vpar[1] * 4)) { 651 s->idx = 0; 652 s->state = 1; 653 } else { 654 if (s->idx < 210000) s->idx++; 655 } 656 } 657} 658 659void 660isdn_audio_put_dle_code(modem_info * info, u_char code) 661{ 662 struct sk_buff *skb; 663 int di; 664 int ch; 665 char *p; 666 667 skb = dev_alloc_skb(2); 668 if (!skb) { 669 printk(KERN_WARNING 670 "isdn_audio: Could not alloc skb for ttyI%d\n", 671 info->line); 672 return; 673 } 674 p = (char *) skb_put(skb, 2); 675 p[0] = 0x10; 676 p[1] = code; 677 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; 678 ISDN_AUDIO_SKB_LOCK(skb) = 0; 679 di = info->isdn_driver; 680 ch = info->isdn_channel; 681 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); 682 dev->drv[di]->rcvcount[ch] += 2; 683 /* Schedule dequeuing */ 684 if ((dev->modempoll) && (info->rcvsched)) 685 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); 686 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); 687} 688 689void 690isdn_audio_eval_silence(modem_info * info) 691{ 692 silence_state *s = info->silence_state; 693 char what; 694 695 what = ' '; 696 697 if (s->idx > (info->emu.vpar[2] * 800)) { 698 s->idx = 0; 699 if (!s->state) { /* silence from beginning of rec */ 700 what = 's'; 701 } else { 702 what = 'q'; 703 } 704 } 705 if ((what == 's') || (what == 'q')) { 706 printk(KERN_DEBUG "ttyI%d: %s\n", info->line, 707 (what=='s') ? "silence":"quiet"); 708 isdn_audio_put_dle_code(info, what); 709 } 710} 711