linux-old/drivers/isdn/isdn_audio.c
<<
>>
Prefs
   1/* $Id: isdn_audio.c,v 1.1.4.1 2001/11/20 14:19:33 kai 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.4.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 = (adpcm_state *) 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 = (dtmf_state *) 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_2adpcm_flush(adpcm_state * s, unsigned char *out)
 396{
 397        int olen = 0;
 398
 399        if (s->nleft)
 400                isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
 401        return olen;
 402}
 403
 404int
 405isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
 406                      unsigned char *out, int len)
 407{
 408        int a = s->a;
 409        int d = s->d;
 410        int nbits = s->nbits;
 411        int olen = 0;
 412
 413        while (len--) {
 414                int e = 0,
 415                 nmax = 1 << (nbits - 1);
 416                int sign,
 417                 delta;
 418
 419                if (fmt)
 420                        delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
 421                else
 422                        delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
 423                if (delta < 0) {
 424                        e = nmax;
 425                        delta = -delta;
 426                }
 427                while (--nmax && delta > d) {
 428                        delta -= d;
 429                        e++;
 430                }
 431                if (nbits == 4 && ((e & 0x0f) == 0))
 432                        e = 8;
 433                isdn_audio_put_bits(e, nbits, s, &out, &olen);
 434                sign = (e >> (nbits - 1)) ? -1 : 1;
 435                e &= bitmask[nbits - 1];
 436
 437                a += sign * ((e << 1) + 1) * d >> 1;
 438                if (d & 1)
 439                        a++;
 440                d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
 441                if (d < 5)
 442                        d = 5;
 443        }
 444        s->a = a;
 445        s->d = d;
 446        return olen;
 447}
 448
 449/*
 450 * Goertzel algorithm.
 451 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
 452 * for more info.
 453 * Result is stored into an sk_buff and queued up for later
 454 * evaluation.
 455 */
 456static void
 457isdn_audio_goertzel(int *sample, modem_info * info)
 458{
 459        int sk,
 460         sk1,
 461         sk2;
 462        int k,
 463         n;
 464        struct sk_buff *skb;
 465        int *result;
 466
 467        skb = dev_alloc_skb(sizeof(int) * NCOEFF);
 468        if (!skb) {
 469                printk(KERN_WARNING
 470                  "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
 471                       info->line);
 472                return;
 473        }
 474        result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
 475        for (k = 0; k < NCOEFF; k++) {
 476                sk = sk1 = sk2 = 0;
 477                for (n = 0; n < DTMF_NPOINTS; n++) {
 478                        sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
 479                        sk2 = sk1;
 480                        sk1 = sk;
 481                }
 482                /* Avoid overflows */
 483                sk >>= 1;
 484                sk2 >>= 1;
 485                /* compute |X(k)|**2 */
 486                /* report overflows. This should not happen. */
 487                /* Comment this out if desired */
 488                if (sk < -32768 || sk > 32767)
 489                        printk(KERN_DEBUG
 490                               "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
 491                if (sk2 < -32768 || sk2 > 32767)
 492                        printk(KERN_DEBUG
 493                               "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
 494                result[k] =
 495                    ((sk * sk) >> AMP_BITS) -
 496                    ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
 497                    ((sk2 * sk2) >> AMP_BITS);
 498        }
 499        skb_queue_tail(&info->dtmf_queue, skb);
 500        isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
 501}
 502
 503void
 504isdn_audio_eval_dtmf(modem_info * info)
 505{
 506        struct sk_buff *skb;
 507        int *result;
 508        dtmf_state *s;
 509        int silence;
 510        int i;
 511        int di;
 512        int ch;
 513        unsigned long flags;
 514        int grp[2];
 515        char what;
 516        char *p;
 517        int thresh;
 518
 519        while ((skb = skb_dequeue(&info->dtmf_queue))) {
 520                result = (int *) skb->data;
 521                s = info->dtmf_state;
 522                grp[LOGRP] = grp[HIGRP] = -1;
 523                silence = 0;
 524                thresh = 0;
 525                for (i = 0; i < NCOEFF; i++) {
 526                        if (result[i] > DTMF_TRESH) {
 527                                if (result[i] > thresh)
 528                                        thresh = result[i];
 529                        }
 530                        else if (result[i] < SILENCE_TRESH)
 531                                silence++;
 532                }
 533                if (silence == NCOEFF)
 534                        what = ' ';
 535                else {
 536                        if (thresh > 0) {
 537                                thresh = thresh >> 4;  /* touchtones must match within 12 dB */
 538                                for (i = 0; i < NCOEFF; i++) {
 539                                        if (result[i] < thresh)
 540                                                continue;  /* ignore */
 541                                        /* good level found. This is allowed only one time per group */
 542                                        if (i < NCOEFF / 2) {
 543                                                /* lowgroup*/
 544                                                if (grp[LOGRP] >= 0) {
 545                                                        // Bad. Another tone found. */
 546                                                        grp[LOGRP] = -1;
 547                                                        break;
 548                                                }
 549                                                else
 550                                                        grp[LOGRP] = i;
 551                                        }
 552                                        else { /* higroup */
 553                                                if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
 554                                                        grp[HIGRP] = -1;
 555                                                        break;
 556                                                }
 557                                                else
 558                                                        grp[HIGRP] = i - NCOEFF/2;
 559                                        }
 560                                }
 561                                if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
 562                                        what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
 563                                        if (s->last != ' ' && s->last != '.')
 564                                                s->last = what; /* min. 1 non-DTMF between DTMF */
 565                                } else
 566                                        what = '.';
 567                        }
 568                        else
 569                                what = '.';
 570                }
 571                if ((what != s->last) && (what != ' ') && (what != '.')) {
 572                        printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
 573                        p = skb->data;
 574                        *p++ = 0x10;
 575                        *p = what;
 576                        skb_trim(skb, 2);
 577                        if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
 578                                printk(KERN_WARNING
 579                                       "isdn_audio: insufficient skb_headroom, dropping\n");
 580                                kfree_skb(skb);
 581                                return;
 582                        }
 583                        ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
 584                        ISDN_AUDIO_SKB_LOCK(skb) = 0;
 585                        save_flags(flags);
 586                        cli();
 587                        di = info->isdn_driver;
 588                        ch = info->isdn_channel;
 589                        __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
 590                        dev->drv[di]->rcvcount[ch] += 2;
 591                        restore_flags(flags);
 592                        /* Schedule dequeuing */
 593                        if ((dev->modempoll) && (info->rcvsched))
 594                                isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
 595                        wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
 596                } else
 597                        kfree_skb(skb);
 598                s->last = what;
 599        }
 600}
 601
 602/*
 603 * Decode DTMF tones, queue result in separate sk_buf for
 604 * later examination.
 605 * Parameters:
 606 *   s    = pointer to state-struct.
 607 *   buf  = input audio data
 608 *   len  = size of audio data.
 609 *   fmt  = audio data format (0 = ulaw, 1 = alaw)
 610 */
 611void
 612isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
 613{
 614        dtmf_state *s = info->dtmf_state;
 615        int i;
 616        int c;
 617
 618        while (len) {
 619                c = DTMF_NPOINTS - s->idx;
 620                if (c > len)
 621                        c = len;
 622                if (c <= 0)
 623                        break;
 624                for (i = 0; i < c; i++) {
 625                        if (fmt)
 626                                s->buf[s->idx++] =
 627                                    isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
 628                        else
 629                                s->buf[s->idx++] =
 630                                    isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
 631                }
 632                if (s->idx == DTMF_NPOINTS) {
 633                        isdn_audio_goertzel(s->buf, info);
 634                        s->idx = 0;
 635                }
 636                len -= c;
 637        }
 638}
 639
 640silence_state *
 641isdn_audio_silence_init(silence_state * s)
 642{
 643        if (!s)
 644                s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
 645        if (s) {
 646                s->idx = 0;
 647                s->state = 0;
 648        }
 649        return s;
 650}
 651
 652void
 653isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
 654{
 655        silence_state *s = info->silence_state;
 656        int i;
 657        signed char c;
 658
 659        if (!info->emu.vpar[1]) return;
 660
 661        for (i = 0; i < len; i++) {
 662                if (fmt)
 663                    c = isdn_audio_alaw_to_ulaw[*buf++];
 664                        else
 665                    c = *buf++;
 666
 667                if (c > 0) c -= 128;
 668                c = abs(c);
 669
 670                if (c > (info->emu.vpar[1] * 4)) { 
 671                        s->idx = 0;
 672                        s->state = 1; 
 673                } else {
 674                        if (s->idx < 210000) s->idx++; 
 675                }
 676        }
 677}
 678
 679void
 680isdn_audio_put_dle_code(modem_info * info, u_char code)
 681{
 682        struct sk_buff *skb;
 683        unsigned long flags;
 684        int di;
 685        int ch;
 686        char *p;
 687
 688        skb = dev_alloc_skb(2);
 689        if (!skb) {
 690                printk(KERN_WARNING
 691                  "isdn_audio: Could not alloc skb for ttyI%d\n",
 692                       info->line);
 693                return;
 694        }
 695        p = (char *) skb_put(skb, 2);
 696        p[0] = 0x10;
 697        p[1] = code;
 698        if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
 699                printk(KERN_WARNING
 700                       "isdn_audio: insufficient skb_headroom, dropping\n");
 701                kfree_skb(skb);
 702                return;
 703        }
 704        ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
 705        ISDN_AUDIO_SKB_LOCK(skb) = 0;
 706        save_flags(flags);
 707        cli();
 708        di = info->isdn_driver;
 709        ch = info->isdn_channel;
 710        __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
 711        dev->drv[di]->rcvcount[ch] += 2;
 712        restore_flags(flags);
 713        /* Schedule dequeuing */
 714        if ((dev->modempoll) && (info->rcvsched))
 715                isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
 716        wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
 717}
 718
 719void
 720isdn_audio_eval_silence(modem_info * info)
 721{
 722        silence_state *s = info->silence_state;
 723        char what;
 724
 725        what = ' ';
 726
 727        if (s->idx > (info->emu.vpar[2] * 800)) { 
 728                s->idx = 0;
 729                if (!s->state) {        /* silence from beginning of rec */ 
 730                        what = 's';
 731                } else {
 732                        what = 'q';
 733                }
 734        }
 735                if ((what == 's') || (what == 'q')) {
 736                        printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
 737                                (what=='s') ? "silence":"quiet");
 738                        isdn_audio_put_dle_code(info, what);
 739                } 
 740}
 741
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.