G711 语音压缩的 C#实现

 

using System;

public class G711
{
    
static readonly byte[] ALawCompressTable = new byte[] 
    { 
         
1122333344444444,
         
5555555555555555,
         
6666666666666666
         
6666666666666666
         
7777777777777777,
         
7777777777777777
         
7777777777777777,
         
7777777777777777 
    };

    
static readonly short[] ALawDecompressTable = new short[] 
    {
        
-5504-5248-6016-5760-4480-4224-4992-4736
        
-7552-7296-8064-7808-6528-6272-7040-6784
        
-2752-2624-3008-2880-2240-2112-2496-2368
        
-3776-3648-4032-3904-3264-3136-3520-3392
        
-22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944
        
-30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136
        
-11008,-10496,-12032,-11520,-8960-8448-9984-9472
        
-15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568
        
-344,  -328,  -376,  -360,  -280,  -264,  -312,  -296
        
-472,  -456,  -504,  -488,  -408,  -392,  -440,  -424
        
-88,   -72,   -120,  -104,  -24,   -8,    -56,   -40
        
-216,  -200,  -248,  -232,  -152,  -136,  -184,  -168
        
-1376-1312-1504-1440-1120-1056-1248-1184
        
-1888-1824-2016-1952-1632-1568-1760-1696
        
-688,  -656,  -752,  -720,  -560,  -528,  -624,  -592
        
-944,  -912,  -1008-976,  -816,  -784,  -880,  -848
        
5504,  5248,  6016,  5760,  4480,  4224,  4992,  4736
        
7552,  7296,  8064,  7808,  6528,  6272,  7040,  6784
        
2752,  2624,  3008,  2880,  2240,  2112,  2496,  2368
        
3776,  3648,  4032,  3904,  3264,  3136,  3520,  3392
        
2201620992240642304017920168961996818944
        
3020829184322563123226112250882816027136
        
110081049612032115208960,  8448,  9984,  9472
        
1510414592161281561613056125441408013568
        
344,   328,   376,   360,   280,   264,   312,   296
        
472,   456,   504,   488,   408,   392,   440,   424
        
88,    72,   120,   104,    24,     8,    56,    40
        
216,   200,   248,   232,   152,   136,   184,   168
        
1376,  1312,  1504,  1440,  1120,  1056,  1248,  1184
        
1888,  1824,  2016,  1952,  1632,  1568,  1760,  1696
        
688,   656,   752,   720,   560,   528,   624,   592
        
944,   912,  1008,   976,   816,   784,   880,   848 
    };

    
static readonly byte[] MuLawCompressTable = new byte[] 
    {
        
0011222233333333
        
4444444444444444,
        
5555555555555555
        
5555555555555555
        
6666666666666666,
        
6666666666666666,
        
6666666666666666,
        
6666666666666666
        
7777777777777777,
        
7777777777777777,
        
7777777777777777,
        
7777777777777777,
        
7777777777777777
        
7777777777777777,
        
7777777777777777,
        
7777777777777777 
    };

    
static readonly short[] MuLawDecompressTable = new short[]
    { 
        
-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956
        
-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764
        
-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412
        
-11900,-11388,-10876,-10364-9852-9340-8828-8316
        
-7932-7676-7420-7164-6908-6652-6396-6140
        
-5884-5628-5372-5116-4860-4604-4348-4092
        
-3900-3772-3644-3516-3388-3260-3132-3004
        
-2876-2748-2620-2492-2364-2236-2108-1980
        
-1884-1820-1756-1692-1628-1564-1500-1436
        
-1372-1308-1244-1180-1116-1052,  -988,  -924
        
-876,  -844,  -812,  -780,  -748,  -716,  -684,  -652
        
-620,  -588,  -556,  -524,  -492,  -460,  -428,  -396
        
-372,  -356,  -340,  -324,  -308,  -292,  -276,  -260
        
-244,  -228,  -212,  -196,  -180,  -164,  -148,  -132
        
-120,  -112,  -104,   -96,   -88,   -80,   -72,   -64
        
-56,   -48,   -40,   -32,   -24,   -16,    -8,     0
        
3212431100300762905228028270042598024956
        
2393222908218842086019836188121778816764
        
1599615484149721446013948134361292412412
        
11900113881087610364,  9852,  9340,  8828,  8316
        
7932,  7676,  7420,  7164,  6908,  6652,  6396,  6140
        
5884,  5628,  5372,  5116,  4860,  4604,  4348,  4092
        
3900,  3772,  3644,  3516,  3388,  3260,  3132,  3004
        
2876,  2748,  2620,  2492,  2364,  2236,  2108,  1980
        
1884,  1820,  1756,  1692,  1628,  1564,  1500,  1436
        
1372,  1308,  1244,  1180,  1116,  1052,   988,   924
        
876,   844,   812,   780,   748,   716,   684,   652
        
620,   588,   556,   524,   492,   460,   428,   396
        
372,   356,   340,   324,   308,   292,   276,   260
        
244,   228,   212,   196,   180,   164,   148,   132
        
120,   112,   104,    96,    88,    80,    72,    64
        
56,    48,    40,    32,    24,    16,     8,     0 
 };

    
static byte LinearToALawSample(short sample)
    {
        
int sign = 0;
        
int exponent = 0;
        
int mantissa = 0;
        
byte compressedByte = 0;
        sign 
= ((~sample) >> 8& 0x80;
        
if (sign == 0)
            sample 
= (short)-sample;
        
if (sample > 32635)
            sample 
= 32635;
        
if (sample >= 256)
        {
            exponent 
= (int)ALawCompressTable[(sample >> 8& 0x7F];
            mantissa 
= (sample >> (exponent + 3)) & 0x0F;
            compressedByte 
= (byte)((exponent << 4| mantissa);
        }
        
else
            compressedByte 
= (byte)(sample >> 4);
        compressedByte 
^= (byte)(sign ^ 0x55);
        
return compressedByte;
    }

    
static byte LinearToMuLawSample(short sample)
    {
        
int cBias = 0x84;
        
int cClip = 32635;
        
int sign = (sample >> 8& 0x80;
        
if (sign != 0) sample = (short)-sample;
        
if (sample > cClip) sample = (short)cClip;
        sample 
= (short)(sample + cBias);
        
int exponent = (int)MuLawCompressTable[(sample >> 7& 0xFF];
        
int mantissa = (sample >> (exponent + 3)) & 0x0F;
        
int compressedByte = ~(sign | (exponent << 4| mantissa);
        
return (byte)compressedByte;
    }

    
/// <summary>Encodes linear 16-bit linear PCM to 8-bit a-law.</summary>
    
/// <param name="buffer">Data which to convert. Data must be in Little-Endian format.</param>
    
/// <param name="offset">Offset in the buffer.</param>
    
/// <param name="count">Number of bytes to encode.</param>
    
/// <returns>Returns encoded data.</returns>
    
/// <exception cref="ArgumentNullException">Is raised when when <b>buffer</b> is null.</exception>
    
/// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
    public static byte[] Encode_aLaw(byte[] buffer, int offset, int count)
    {
        
if (buffer == nullthrow new ArgumentNullException("buffer");
        
if (offset < 0 || offset > buffer.Length)
            
throw new ArgumentException("Argument offset is out of range.");
        
if (count < 1 || (count + offset) > buffer.Length)
            
throw new ArgumentException("Argument offset is out of range.");
        
if ((buffer.Length % 2!= 0)
            
throw new ArgumentException("Invalid buufer value, it doesn't contain 16-bit boundaries.");
        
int offsetInRetVal = 0;
        
byte[] retVal = new byte[count / 2];
        
while (offsetInRetVal < retVal.Length)
        {
            
// Little-Endian - lower byte,higer byte.
            short pcm = (short)(buffer[offset + 1<< 8 | buffer[offset]);
            offset 
+= 2;
            retVal[offsetInRetVal
++= LinearToALawSample(pcm);
        }
        
return retVal;
    }

    
/// <summary>Decodes 8-bit a-law to 16-bit linear 16-bit PCM.</summary>
    
/// <param name="buffer">Data to decode. Data must be in Little-Endian format.</param>
    
/// <param name="offset">Offset in the buffer.</param>
    
/// <param name="count">Number of bytes to decode.</param>
    
/// <returns>Return decoded data.</returns>
    
/// <exception cref="ArgumentNullException">Is raised when when <b>buffer</b> is null.</exception>
    
/// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
    public static byte[] Decode_aLaw(byte[] buffer, int offset, int count)
    {
        
if (buffer == null)
            
throw new ArgumentNullException("buffer");
        
if (offset < 0 || offset > buffer.Length)
            
throw new ArgumentException("Argument offset is out of range.");
        
if (count < 1 || (count + offset) > buffer.Length)
            
throw new ArgumentException("Argument offset is out of range.");
        
int offsetInRetVal = 0;
        
byte[] retVal = new byte[count * 2];
        
for (int i = offset; i < buffer.Length; i++)
        {
            
short pcm = ALawDecompressTable[buffer[i]];
            retVal[offsetInRetVal
++= (byte)(pcm & 0xFF);
            retVal[offsetInRetVal
++= (byte)(pcm >> 8 & 0xFF);
        }
        
return retVal;
    }

    
/// <summary>Encodes linear 16-bit linear PCM to 8-bit u-law.</summary>
    
/// <param name="buffer">Data which to convert. Data must be in Little-Endian format.</param>
    
/// <param name="offset">Offset in the buffer.</param>
    
/// <param name="count">Number of bytes to encode.</param>
    
/// <returns>Returns encoded data.</returns>
    public static byte[] Encode_uLaw(byte[] buffer, int offset, int count)
    {
        
if (buffer == null)
            
throw new ArgumentNullException("buffer");
        
if (offset < 0 || offset > buffer.Length)
            
throw new ArgumentException("Argument offset is out of range.");
        
if (count < 1 || (count + offset) > buffer.Length)
            
throw new ArgumentException("Argument offset is out of range.");
        
if ((buffer.Length % 2!= 0)
            
throw new ArgumentException("Invalid buufer value, it doesn't contain 16-bit boundaries.");
        
int offsetInRetVal = 0;
        
byte[] retVal = new byte[count / 2];
        
while (offsetInRetVal < retVal.Length)
        {
            
// Little-Endian - lower byte,higer byte.
            short pcm = (short)(buffer[offset + 1<< 8 | buffer[offset]);
            offset 
+= 2;
            retVal[offsetInRetVal
++= LinearToMuLawSample(pcm);
        }
        
return retVal;
    }

    
/// <summary>Decodes 8-bit u-law to 16-bit linear 16-bit PCM.</summary>
    
/// <param name="buffer">Data to decode. Data must be in Little-Endian format.</param>
    
/// <param name="offset">Offset in the buffer.</param>
    
/// <param name="count">Number of bytes to decode.</param>
    
/// <returns>Return decoded data.</returns>
    
/// <exception cref="ArgumentNullException">Is raised when when <b>buffer</b> is null.</exception>
    
/// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
    public static byte[] Decode_uLaw(byte[] buffer, int offset, int count)
    {
        
if (buffer == null)
            
throw new ArgumentNullException("buffer");
        
if (offset < 0 || offset > buffer.Length)
            
throw new ArgumentException("Argument offset is out of range.");
        
if (count < 1 || (count + offset) > buffer.Length)
            
throw new ArgumentException("Argument offset is out of range.");
        
int offsetInRetVal = 0;
        
byte[] retVal = new byte[count * 2];
        
for (int i = offset; i < buffer.Length; i++)
        {
            
short pcm = MuLawDecompressTable[buffer[i]];
            retVal[offsetInRetVal
++= (byte)(pcm & 0xFF);
            retVal[offsetInRetVal
++= (byte)(pcm >> 8 & 0xFF);
        }
        
return retVal;
    }

}

技术讨论的QQ群: 2514097 或 10987609

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值