Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

G711.cpp

Go to the documentation of this file.
00001 /*
00002 This program is distributed under the terms of the 'MIT license'. The text
00003 of this licence follows...
00004 
00005 Copyright (c) 2004 J.D.Medhurst (a.k.a. Tixy)
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00020 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00022 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00023 THE SOFTWARE.
00024 */
00025 
00032 #include "common.h"
00033 #include "G711.h"
00034 
00035 
00036 /*
00037 Members of class G711
00038 */
00039 
00040 
00041 EXPORT uint8_t G711::ALawEncode(int16_t pcm16)
00042     {
00043     int p = pcm16;
00044     unsigned a;  // A-law value we are forming
00045     if(p<0)
00046         {
00047         // -ve value
00048         // Note, ones compliment is used here as this keeps encoding symetrical
00049         // and equal spaced around zero cross-over, (it also matches the standard).
00050         p = ~p;
00051         a = 0x00; // sign = 0
00052         }
00053     else
00054         {
00055         // +ve value
00056         a = 0x80; // sign = 1
00057         }
00058 
00059     // Calculate segment and interval numbers
00060     p >>= 4;
00061     if(p>=0x20)
00062         {
00063         if(p>=0x100)
00064             {
00065             p >>= 4;
00066             a += 0x40;
00067             }
00068         if(p>=0x40)
00069             {
00070             p >>= 2;
00071             a += 0x20;
00072             }
00073         if(p>=0x20)
00074             {
00075             p >>= 1;
00076             a += 0x10;
00077             }
00078         }
00079     // a&0x70 now holds segment value and 'p' the interval number
00080 
00081     a += p;  // a now equal to encoded A-law value
00082 
00083     return a^0x55;  // A-law has alternate bits inverted for transmission
00084     }
00085 
00086 
00087 EXPORT int G711::ALawDecode(uint8_t alaw)
00088     {
00089     alaw ^= 0x55;  // A-law has alternate bits inverted for transmission
00090 
00091     unsigned sign = alaw&0x80;
00092 
00093     int linear = alaw&0x1f;
00094     linear <<= 4;
00095     linear += 8;  // Add a 'half' bit (0x08) to place PCM value in middle of range
00096 
00097     alaw &= 0x7f;
00098     if(alaw>=0x20)
00099         {
00100         linear |= 0x100;  // Put in MSB
00101         unsigned shift = (alaw>>4)-1;
00102         linear <<= shift;
00103         }
00104 
00105     if(!sign)
00106         return -linear;
00107     else
00108         return linear;
00109     }
00110 
00111 
00112 EXPORT uint8_t G711::ULawEncode(int16_t pcm16)
00113     {
00114     int p = pcm16;
00115     unsigned u;  // u-law value we are forming
00116 
00117     if(p<0)
00118         {
00119         // -ve value
00120         // Note, ones compliment is used here as this keeps encoding symetrical
00121         // and equal spaced around zero cross-over, (it also matches the standard).
00122         p = ~p;
00123         u = 0x80^0x10^0xff;  // Sign bit = 1, ^0x10 because this will get inverted later, ^0xff to invert final u-Law code
00124         }
00125     else
00126         {
00127         // +ve value
00128         u = 0x00^0x10^0xff;  // Sign bit = 0, ^0x10 because this will get inverted later, ^0xff to invert final u-Law code
00129         }
00130 
00131     p += 0x84; // Add uLaw bias
00132 
00133     if(p>0x7f00)
00134         p = 0x7f00;  // Clip to 15 bits
00135 
00136     // Calculate segment and interval numbers
00137     p >>= 3;    // Shift down to 13bit
00138     if(p>=0x100)
00139         {
00140         p >>= 4;
00141         u ^= 0x40;
00142         }
00143     if(p>=0x40)
00144         {
00145         p >>= 2;
00146         u ^= 0x20;
00147         }
00148     if(p>=0x20)
00149         {
00150         p >>= 1;
00151         u ^= 0x10;
00152         }
00153     // (u^0x10)&0x70 now equal to the segment value and 'p' the interval number ^0x10
00154 
00155     u ^= p; // u now equal to encoded u-law value (with all bits inverted)
00156 
00157     return u;
00158     }
00159 
00160 
00161 EXPORT int G711::ULawDecode(uint8_t ulaw)
00162     {
00163     ulaw ^= 0xff;  // u-law has all bits inverted for transmission
00164 
00165     int linear = ulaw&0x0f;
00166     linear <<= 3;
00167     linear |= 0x84;  // Set MSB (0x80) and a 'half' bit (0x04) to place PCM value in middle of range
00168 
00169     unsigned shift = ulaw>>4;
00170     shift &= 7;
00171     linear <<= shift;
00172 
00173     linear -= 0x84; // Subract uLaw bias
00174     
00175     if(ulaw&0x80)
00176         return -linear;
00177     else
00178         return linear;
00179     }
00180 
00181 
00182 EXPORT uint8_t G711::ALawToULaw(uint8_t alaw)
00183     {
00184     uint8_t sign=alaw&0x80;
00185     alaw ^= sign;
00186     alaw ^= 0x55;
00187     unsigned ulaw;
00188     if(alaw<45)
00189         {
00190         if(alaw<24)
00191             ulaw = (alaw<8) ? (alaw<<1)+1 : alaw+8;
00192         else
00193             ulaw = (alaw<32) ? (alaw>>1)+20 : alaw+4;
00194         }
00195     else
00196         {
00197         if(alaw<63)
00198             ulaw = (alaw<47) ? alaw+3 : alaw+2;
00199         else
00200             ulaw = (alaw<79) ? alaw+1 : alaw;
00201         }
00202     ulaw ^= sign;
00203     return ulaw^0x7f;
00204     }
00205 
00206 
00207 EXPORT uint8_t G711::ULawToALaw(uint8_t ulaw)
00208     {
00209     uint8_t sign=ulaw&0x80;
00210     ulaw ^= sign;
00211     ulaw ^= 0x7f;
00212     unsigned alaw;
00213     if(ulaw<48)
00214         {
00215         if(ulaw<=32)
00216             alaw = (ulaw<=15) ? ulaw>>1 : ulaw-8;
00217         else
00218             alaw = (ulaw<=35) ? (ulaw<<1)-40 : ulaw-4;
00219         }
00220     else
00221         {
00222         if(ulaw<=63)
00223             alaw = (ulaw==48) ? ulaw-3 : ulaw-2;
00224         else
00225             alaw = (ulaw<=79) ? ulaw-1 : ulaw;
00226         }
00227     alaw ^= sign;
00228     return alaw^0x55;
00229     }
00230 
00231 
00232 EXPORT unsigned G711::ALawEncode(uint8_t* dst, int16_t* src, size_t srcSize)
00233     {
00234     srcSize >>= 1;
00235     uint8_t* end = dst+srcSize;
00236     while(dst<end)
00237         *dst++ = ALawEncode(*src++);
00238     return srcSize;
00239     }
00240 
00241 
00242 EXPORT unsigned G711::ALawDecode(int16_t* dst, const uint8_t* src, size_t srcSize)
00243     {
00244     int16_t* end = dst+srcSize;
00245     while(dst<end)
00246         *dst++ = ALawDecode(*src++);
00247     return srcSize<<1;
00248     }
00249 
00250 
00251 EXPORT unsigned G711::ULawEncode(uint8_t* dst, int16_t* src, size_t srcSize)
00252     {
00253     srcSize >>= 1;
00254     uint8_t* end = dst+srcSize;
00255     while(dst<end)
00256         *dst++ = ULawEncode(*src++);
00257     return srcSize;
00258     }
00259 
00260 
00261 EXPORT unsigned G711::ULawDecode(int16_t* dst, const uint8_t* src, size_t srcSize)
00262     {
00263     int16_t* end = dst+srcSize;
00264     while(dst<end)
00265         *dst++ = ULawDecode(*src++);
00266     return srcSize<<1;
00267     }
00268 
00269 
00270 EXPORT unsigned G711::ALawToULaw(uint8_t* dst, const uint8_t* src, size_t srcSize)
00271     {
00272     uint8_t* end = dst+srcSize;
00273     while(dst<end)
00274         *dst++ = ALawToULaw(*src++);
00275     return srcSize;
00276     }
00277 
00278 
00279 EXPORT unsigned G711::ULawToALaw(uint8_t* dst, const uint8_t* src, size_t srcSize)
00280     {
00281     uint8_t* end = dst+srcSize;
00282     while(dst<end)
00283         *dst++ = ULawToALaw(*src++);
00284     return srcSize;
00285     }

Generated by  doxygen 1.4.4