IT++ Logo
g711.h
Go to the documentation of this file.
1 
28 #ifndef G711_H
29 #define G711_H
30 
31 #include <itpp/itexports.h>
32 #include <utility>
33 #include <itpp/base/ittypes.h>
34 
64 namespace itpp {
65 
67 
68 //forward declarations to make friends visible
69 std::pair<int16_t,int16_t> ulaw_range();
70 uint8_t ulaw_compress(int16_t s);
71 int16_t ulaw_expand(uint8_t s);
72 std::pair<int16_t,int16_t> alaw_range();
73 uint8_t alaw_compress(int16_t s);
74 int16_t alaw_expand(uint8_t s);
75 
76 
77 namespace g711_details {
78  //This makes compression-expansion tables inaccessible in user's code
79  //while compression-expansion functions are still defined inline. Also, it
80  //hides property classes from itpp namespace.
81 
82  //Base properties of G.711 codecs
83  class G711_Base_Properties
84  {
85  protected:
87  static ITPP_EXPORT uint8_t compression_table[128];
88  };
89 
90  //u-law algorithm properties
91  class MuLaw_Properties : public G711_Base_Properties
92  {
93  //u-law codec input bitwidth
94  static const int input_bitwidth = 14;
95  //offset applied to magnitude of the input sample
96  static const int16_t magnitude_offset = 33;
97  //maximum input value according to G.711
98  static const int16_t input_max = 8158;
99  //minimum input value according to G.711
100  static const int16_t input_min = -8159;
101  //table used in u-law expansion
102  static ITPP_EXPORT int16_t expansion_table[256];
103 
104  friend std::pair<int16_t,int16_t> itpp::ulaw_range();
105  friend uint8_t itpp::ulaw_compress(int16_t s);
106  friend int16_t itpp::ulaw_expand(uint8_t s);
107  };
108 
109  //a-law algorithm properties
110  class ALaw_Properties : public G711_Base_Properties
111  {
112  //a-law codec input bitwidth
113  static const int input_bitwidth = 13;
114  //maximum input value according to G.711
115  static const int16_t input_max = 4095;
116  //minimum input value according to G.711
117  static const int16_t input_min = -4096;
118  //table used in u-law expansion
119  static ITPP_EXPORT int16_t expansion_table[256];
120 
121  friend std::pair<int16_t,int16_t> itpp::alaw_range();
122  friend uint8_t itpp::alaw_compress(int16_t s);
123  friend int16_t itpp::alaw_expand(uint8_t s);
124  };
125 }
127 
132 inline std::pair<int16_t,int16_t> ulaw_range()
133 {
134  using namespace g711_details;
135  return std::make_pair(MuLaw_Properties::input_min,MuLaw_Properties::input_max);
136 }
137 
138 
143 inline uint8_t ulaw_compress(int16_t s)
144 {
145  using namespace g711_details;
146  //Limiting and shifting. Negative samples are 1's complemented to align dynamic
147  //ranges of positive and negative numbers. Compressed negative
148  //and positive values of equal magnitude are distinguished by the sign bit.
149  //As per G.711 spec, resulting magnitude is shifted before compression.
150  uint8_t sign; uint16_t shifted_magnitude;
151  if(s >= 0){
152  if(s > MuLaw_Properties::input_max) s = MuLaw_Properties::input_max;
153  shifted_magnitude = s + MuLaw_Properties::magnitude_offset;
154  sign = 0xff;
155  }
156  else{
157  if(s < MuLaw_Properties::input_min) s = MuLaw_Properties::input_min;
158  shifted_magnitude = (MuLaw_Properties::magnitude_offset - 1) - s;
159  sign = 0x7f;
160  }
161  //use compression table to get the segment number. Segment number corresponds
162  //to the exponent value stored in compressed sample.
163  uint8_t seg_no = MuLaw_Properties::compression_table[shifted_magnitude>>6];
164  //extract 4 MSBs of magnitude, except leading 1, compose it with segment number
165  //and sign, store 1's complement value as compressed sample
166  uint8_t ret = (seg_no << 4) | ((shifted_magnitude >> (seg_no + 1)) & 0x0f);
167  ret ^= sign; //1's complement and add sign
168  return ret;
169 }
170 
176 inline int16_t ulaw_expand(uint8_t s){return g711_details::MuLaw_Properties::expansion_table[s];}
177 
182 inline std::pair<int16_t,int16_t> alaw_range()
183 {
184  using namespace g711_details;
185  return std::make_pair(ALaw_Properties::input_min,ALaw_Properties::input_max);
186 }
187 
192 inline uint8_t alaw_compress(int16_t s)
193 {
194  using namespace g711_details;
195  //Limiting. Negative samples are 1's complemented to align dynamic
196  //ranges of positive and negative numbers. Compressed negative
197  //and positive values of equal magnitude are distinguished by the sign bit.
198  uint8_t sign; uint16_t magnitude;
199  if(s >= 0){
200  if(s > ALaw_Properties::input_max) s = ALaw_Properties::input_max;
201  magnitude = s; sign = 0xd5;
202  }
203  else{//1's complement to get magnitude
204  if(s < ALaw_Properties::input_min) s = ALaw_Properties::input_min;
205  magnitude = -1 - s; sign = 0x55;
206  }
207  //use compression table to get the exponent.
208  uint8_t exp_val = ALaw_Properties::compression_table[magnitude>>5];
209  uint8_t ret;
210  if(exp_val > 0) {
211  //extract 4 MSBs of magnitude, except leading 1 and compose it with exponent
212  ret = (exp_val << 4) | ((magnitude >> (exp_val)) & 0x0f);
213  }
214  else{//exp is 0, store 4 MSBs of magnitude
215  ret = (uint8_t)magnitude >> 1;
216  }
217  ret ^= sign; //toggle even bits and add sign
218  return ret;
219 }
220 
226 inline int16_t alaw_expand(uint8_t s){return g711_details::ALaw_Properties::expansion_table[s];}
227 
228 }
229 
230 #endif
SourceForge Logo

Generated on Sat Jul 6 2013 10:54:25 for IT++ by Doxygen 1.8.2