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