Click here to Skip to main content
Click here to Skip to main content
Articles » Languages » C# » General » Downloads
 
Add your own
alternative version

Using OpenTK/OpenAL to Develop Cross Platform DIS VOIP Application

, 15 Mar 2010 BSD
Application allows voice communications (VOIP) utilizing the Distributed Interactive Simulation protocol (IEEE 1278.1)
MonoDISRadioTransmitter_SourceCode.zip
MonoDISRadioTransmitter
AudioIN
bin
Properties
StyleCop.Cache
AudioOUT
bin
Properties
DISNET
bin
DataStreams
DISPDU
Enumerations
Properties
Utilities
OpenDISRadioTransmitterExample
AudioCodecs
bin
OpenDISRadioTransmitter.csproj.user
OpenTK
OpenTK.Compatibility.dll
OpenTK.dll
OpenTK.GLControl.dll
Properties
Settings.settings
StyleCop.Cache
OpenDISRadioTransmitterSolution.suo
RadioFeatureSelection
bin
Properties
Sockets
bin
Properties
namespace LumiSoft.Net.Media.Codec.Audio
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    /// <summary>
    /// Implements PCMA(G711 alaw) codec.
    /// </summary>
    public class PCMA : AudioCodec
    {
        #region Fields

        private static readonly byte[] ALawCompressTable = new byte[]{ 
            1,1,2,2,3,3,3,3,
            4,4,4,4,4,4,4,4,
            5,5,5,5,5,5,5,5,
            5,5,5,5,5,5,5,5,
            6,6,6,6,6,6,6,6,
            6,6,6,6,6,6,6,6,
            6,6,6,6,6,6,6,6,
            6,6,6,6,6,6,6,6,
            7,7,7,7,7,7,7,7,
            7,7,7,7,7,7,7,7,
            7,7,7,7,7,7,7,7,
            7,7,7,7,7,7,7,7,
            7,7,7,7,7,7,7,7,
            7,7,7,7,7,7,7,7,
            7,7,7,7,7,7,7,7,
            7,7,7,7,7,7,7,7
        };
        private 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,
            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
        };

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Default constructor.
        /// </summary>
        public PCMA()
        {
        }

        #endregion Constructors

        #region Properties

        /// <summary>
        /// Gets number of bits per sample.
        /// </summary>
        public override int BitsPerSample
        {
            get{ return 8; }
        }

        /// <summary>
        /// Gets codec name.
        /// </summary>
        public override string Name
        {
            get{ return "PCMA"; }
        }

        /// <summary>
        /// Gets sample number of samples in second(hz). 
        /// </summary>
        public override int SampleRate
        {
            get{ return 8000; }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Decodes 8-bit alaw to 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>Returns decoded data.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>buffer</b> is null reference.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        public override byte[] Decode(byte[] buffer,int offset,int count)
        {
            if(buffer == null){
                throw new ArgumentNullException("buffer");
            }
            if(offset < 0 || offset > buffer.Length){
                throw new ArgumentException("Argument 'offse't is out of range.");
            }
            if(count < 1 || (count + offset) > buffer.Length){
                throw new ArgumentException("Argument 'count' 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 alaw.
        /// </summary>
        /// <param name="buffer">Data to encode. 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 block.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>buffer</b> is null reference.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        public override byte[] Encode(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 'count' is out of range.");
            }
            if((count % 2) != 0){
                throw new ArgumentException("Invalid 'count' 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;
        }

        private 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;
        }

        #endregion Methods
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The BSD License

Share

About the Author

pesmith
Software Developer
United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web02 | 2.8.141022.2 | Last Updated 15 Mar 2010
Article Copyright 2010 by pesmith
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid