• Main Page
  • Related Pages
  • Packages
  • Classes
  • Files
  • File List

audio/AudioCodecAlaw.java

Go to the documentation of this file.
00001 
00002 package audio;
00003 
00004 import utils.OctetBuffer;
00005 
00006 /**
00007  *  Converts a 16-bit linear PCM stream from and to 8-bit A-law.
00008  *  
00009  *  @author Mikica B Kocic, based on Sun Microsystem's C source code.
00010  */
00011 public class AudioCodecAlaw extends AbstractCODEC
00012 {
00013     private int sampleSize;
00014 
00015     /**
00016      *  Constructs A-Law CODEC above existing PCM audio interface
00017      */
00018     public AudioCodecAlaw( AudioInterfacePCM audio ) 
00019     {
00020         this.audio = audio;
00021         this.sampleSize = this.audio.getSampleSize ();
00022         this.outputPcmBuf = new byte[ this.sampleSize ];
00023         this.inputPcmBuf = new byte[ this.sampleSize ];
00024     }
00025 
00026     /**
00027      * Gets the VoicePDU subclass attribute of the AbstractAudio object
00028      */
00029     public int getVoicePduSubclass () 
00030     {
00031         return protocol.VoicePDU.ALAW;
00032     }
00033 
00034     /**
00035      *  Returns the minimum sample size for use in creating buffers etc.
00036      */
00037     public int getSampleSize ()
00038     {
00039         return 160;
00040     }
00041 
00042     /**
00043      *  Encodes data to PCM, i.e. converts samples from A-Law to CODEC format.
00044      */
00045     public void convertToPCM( byte[] in, byte[] out )
00046     {
00047         OctetBuffer bb = OctetBuffer.wrap( out );
00048 
00049         for ( int i = 0; i < in.length; ++i ) 
00050         {
00051             bb.putShort( alaw2linear( in[i] ) );
00052         }
00053     }
00054 
00055     /**
00056      *  Decodes data from PCM, i.e. converts samples from CODEC to A-Law format.
00057      */
00058     public void convertFromPCM( byte[] in, byte[] out ) 
00059     {
00060         OctetBuffer bb = OctetBuffer.wrap( in );
00061 
00062         for( int i = 0; i < in.length / 2; ++i )
00063         {
00064             out[i] = linear2alaw( bb.getShort () );
00065         }
00066     }
00067 
00068     ///////////////////////////////////////////////////////////// ALGORITHM //////////////
00069     /*
00070      *  Converts a 16-bit linear PCM stream from and to 8-bit A-law.
00071      *  
00072      *  <pre>
00073      *     Linear Input Code    Compressed Code
00074      *     ------------------------ ---------------
00075      *     0000000wxyza         000wxyz
00076      *     0000001wxyza         001wxyz
00077      *     000001wxyzab         010wxyz
00078      *     00001wxyzabc         011wxyz
00079      *     0001wxyzabcd         100wxyz
00080      *     001wxyzabcde         101wxyz
00081      *     01wxyzabcdef         110wxyz
00082      *     1wxyzabcdefg         111wxyz
00083      *  </pre>
00084      *     
00085      *  This original source code is a product of Sun Microsystems, Inc. and is provided
00086      *  for unrestricted use. Users may copy or modify this source code without charge.
00087      *  For further information see John C. Bellamy's Digital Telephony, 1982,
00088      *  John Wiley & Sons, pps 98-111 and 472-476.
00089      */
00090     
00091     /* Sign bit */
00092     private final static int SIGN_BIT = 0x80;
00093     
00094     /* Quantization field mask.  */
00095     private final static int QUANT_MASK = 0xf;
00096 
00097     /* Left shift for segment number.  */
00098     private final static int SEG_SHIFT = 4;
00099     private final static int SEG_MASK = 0x70;
00100     
00101     /* Segment-ends lookup table */
00102     private final static int[] seg_end = {
00103             0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF
00104             };
00105 
00106     /**
00107      *  Converts a 16-bit linear PCM value to 8-bit A-law
00108      */
00109     private static byte linear2alaw( short pcm_value ) 
00110     {
00111         
00112         int pcm = pcm_value >> 3;
00113 
00114         int mask;
00115         if ( pcm >= 0 )
00116         {
00117             mask = 0xD5; // sign (7th) bit = 1 
00118             }
00119         else 
00120         {
00121             mask = 0x55; // sign bit = 0 
00122             pcm = -pcm - 1;
00123             }
00124 
00125         /* Convert the scaled magnitude to segment number. 
00126          */
00127         int seg = 8;
00128         
00129         for ( int i = 0; i < 8; ++i ) {
00130             if ( pcm <= seg_end[i] ) {
00131                 seg = i;
00132                 break;
00133             }
00134         }
00135 
00136         /* Combine the sign, segment, and quantization bits. 
00137          */
00138         if ( seg >= 8 ) { // out of range, return maximum value. 
00139             return (byte)( (  0x7F ^ mask ) & 0xFF - 0x100 );
00140         }
00141 
00142         int aval = ( seg << SEG_SHIFT ) & 0xFF;
00143         
00144         if ( seg < 2 ) {
00145             aval |= (pcm >> 1) & QUANT_MASK;
00146         } else {
00147             aval |= (pcm >> seg) & QUANT_MASK;
00148         }
00149         
00150         return (byte)( ( aval ^ mask ) & 0xFF - 0x100 );
00151     }
00152 
00153     /**
00154      *  Converts an 8-bit A-law value to 16-bit linear PCM
00155      */
00156     private static short alaw2linear( byte alaw_value )
00157     {
00158         
00159         int a_val = ( ( alaw_value + 0x100 ) & 0xFF ) ^ 0x55;
00160         
00161         int t = ( a_val & QUANT_MASK ) << 4;
00162         int seg = ( a_val & SEG_MASK ) >> SEG_SHIFT;
00163         
00164         switch ( seg )
00165         {
00166             case 0:
00167                 t += 8;
00168                 break;
00169             case 1:
00170                 t += 0x108;
00171                 break;
00172             default:
00173                 t += 0x108;
00174                 t <<= seg - 1;
00175             }
00176 
00177         return (short)( ( a_val & SIGN_BIT ) != 0 ? t : -t );        
00178     }
00179 }
00180 

Generated on Thu Dec 16 2010 14:44:42 for VoIP Kryptofon by  doxygen 1.7.2