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 "isdn_audio.h"
  16#include "isdn_common.h"
  17
  18char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
  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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.