254 lines
9.5 KiB
C
254 lines
9.5 KiB
C
/* $Id$
|
|
******************************************************************************
|
|
|
|
Fax program for ISDN.
|
|
Integer to aLaw conversion.
|
|
|
|
Copyright (C) 1998 Morten Rolland [Morten.Rolland@asker.mail.telia.com]
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/* int2alaw.c
|
|
*
|
|
* Convert an integer value to alaw-encoding as used in Europe for voice
|
|
* over ISDN. The input value is in the range:
|
|
*
|
|
* -2147483648 to 2147483647
|
|
*
|
|
* This is equal to a full-blown 32 bit signed integer (two's complement).
|
|
* Most modern computer equipment should be able to handle this.
|
|
* The reason why the full range is used, is to make it possible to
|
|
* multiply/accumulate with integers in the application, and make the
|
|
* final (and maybe the only) scaling when converting to alaw.
|
|
*
|
|
* Documentation on this linear to a-law transformation:
|
|
*
|
|
* Figure out and remember the sign bit of the value to be converted,
|
|
* and take the absolute value such that the value -1 becomes 0 to
|
|
* index the tables correctly (and -2 becomes 1 etc.).
|
|
* If we didn't do this, The number -2147483648 would negate to itself
|
|
* and spoil the indexing.
|
|
*
|
|
* The resulting value is positive (or zero), and is split into two
|
|
* ranges, or segments; like this (32 bit binary):
|
|
*
|
|
* 00000000 00000000 00000000 00000000 (segment 0)
|
|
* to 00001111 11111111 11111111 11111111
|
|
*
|
|
* 00010000 00000000 00000000 00000000 (segment 1)
|
|
* to 01111111 11111111 11111111 11111111
|
|
*
|
|
* These two ranges index into each of four tables (two ranges, two signs).
|
|
* The index into the tables are found by using the proper bits from
|
|
* the (positive) value:
|
|
*
|
|
* 0000xxxx xxxx???? ???????? ???????? (segment 0)
|
|
* 0xxxxxxx ???????? ???????? ???????? (segment 1)
|
|
*
|
|
* The 'x' indicate the bits used to index, while '?' is don't care.
|
|
*/
|
|
|
|
|
|
static unsigned char pos0[256] = {
|
|
0xd5,0xd4,0xd7,0xd6,0xd1,0xd0,0xd3,0xd2,
|
|
0xdd,0xdc,0xdf,0xde,0xd9,0xd8,0xdb,0xda,
|
|
0xc5,0xc4,0xc7,0xc6,0xc1,0xc0,0xc3,0xc2,
|
|
0xcd,0xcc,0xcf,0xce,0xc9,0xc8,0xcb,0xca,
|
|
0xf5,0xf5,0xf4,0xf4,0xf7,0xf7,0xf6,0xf6,
|
|
0xf1,0xf1,0xf0,0xf0,0xf3,0xf3,0xf2,0xf2,
|
|
0xfd,0xfd,0xfc,0xfc,0xff,0xff,0xfe,0xfe,
|
|
0xf9,0xf9,0xf8,0xf8,0xfb,0xfb,0xfa,0xfa,
|
|
0xe5,0xe5,0xe5,0xe5,0xe4,0xe4,0xe4,0xe4,
|
|
0xe7,0xe7,0xe7,0xe7,0xe6,0xe6,0xe6,0xe6,
|
|
0xe1,0xe1,0xe1,0xe1,0xe0,0xe0,0xe0,0xe0,
|
|
0xe3,0xe3,0xe3,0xe3,0xe2,0xe2,0xe2,0xe2,
|
|
0xed,0xed,0xed,0xed,0xec,0xec,0xec,0xec,
|
|
0xef,0xef,0xef,0xef,0xee,0xee,0xee,0xee,
|
|
0xe9,0xe9,0xe9,0xe9,0xe8,0xe8,0xe8,0xe8,
|
|
0xeb,0xeb,0xeb,0xeb,0xea,0xea,0xea,0xea,
|
|
0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
|
|
0x94,0x94,0x94,0x94,0x94,0x94,0x94,0x94,
|
|
0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,
|
|
0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
|
|
0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,
|
|
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
|
|
0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,
|
|
0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92,
|
|
0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,0x9d,
|
|
0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,0x9c,
|
|
0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,
|
|
0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,
|
|
0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,
|
|
0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,
|
|
0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,
|
|
0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a
|
|
};
|
|
|
|
static unsigned char pos1[128] = {
|
|
0xd5,0xc5,0xf5,0xfd,0xe5,0xe1,0xed,0xe9,
|
|
0x95,0x97,0x91,0x93,0x9d,0x9f,0x99,0x9b,
|
|
0x85,0x84,0x87,0x86,0x81,0x80,0x83,0x82,
|
|
0x8d,0x8c,0x8f,0x8e,0x89,0x88,0x8b,0x8a,
|
|
0xb5,0xb5,0xb4,0xb4,0xb7,0xb7,0xb6,0xb6,
|
|
0xb1,0xb1,0xb0,0xb0,0xb3,0xb3,0xb2,0xb2,
|
|
0xbd,0xbd,0xbc,0xbc,0xbf,0xbf,0xbe,0xbe,
|
|
0xb9,0xb9,0xb8,0xb8,0xbb,0xbb,0xba,0xba,
|
|
0xa5,0xa5,0xa5,0xa5,0xa4,0xa4,0xa4,0xa4,
|
|
0xa7,0xa7,0xa7,0xa7,0xa6,0xa6,0xa6,0xa6,
|
|
0xa1,0xa1,0xa1,0xa1,0xa0,0xa0,0xa0,0xa0,
|
|
0xa3,0xa3,0xa3,0xa3,0xa2,0xa2,0xa2,0xa2,
|
|
0xad,0xad,0xad,0xad,0xac,0xac,0xac,0xac,
|
|
0xaf,0xaf,0xaf,0xaf,0xae,0xae,0xae,0xae,
|
|
0xa9,0xa9,0xa9,0xa9,0xa8,0xa8,0xa8,0xa8,
|
|
0xab,0xab,0xab,0xab,0xaa,0xaa,0xaa,0xaa
|
|
};
|
|
|
|
static unsigned char neg0[256] = {
|
|
0x55,0x54,0x57,0x56,0x51,0x50,0x53,0x52,
|
|
0x5d,0x5c,0x5f,0x5e,0x59,0x58,0x5b,0x5a,
|
|
0x45,0x44,0x47,0x46,0x41,0x40,0x43,0x42,
|
|
0x4d,0x4c,0x4f,0x4e,0x49,0x48,0x4b,0x4a,
|
|
0x75,0x75,0x74,0x74,0x77,0x77,0x76,0x76,
|
|
0x71,0x71,0x70,0x70,0x73,0x73,0x72,0x72,
|
|
0x7d,0x7d,0x7c,0x7c,0x7f,0x7f,0x7e,0x7e,
|
|
0x79,0x79,0x78,0x78,0x7b,0x7b,0x7a,0x7a,
|
|
0x65,0x65,0x65,0x65,0x64,0x64,0x64,0x64,
|
|
0x67,0x67,0x67,0x67,0x66,0x66,0x66,0x66,
|
|
0x61,0x61,0x61,0x61,0x60,0x60,0x60,0x60,
|
|
0x63,0x63,0x63,0x63,0x62,0x62,0x62,0x62,
|
|
0x6d,0x6d,0x6d,0x6d,0x6c,0x6c,0x6c,0x6c,
|
|
0x6f,0x6f,0x6f,0x6f,0x6e,0x6e,0x6e,0x6e,
|
|
0x69,0x69,0x69,0x69,0x68,0x68,0x68,0x68,
|
|
0x6b,0x6b,0x6b,0x6b,0x6a,0x6a,0x6a,0x6a,
|
|
0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
|
|
0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,
|
|
0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
|
|
0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
|
|
0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
|
|
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
|
0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
|
|
0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
|
|
0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,
|
|
0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,
|
|
0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
|
|
0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
|
|
0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
|
|
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,
|
|
0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a
|
|
};
|
|
|
|
static unsigned char neg1[128] = {
|
|
0x55,0x45,0x75,0x7d,0x65,0x61,0x6d,0x69,
|
|
0x15,0x17,0x11,0x13,0x1d,0x1f,0x19,0x1b,
|
|
0x05,0x04,0x07,0x06,0x01,0x00,0x03,0x02,
|
|
0x0d,0x0c,0x0f,0x0e,0x09,0x08,0x0b,0x0a,
|
|
0x35,0x35,0x34,0x34,0x37,0x37,0x36,0x36,
|
|
0x31,0x31,0x30,0x30,0x33,0x33,0x32,0x32,
|
|
0x3d,0x3d,0x3c,0x3c,0x3f,0x3f,0x3e,0x3e,
|
|
0x39,0x39,0x38,0x38,0x3b,0x3b,0x3a,0x3a,
|
|
0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x24,
|
|
0x27,0x27,0x27,0x27,0x26,0x26,0x26,0x26,
|
|
0x21,0x21,0x21,0x21,0x20,0x20,0x20,0x20,
|
|
0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,
|
|
0x2d,0x2d,0x2d,0x2d,0x2c,0x2c,0x2c,0x2c,
|
|
0x2f,0x2f,0x2f,0x2f,0x2e,0x2e,0x2e,0x2e,
|
|
0x29,0x29,0x29,0x29,0x28,0x28,0x28,0x28,
|
|
0x2b,0x2b,0x2b,0x2b,0x2a,0x2a,0x2a,0x2a
|
|
};
|
|
|
|
|
|
unsigned char int2alaw(int value)
|
|
{
|
|
unsigned int idx;
|
|
|
|
if ( value >= 0 ) {
|
|
idx = value;
|
|
if ( idx < 0x10000000 ) {
|
|
idx >>= 20;
|
|
return pos0[idx];
|
|
} else {
|
|
idx >>= 24;
|
|
return pos1[idx];
|
|
}
|
|
} else {
|
|
idx = -(value+1);
|
|
if ( idx < 0x10000000 ) {
|
|
idx >>= 20;
|
|
return neg0[idx];
|
|
} else {
|
|
idx >>= 24;
|
|
return neg1[idx];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned short alaw2short[256] = {
|
|
0xea80,0xeb80,0xe880,0xe980,0xee80,0xef80,0xec80,0xed80,
|
|
0xe280,0xe380,0xe080,0xe180,0xe680,0xe780,0xe480,0xe580,
|
|
0xf540,0xf5c0,0xf440,0xf4c0,0xf740,0xf7c0,0xf640,0xf6c0,
|
|
0xf140,0xf1c0,0xf040,0xf0c0,0xf340,0xf3c0,0xf240,0xf2c0,
|
|
0xaa00,0xae00,0xa200,0xa600,0xba00,0xbe00,0xb200,0xb600,
|
|
0x8a00,0x8e00,0x8200,0x8600,0x9a00,0x9e00,0x9200,0x9600,
|
|
0xd500,0xd700,0xd100,0xd300,0xdd00,0xdf00,0xd900,0xdb00,
|
|
0xc500,0xc700,0xc100,0xc300,0xcd00,0xcf00,0xc900,0xcb00,
|
|
0xfea8,0xfeb8,0xfe88,0xfe98,0xfee8,0xfef8,0xfec8,0xfed8,
|
|
0xfe28,0xfe38,0xfe08,0xfe18,0xfe68,0xfe78,0xfe48,0xfe58,
|
|
0xffa8,0xffb8,0xff88,0xff98,0xffe8,0xfff8,0xffc8,0xffd8,
|
|
0xff28,0xff38,0xff08,0xff18,0xff68,0xff78,0xff48,0xff58,
|
|
0xfaa0,0xfae0,0xfa20,0xfa60,0xfba0,0xfbe0,0xfb20,0xfb60,
|
|
0xf8a0,0xf8e0,0xf820,0xf860,0xf9a0,0xf9e0,0xf920,0xf960,
|
|
0xfd50,0xfd70,0xfd10,0xfd30,0xfdd0,0xfdf0,0xfd90,0xfdb0,
|
|
0xfc50,0xfc70,0xfc10,0xfc30,0xfcd0,0xfcf0,0xfc90,0xfcb0,
|
|
0x1580,0x1480,0x1780,0x1680,0x1180,0x1080,0x1380,0x1280,
|
|
0x1d80,0x1c80,0x1f80,0x1e80,0x1980,0x1880,0x1b80,0x1a80,
|
|
0x0ac0,0x0a40,0x0bc0,0x0b40,0x08c0,0x0840,0x09c0,0x0940,
|
|
0x0ec0,0x0e40,0x0fc0,0x0f40,0x0cc0,0x0c40,0x0dc0,0x0d40,
|
|
0x5600,0x5200,0x5e00,0x5a00,0x4600,0x4200,0x4e00,0x4a00,
|
|
0x7600,0x7200,0x7e00,0x7a00,0x6600,0x6200,0x6e00,0x6a00,
|
|
0x2b00,0x2900,0x2f00,0x2d00,0x2300,0x2100,0x2700,0x2500,
|
|
0x3b00,0x3900,0x3f00,0x3d00,0x3300,0x3100,0x3700,0x3500,
|
|
0x0158,0x0148,0x0178,0x0168,0x0118,0x0108,0x0138,0x0128,
|
|
0x01d8,0x01c8,0x01f8,0x01e8,0x0198,0x0188,0x01b8,0x01a8,
|
|
0x0058,0x0048,0x0078,0x0068,0x0018,0x0008,0x0038,0x0028,
|
|
0x00d8,0x00c8,0x00f8,0x00e8,0x0098,0x0088,0x00b8,0x00a8,
|
|
0x0560,0x0520,0x05e0,0x05a0,0x0460,0x0420,0x04e0,0x04a0,
|
|
0x0760,0x0720,0x07e0,0x07a0,0x0660,0x0620,0x06e0,0x06a0,
|
|
0x02b0,0x0290,0x02f0,0x02d0,0x0230,0x0210,0x0270,0x0250,
|
|
0x03b0,0x0390,0x03f0,0x03d0,0x0330,0x0310,0x0370,0x0350
|
|
};
|
|
|
|
|
|
int alaw2int(unsigned char value)
|
|
{
|
|
unsigned int u;
|
|
int p;
|
|
|
|
u = alaw2short[value];
|
|
u <<= 16;
|
|
p = u;
|
|
|
|
return p;
|
|
}
|
|
|