// SPDX-License-Identifier: GPL-2.0-or-later
/*
* l1oip_codec . c generic codec using lookup table
* - > conversion from a - Law to u - Law
* - > conversion from u - Law to a - Law
* - > compression by reducing the number of sample resolution to 4
*
* NOTE : It is not compatible with any standard codec like ADPCM .
*
* Author Andreas Eversberg ( jolly @ eversberg . eu )
*
*/
/*
How the codec works :
- - - - - - - - - - - - - - - - - - - -
The volume is increased to increase the dynamic range of the audio signal .
Each sample is converted to a - LAW with only 16 steps of level resolution .
A pair of two samples are stored in one byte .
The first byte is stored in the upper bits , the second byte is stored in the
lower bits .
To speed up compression and decompression , two lookup tables are formed :
- 16 bits index for two samples ( law encoded ) with 8 bit compressed result .
- 8 bits index for one compressed data with 16 bits decompressed result .
NOTE : The bytes are handled as they are law - encoded .
*/
#include <linux/vmalloc.h>
#include <linux/mISDNif.h>
#include <linux/in.h>
#include "core.h"
#include "l1oip.h"
/* definitions of codec. don't use calculations, code may run slower. */
static u8 *table_com;
static u16 *table_dec;
/* alaw -> ulaw */
static u8 alaw_to_ulaw[256 ] =
{
0 xab, 0 x2b, 0 xe3, 0 x63, 0 x8b, 0 x0b, 0 xc9, 0 x49,
0 xba, 0 x3a, 0 xf6, 0 x76, 0 x9b, 0 x1b, 0 xd7, 0 x57,
0 xa3, 0 x23, 0 xdd, 0 x5d, 0 x83, 0 x03, 0 xc1, 0 x41,
0 xb2, 0 x32, 0 xeb, 0 x6b, 0 x93, 0 x13, 0 xcf, 0 x4f,
0 xaf, 0 x2f, 0 xe7, 0 x67, 0 x8f, 0 x0f, 0 xcd, 0 x4d,
0 xbe, 0 x3e, 0 xfe, 0 x7e, 0 x9f, 0 x1f, 0 xdb, 0 x5b,
0 xa7, 0 x27, 0 xdf, 0 x5f, 0 x87, 0 x07, 0 xc5, 0 x45,
0 xb6, 0 x36, 0 xef, 0 x6f, 0 x97, 0 x17, 0 xd3, 0 x53,
0 xa9, 0 x29, 0 xe1, 0 x61, 0 x89, 0 x09, 0 xc7, 0 x47,
0 xb8, 0 x38, 0 xf2, 0 x72, 0 x99, 0 x19, 0 xd5, 0 x55,
0 xa1, 0 x21, 0 xdc, 0 x5c, 0 x81, 0 x01, 0 xbf, 0 x3f,
0 xb0, 0 x30, 0 xe9, 0 x69, 0 x91, 0 x11, 0 xce, 0 x4e,
0 xad, 0 x2d, 0 xe5, 0 x65, 0 x8d, 0 x0d, 0 xcb, 0 x4b,
0 xbc, 0 x3c, 0 xfa, 0 x7a, 0 x9d, 0 x1d, 0 xd9, 0 x59,
0 xa5, 0 x25, 0 xde, 0 x5e, 0 x85, 0 x05, 0 xc3, 0 x43,
0 xb4, 0 x34, 0 xed, 0 x6d, 0 x95, 0 x15, 0 xd1, 0 x51,
0 xac, 0 x2c, 0 xe4, 0 x64, 0 x8c, 0 x0c, 0 xca, 0 x4a,
0 xbb, 0 x3b, 0 xf8, 0 x78, 0 x9c, 0 x1c, 0 xd8, 0 x58,
0 xa4, 0 x24, 0 xde, 0 x5e, 0 x84, 0 x04, 0 xc2, 0 x42,
0 xb3, 0 x33, 0 xec, 0 x6c, 0 x94, 0 x14, 0 xd0, 0 x50,
0 xb0, 0 x30, 0 xe8, 0 x68, 0 x90, 0 x10, 0 xce, 0 x4e,
0 xbf, 0 x3f, 0 xfe, 0 x7e, 0 xa0, 0 x20, 0 xdc, 0 x5c,
0 xa8, 0 x28, 0 xe0, 0 x60, 0 x88, 0 x08, 0 xc6, 0 x46,
0 xb7, 0 x37, 0 xf0, 0 x70, 0 x98, 0 x18, 0 xd4, 0 x54,
0 xaa, 0 x2a, 0 xe2, 0 x62, 0 x8a, 0 x0a, 0 xc8, 0 x48,
0 xb9, 0 x39, 0 xf4, 0 x74, 0 x9a, 0 x1a, 0 xd6, 0 x56,
0 xa2, 0 x22, 0 xdd, 0 x5d, 0 x82, 0 x02, 0 xc0, 0 x40,
0 xb1, 0 x31, 0 xea, 0 x6a, 0 x92, 0 x12, 0 xcf, 0 x4f,
0 xae, 0 x2e, 0 xe6, 0 x66, 0 x8e, 0 x0e, 0 xcc, 0 x4c,
0 xbd, 0 x3d, 0 xfc, 0 x7c, 0 x9e, 0 x1e, 0 xda, 0 x5a,
0 xa6, 0 x26, 0 xdf, 0 x5f, 0 x86, 0 x06, 0 xc4, 0 x44,
0 xb5, 0 x35, 0 xee, 0 x6e, 0 x96, 0 x16, 0 xd2, 0 x52
};
/* ulaw -> alaw */
static u8 ulaw_to_alaw[256 ] =
{
0 xab, 0 x55, 0 xd5, 0 x15, 0 x95, 0 x75, 0 xf5, 0 x35,
0 xb5, 0 x45, 0 xc5, 0 x05, 0 x85, 0 x65, 0 xe5, 0 x25,
0 xa5, 0 x5d, 0 xdd, 0 x1d, 0 x9d, 0 x7d, 0 xfd, 0 x3d,
0 xbd, 0 x4d, 0 xcd, 0 x0d, 0 x8d, 0 x6d, 0 xed, 0 x2d,
0 xad, 0 x51, 0 xd1, 0 x11, 0 x91, 0 x71, 0 xf1, 0 x31,
0 xb1, 0 x41, 0 xc1, 0 x01, 0 x81, 0 x61, 0 xe1, 0 x21,
0 x59, 0 xd9, 0 x19, 0 x99, 0 x79, 0 xf9, 0 x39, 0 xb9,
0 x49, 0 xc9, 0 x09, 0 x89, 0 x69, 0 xe9, 0 x29, 0 xa9,
0 xd7, 0 x17, 0 x97, 0 x77, 0 xf7, 0 x37, 0 xb7, 0 x47,
0 xc7, 0 x07, 0 x87, 0 x67, 0 xe7, 0 x27, 0 xa7, 0 xdf,
0 x9f, 0 x7f, 0 xff, 0 x3f, 0 xbf, 0 x4f, 0 xcf, 0 x0f,
0 x8f, 0 x6f, 0 xef, 0 x2f, 0 x53, 0 x13, 0 x73, 0 x33,
0 xb3, 0 x43, 0 xc3, 0 x03, 0 x83, 0 x63, 0 xe3, 0 x23,
0 xa3, 0 x5b, 0 xdb, 0 x1b, 0 x9b, 0 x7b, 0 xfb, 0 x3b,
0 xbb, 0 xbb, 0 x4b, 0 x4b, 0 xcb, 0 xcb, 0 x0b, 0 x0b,
0 x8b, 0 x8b, 0 x6b, 0 x6b, 0 xeb, 0 xeb, 0 x2b, 0 x2b,
0 xab, 0 x54, 0 xd4, 0 x14, 0 x94, 0 x74, 0 xf4, 0 x34,
0 xb4, 0 x44, 0 xc4, 0 x04, 0 x84, 0 x64, 0 xe4, 0 x24,
0 xa4, 0 x5c, 0 xdc, 0 x1c, 0 x9c, 0 x7c, 0 xfc, 0 x3c,
0 xbc, 0 x4c, 0 xcc, 0 x0c, 0 x8c, 0 x6c, 0 xec, 0 x2c,
0 xac, 0 x50, 0 xd0, 0 x10, 0 x90, 0 x70, 0 xf0, 0 x30,
0 xb0, 0 x40, 0 xc0, 0 x00, 0 x80, 0 x60, 0 xe0, 0 x20,
0 x58, 0 xd8, 0 x18, 0 x98, 0 x78, 0 xf8, 0 x38, 0 xb8,
0 x48, 0 xc8, 0 x08, 0 x88, 0 x68, 0 xe8, 0 x28, 0 xa8,
0 xd6, 0 x16, 0 x96, 0 x76, 0 xf6, 0 x36, 0 xb6, 0 x46,
0 xc6, 0 x06, 0 x86, 0 x66, 0 xe6, 0 x26, 0 xa6, 0 xde,
0 x9e, 0 x7e, 0 xfe, 0 x3e, 0 xbe, 0 x4e, 0 xce, 0 x0e,
0 x8e, 0 x6e, 0 xee, 0 x2e, 0 x52, 0 x12, 0 x72, 0 x32,
0 xb2, 0 x42, 0 xc2, 0 x02, 0 x82, 0 x62, 0 xe2, 0 x22,
0 xa2, 0 x5a, 0 xda, 0 x1a, 0 x9a, 0 x7a, 0 xfa, 0 x3a,
0 xba, 0 xba, 0 x4a, 0 x4a, 0 xca, 0 xca, 0 x0a, 0 x0a,
0 x8a, 0 x8a, 0 x6a, 0 x6a, 0 xea, 0 xea, 0 x2a, 0 x2a
};
/* alaw -> 4bit compression */
static u8 alaw_to_4bit[256 ] = {
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x08, 0 x07, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x09, 0 x06, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x08, 0 x07, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x09, 0 x06, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x08, 0 x07, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0d, 0 x02,
0 x0e, 0 x02, 0 x09, 0 x06, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x08, 0 x07, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x09, 0 x06, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x08, 0 x07, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x09, 0 x06, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x02, 0 x09, 0 x06, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0d, 0 x02, 0 x08, 0 x07, 0 x0f, 0 x01, 0 x0a, 0 x05,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x09, 0 x07, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x08, 0 x07, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x09, 0 x06, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x08, 0 x07, 0 x0f, 0 x00, 0 x0b, 0 x04,
0 x0e, 0 x01, 0 x0a, 0 x05, 0 x0f, 0 x00, 0 x0c, 0 x03,
0 x0d, 0 x02, 0 x09, 0 x06, 0 x0f, 0 x00, 0 x0b, 0 x04,
};
/* 4bit -> alaw decompression */
static u8 _4 bit_to_alaw[16 ] = {
0 x5d, 0 x51, 0 xd9, 0 xd7, 0 x5f, 0 x53, 0 xa3, 0 x4b,
0 x2a, 0 x3a, 0 x22, 0 x2e, 0 x26, 0 x56, 0 x20, 0 x2c,
};
/* ulaw -> 4bit compression */
static u8 ulaw_to_4bit[256 ] = {
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x01,
0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x01, 0 x01,
0 x02, 0 x02, 0 x02, 0 x02, 0 x02, 0 x02, 0 x02, 0 x02,
0 x02, 0 x02, 0 x02, 0 x02, 0 x02, 0 x02, 0 x02, 0 x02,
0 x03, 0 x03, 0 x03, 0 x03, 0 x03, 0 x03, 0 x03, 0 x03,
0 x03, 0 x03, 0 x03, 0 x03, 0 x03, 0 x03, 0 x04, 0 x04,
0 x04, 0 x04, 0 x04, 0 x04, 0 x04, 0 x04, 0 x04, 0 x04,
0 x04, 0 x04, 0 x04, 0 x04, 0 x05, 0 x05, 0 x05, 0 x05,
0 x05, 0 x05, 0 x05, 0 x05, 0 x05, 0 x05, 0 x05, 0 x05,
0 x06, 0 x06, 0 x06, 0 x06, 0 x06, 0 x06, 0 x06, 0 x06,
0 x07, 0 x07, 0 x07, 0 x07, 0 x07, 0 x07, 0 x07, 0 x07,
0 x07, 0 x07, 0 x07, 0 x07, 0 x07, 0 x07, 0 x07, 0 x08,
0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f,
0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f,
0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f,
0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f, 0 x0f,
0 x0f, 0 x0e, 0 x0e, 0 x0e, 0 x0e, 0 x0e, 0 x0e, 0 x0e,
0 x0e, 0 x0e, 0 x0e, 0 x0e, 0 x0e, 0 x0e, 0 x0e, 0 x0e,
0 x0e, 0 x0d, 0 x0d, 0 x0d, 0 x0d, 0 x0d, 0 x0d, 0 x0d,
0 x0d, 0 x0d, 0 x0d, 0 x0d, 0 x0d, 0 x0d, 0 x0d, 0 x0d,
0 x0c, 0 x0c, 0 x0c, 0 x0c, 0 x0c, 0 x0c, 0 x0c, 0 x0c,
0 x0c, 0 x0c, 0 x0c, 0 x0c, 0 x0c, 0 x0c, 0 x0b, 0 x0b,
0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0b,
0 x0b, 0 x0b, 0 x0b, 0 x0b, 0 x0a, 0 x0a, 0 x0a, 0 x0a,
0 x0a, 0 x0a, 0 x0a, 0 x0a, 0 x0a, 0 x0a, 0 x0a, 0 x0a,
0 x09, 0 x09, 0 x09, 0 x09, 0 x09, 0 x09, 0 x09, 0 x09,
0 x09, 0 x08, 0 x08, 0 x08, 0 x08, 0 x08, 0 x08, 0 x08,
0 x08, 0 x08, 0 x08, 0 x08, 0 x08, 0 x08, 0 x08, 0 x08,
};
/* 4bit -> ulaw decompression */
static u8 _4 bit_to_ulaw[16 ] = {
0 x11, 0 x21, 0 x31, 0 x40, 0 x4e, 0 x5c, 0 x68, 0 x71,
0 xfe, 0 xef, 0 xe7, 0 xdb, 0 xcd, 0 xbf, 0 xaf, 0 x9f,
};
/*
* Compresses data to the result buffer
* The result size must be at least half of the input buffer .
* The number of samples also must be even !
*/
int
l1oip_law_to_4bit(u8 *data, int len, u8 *result, u32 *state)
{
int ii, i = 0 , o = 0 ;
if (!len)
return 0 ;
/* send saved byte and first input byte */
if (*state) {
*result++ = table_com[(((*state) << 8 ) & 0 xff00) | (*data++)];
len--;
o++;
}
ii = len >> 1 ;
while (i < ii) {
*result++ = table_com[(data[0 ]<<8 ) | (data[1 ])];
data += 2 ;
i++;
o++;
}
/* if len has an odd number, we save byte for next call */
if (len & 1 )
*state = 0 x100 + *data;
else
*state = 0 ;
return o;
}
/* Decompress data to the result buffer
* The result size must be the number of sample in packet . ( 2 * input data )
* The number of samples in the result are even !
*/
int
l1oip_4bit_to_law(u8 *data, int len, u8 *result)
{
int i = 0 ;
u16 r;
while (i < len) {
r = table_dec[*data++];
*result++ = r >> 8 ;
*result++ = r;
i++;
}
return len << 1 ;
}
/*
* law conversion
*/
int
l1oip_alaw_to_ulaw(u8 *data, int len, u8 *result)
{
int i = 0 ;
while (i < len) {
*result++ = alaw_to_ulaw[*data++];
i++;
}
return len;
}
int
l1oip_ulaw_to_alaw(u8 *data, int len, u8 *result)
{
int i = 0 ;
while (i < len) {
*result++ = ulaw_to_alaw[*data++];
i++;
}
return len;
}
/*
* generate / free compression and decompression table
*/
void
l1oip_4bit_free(void )
{
vfree(table_dec);
vfree(table_com);
table_com = NULL;
table_dec = NULL;
}
int
l1oip_4bit_alloc(int ulaw)
{
int i1, i2, c, sample;
/* in case, it is called again */
if (table_dec)
return 0 ;
/* alloc conversion tables */
table_com = vzalloc(65536 );
table_dec = vzalloc(512 );
if (!table_com || !table_dec) {
l1oip_4bit_free();
return -ENOMEM;
}
/* generate compression table */
i1 = 0 ;
while (i1 < 256 ) {
if (ulaw)
c = ulaw_to_4bit[i1];
else
c = alaw_to_4bit[i1];
i2 = 0 ;
while (i2 < 256 ) {
table_com[(i1 << 8 ) | i2] |= (c << 4 );
table_com[(i2 << 8 ) | i1] |= c;
i2++;
}
i1++;
}
/* generate decompression table */
i1 = 0 ;
while (i1 < 16 ) {
if (ulaw)
sample = _4 bit_to_ulaw[i1];
else
sample = _4 bit_to_alaw[i1];
i2 = 0 ;
while (i2 < 16 ) {
table_dec[(i1 << 4 ) | i2] |= (sample << 8 );
table_dec[(i2 << 4 ) | i1] |= sample;
i2++;
}
i1++;
}
return 0 ;
}
Messung V0.5 in Prozent C=95 H=69 G=82