liveMedia/uLawAudioFilter.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2013 Live Networks, Inc.  All rights reserved.
00018 // Filters for converting between raw PCM audio and uLaw
00019 // Implementation
00020 
00021 #include "uLawAudioFilter.hh"
00022 
00024 
00025 uLawFromPCMAudioSource* uLawFromPCMAudioSource
00026 ::createNew(UsageEnvironment& env, FramedSource* inputSource, int byteOrdering) {
00027   // "byteOrdering" must be 0, 1, or 2:
00028   if (byteOrdering < 0 || byteOrdering > 2) {
00029     env.setResultMsg("uLawFromPCMAudioSource::createNew(): bad \"byteOrdering\" parameter");
00030     return NULL;
00031   }
00032   return new uLawFromPCMAudioSource(env, inputSource, byteOrdering);
00033 }
00034 
00035 uLawFromPCMAudioSource
00036 ::uLawFromPCMAudioSource(UsageEnvironment& env, FramedSource* inputSource,
00037                          int byteOrdering)
00038   : FramedFilter(env, inputSource),
00039     fByteOrdering(byteOrdering), fInputBuffer(NULL), fInputBufferSize(0) {
00040 }
00041 
00042 uLawFromPCMAudioSource::~uLawFromPCMAudioSource() {
00043   delete[] fInputBuffer;
00044 }
00045 
00046 void uLawFromPCMAudioSource::doGetNextFrame() {
00047   // Figure out how many bytes of input data to ask for, and increase
00048   // our input buffer if necessary:
00049   unsigned bytesToRead = fMaxSize*2; // because we're converting 16 bits->8
00050   if (bytesToRead > fInputBufferSize) {
00051     delete[] fInputBuffer; fInputBuffer = new unsigned char[bytesToRead];
00052     fInputBufferSize = bytesToRead;
00053   }
00054 
00055   // Arrange to read samples into the input buffer:
00056   fInputSource->getNextFrame(fInputBuffer, bytesToRead,
00057                              afterGettingFrame, this,
00058                              FramedSource::handleClosure, this);
00059 }
00060 
00061 void uLawFromPCMAudioSource
00062 ::afterGettingFrame(void* clientData, unsigned frameSize,
00063                     unsigned numTruncatedBytes,
00064                     struct timeval presentationTime,
00065                     unsigned durationInMicroseconds) {
00066   uLawFromPCMAudioSource* source = (uLawFromPCMAudioSource*)clientData;
00067   source->afterGettingFrame1(frameSize, numTruncatedBytes,
00068                              presentationTime, durationInMicroseconds);
00069 }
00070 
00071 #define BIAS 0x84   // the add-in bias for 16 bit samples
00072 #define CLIP 32635
00073 
00074 static unsigned char uLawFrom16BitLinear(u_int16_t sample) {
00075   static int const exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
00076                                    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
00077                                    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00078                                    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00079                                    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00080                                    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00081                                    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00082                                    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00083                                    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00084                                    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00085                                    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00086                                    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00087                                    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00088                                    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00089                                    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00090                                    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
00091   unsigned char sign = (sample >> 8) & 0x80;
00092   if (sign != 0) sample = -sample; // get the magnitude
00093 
00094   if (sample > CLIP) sample = CLIP; // clip the magnitude
00095   sample += BIAS;
00096 
00097   unsigned char exponent = exp_lut[(sample>>7) & 0xFF];
00098   unsigned char mantissa = (sample >> (exponent+3)) & 0x0F;
00099   unsigned char result = ~(sign | (exponent << 4) | mantissa);
00100   if (result == 0 ) result = 0x02;  // CCITT trap
00101 
00102   return result;
00103 }
00104 
00105 void uLawFromPCMAudioSource
00106 ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00107                      struct timeval presentationTime,
00108                      unsigned durationInMicroseconds) {
00109   // Translate raw 16-bit PCM samples (in the input buffer)
00110   // into uLaw samples (in the output buffer).
00111   unsigned numSamples = frameSize/2;
00112   switch (fByteOrdering) {
00113     case 0: { // host order
00114       u_int16_t* inputSample = (u_int16_t*)fInputBuffer;
00115       for (unsigned i = 0; i < numSamples; ++i) {
00116         fTo[i] = uLawFrom16BitLinear(inputSample[i]);
00117       }
00118       break;
00119     }
00120     case 1: { // little-endian order
00121       for (unsigned i = 0; i < numSamples; ++i) {
00122         u_int16_t const newValue = (fInputBuffer[2*i+1]<<8)|fInputBuffer[2*i];
00123         fTo[i] = uLawFrom16BitLinear(newValue);
00124       }
00125       break;
00126     }
00127     case 2: { // network (i.e., big-endian) order
00128       for (unsigned i = 0; i < numSamples; ++i) {
00129         u_int16_t const newValue = (fInputBuffer[2*i]<<8)|fInputBuffer[2*i+i];
00130         fTo[i] = uLawFrom16BitLinear(newValue);
00131       }
00132       break;
00133     }
00134   }
00135 
00136   // Complete delivery to the client:
00137   fFrameSize = numSamples;
00138   fNumTruncatedBytes = numTruncatedBytes;
00139   fPresentationTime = presentationTime;
00140   fDurationInMicroseconds = durationInMicroseconds;
00141   afterGetting(this);
00142 }
00143 
00144 
00146 
00147 PCMFromuLawAudioSource* PCMFromuLawAudioSource
00148 ::createNew(UsageEnvironment& env, FramedSource* inputSource) {
00149   return new PCMFromuLawAudioSource(env, inputSource);
00150 }
00151 
00152 PCMFromuLawAudioSource
00153 ::PCMFromuLawAudioSource(UsageEnvironment& env,
00154                          FramedSource* inputSource)
00155   : FramedFilter(env, inputSource),
00156     fInputBuffer(NULL), fInputBufferSize(0) {
00157 }
00158 
00159 PCMFromuLawAudioSource::~PCMFromuLawAudioSource() {
00160   delete[] fInputBuffer;
00161 }
00162 
00163 void PCMFromuLawAudioSource::doGetNextFrame() {
00164   // Figure out how many bytes of input data to ask for, and increase
00165   // our input buffer if necessary:
00166   unsigned bytesToRead = fMaxSize/2; // because we're converting 8 bits->16
00167   if (bytesToRead > fInputBufferSize) {
00168     delete[] fInputBuffer; fInputBuffer = new unsigned char[bytesToRead];
00169     fInputBufferSize = bytesToRead;
00170   }
00171 
00172   // Arrange to read samples into the input buffer:
00173   fInputSource->getNextFrame(fInputBuffer, bytesToRead,
00174                              afterGettingFrame, this,
00175                              FramedSource::handleClosure, this);
00176 }
00177 
00178 void PCMFromuLawAudioSource
00179 ::afterGettingFrame(void* clientData, unsigned frameSize,
00180                     unsigned numTruncatedBytes,
00181                     struct timeval presentationTime,
00182                     unsigned durationInMicroseconds) {
00183   PCMFromuLawAudioSource* source = (PCMFromuLawAudioSource*)clientData;
00184   source->afterGettingFrame1(frameSize, numTruncatedBytes,
00185                              presentationTime, durationInMicroseconds);
00186 }
00187 
00188 static u_int16_t linear16FromuLaw(unsigned char uLawByte) {
00189   static int const exp_lut[8] = {0,132,396,924,1980,4092,8316,16764};
00190   uLawByte = ~uLawByte;
00191 
00192   Boolean sign = (uLawByte & 0x80) != 0;
00193   unsigned char exponent = (uLawByte>>4) & 0x07;
00194   unsigned char mantissa = uLawByte & 0x0F;
00195 
00196   u_int16_t result = exp_lut[exponent] + (mantissa << (exponent+3));
00197   if (sign) result = -result;
00198   return result;
00199 }
00200 
00201 void PCMFromuLawAudioSource
00202 ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00203                      struct timeval presentationTime,
00204                      unsigned durationInMicroseconds) {
00205   // Translate uLaw samples (in the input buffer)
00206   // into 16-bit PCM samples (in the output buffer), in host order.
00207   unsigned numSamples = frameSize;
00208   u_int16_t* outputSample = (u_int16_t*)fTo;
00209   for (unsigned i = 0; i < numSamples; ++i) {
00210     outputSample[i] = linear16FromuLaw(fInputBuffer[i]);
00211   }
00212 
00213   // Complete delivery to the client:
00214   fFrameSize = numSamples*2;
00215   fNumTruncatedBytes = numTruncatedBytes;
00216   fPresentationTime = presentationTime;
00217   fDurationInMicroseconds = durationInMicroseconds;
00218   afterGetting(this);
00219 }
00220 
00221 
00223 
00224 NetworkFromHostOrder16* NetworkFromHostOrder16
00225 ::createNew(UsageEnvironment& env, FramedSource* inputSource) {
00226   return new NetworkFromHostOrder16(env, inputSource);
00227 }
00228 
00229 NetworkFromHostOrder16
00230 ::NetworkFromHostOrder16(UsageEnvironment& env,
00231                          FramedSource* inputSource)
00232   : FramedFilter(env, inputSource) {
00233 }
00234 
00235 NetworkFromHostOrder16::~NetworkFromHostOrder16() {
00236 }
00237 
00238 void NetworkFromHostOrder16::doGetNextFrame() {
00239   // Arrange to read data directly into the client's buffer:
00240   fInputSource->getNextFrame(fTo, fMaxSize,
00241                              afterGettingFrame, this,
00242                              FramedSource::handleClosure, this);
00243 }
00244 
00245 void NetworkFromHostOrder16
00246 ::afterGettingFrame(void* clientData, unsigned frameSize,
00247                     unsigned numTruncatedBytes,
00248                     struct timeval presentationTime,
00249                     unsigned durationInMicroseconds) {
00250   NetworkFromHostOrder16* source = (NetworkFromHostOrder16*)clientData;
00251   source->afterGettingFrame1(frameSize, numTruncatedBytes,
00252                              presentationTime, durationInMicroseconds);
00253 }
00254 
00255 void NetworkFromHostOrder16
00256 ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00257                      struct timeval presentationTime,
00258                      unsigned durationInMicroseconds) {
00259   // Translate the 16-bit values that we have just read from host
00260   // to network order (in-place)
00261   unsigned numValues = frameSize/2;
00262   u_int16_t* value = (u_int16_t*)fTo;
00263   for (unsigned i = 0; i < numValues; ++i) {
00264     value[i] = htons(value[i]);
00265   }
00266 
00267   // Complete delivery to the client:
00268   fFrameSize = numValues*2;
00269   fNumTruncatedBytes = numTruncatedBytes;
00270   fPresentationTime = presentationTime;
00271   fDurationInMicroseconds = durationInMicroseconds;
00272   afterGetting(this);
00273 }
00274 
00275 
00277 
00278 HostFromNetworkOrder16* HostFromNetworkOrder16
00279 ::createNew(UsageEnvironment& env, FramedSource* inputSource) {
00280   return new HostFromNetworkOrder16(env, inputSource);
00281 }
00282 
00283 HostFromNetworkOrder16
00284 ::HostFromNetworkOrder16(UsageEnvironment& env,
00285                          FramedSource* inputSource)
00286   : FramedFilter(env, inputSource) {
00287 }
00288 
00289 HostFromNetworkOrder16::~HostFromNetworkOrder16() {
00290 }
00291 
00292 void HostFromNetworkOrder16::doGetNextFrame() {
00293   // Arrange to read data directly into the client's buffer:
00294   fInputSource->getNextFrame(fTo, fMaxSize,
00295                              afterGettingFrame, this,
00296                              FramedSource::handleClosure, this);
00297 }
00298 
00299 void HostFromNetworkOrder16
00300 ::afterGettingFrame(void* clientData, unsigned frameSize,
00301                     unsigned numTruncatedBytes,
00302                     struct timeval presentationTime,
00303                     unsigned durationInMicroseconds) {
00304   HostFromNetworkOrder16* source = (HostFromNetworkOrder16*)clientData;
00305   source->afterGettingFrame1(frameSize, numTruncatedBytes,
00306                              presentationTime, durationInMicroseconds);
00307 }
00308 
00309 void HostFromNetworkOrder16
00310 ::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00311                      struct timeval presentationTime,
00312                      unsigned durationInMicroseconds) {
00313   // Translate the 16-bit values that we have just read from network
00314   // to host order (in-place):
00315   unsigned numValues = frameSize/2;
00316   u_int16_t* value = (u_int16_t*)fTo;
00317   for (unsigned i = 0; i < numValues; ++i) {
00318     value[i] = ntohs(value[i]);
00319   }
00320 
00321   // Complete delivery to the client:
00322   fFrameSize = numValues*2;
00323   fNumTruncatedBytes = numTruncatedBytes;
00324   fPresentationTime = presentationTime;
00325   fDurationInMicroseconds = durationInMicroseconds;
00326   afterGetting(this);
00327 }
00328 
00329 
00331 
00332 EndianSwap16*
00333 EndianSwap16::createNew(UsageEnvironment& env, FramedSource* inputSource) {
00334   return new EndianSwap16(env, inputSource);
00335 }
00336 
00337 EndianSwap16::EndianSwap16(UsageEnvironment& env,
00338                          FramedSource* inputSource)
00339   : FramedFilter(env, inputSource) {
00340 }
00341 
00342 EndianSwap16::~EndianSwap16() {
00343 }
00344 
00345 void EndianSwap16::doGetNextFrame() {
00346   // Arrange to read data directly into the client's buffer:
00347   fInputSource->getNextFrame(fTo, fMaxSize,
00348                              afterGettingFrame, this,
00349                              FramedSource::handleClosure, this);
00350 }
00351 
00352 void EndianSwap16::afterGettingFrame(void* clientData, unsigned frameSize,
00353                                      unsigned numTruncatedBytes,
00354                                      struct timeval presentationTime,
00355                                      unsigned durationInMicroseconds) {
00356   EndianSwap16* source = (EndianSwap16*)clientData;
00357   source->afterGettingFrame1(frameSize, numTruncatedBytes,
00358                              presentationTime, durationInMicroseconds);
00359 }
00360 
00361 void EndianSwap16::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00362                                       struct timeval presentationTime,
00363                                       unsigned durationInMicroseconds) {
00364   // Swap the byte order of the 16-bit values that we have just read (in place):
00365   unsigned numValues = frameSize/2;
00366   u_int16_t* value = (u_int16_t*)fTo;
00367   for (unsigned i = 0; i < numValues; ++i) {
00368     u_int16_t const orig = value[i];
00369     value[i] = ((orig&0xFF)<<8) | ((orig&0xFF00)>>8);
00370   }
00371 
00372   // Complete delivery to the client:
00373   fFrameSize = numValues*2;
00374   fNumTruncatedBytes = numTruncatedBytes + (frameSize - fFrameSize);
00375   fPresentationTime = presentationTime;
00376   fDurationInMicroseconds = durationInMicroseconds;
00377   afterGetting(this);
00378 }
00379 
00380 
00382 
00383 EndianSwap24*
00384 EndianSwap24::createNew(UsageEnvironment& env, FramedSource* inputSource) {
00385   return new EndianSwap24(env, inputSource);
00386 }
00387 
00388 EndianSwap24::EndianSwap24(UsageEnvironment& env,
00389                          FramedSource* inputSource)
00390   : FramedFilter(env, inputSource) {
00391 }
00392 
00393 EndianSwap24::~EndianSwap24() {
00394 }
00395 
00396 void EndianSwap24::doGetNextFrame() {
00397   // Arrange to read data directly into the client's buffer:
00398   fInputSource->getNextFrame(fTo, fMaxSize,
00399                              afterGettingFrame, this,
00400                              FramedSource::handleClosure, this);
00401 }
00402 
00403 void EndianSwap24::afterGettingFrame(void* clientData, unsigned frameSize,
00404                                      unsigned numTruncatedBytes,
00405                                      struct timeval presentationTime,
00406                                      unsigned durationInMicroseconds) {
00407   EndianSwap24* source = (EndianSwap24*)clientData;
00408   source->afterGettingFrame1(frameSize, numTruncatedBytes,
00409                              presentationTime, durationInMicroseconds);
00410 }
00411 
00412 void EndianSwap24::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
00413                                       struct timeval presentationTime,
00414                                       unsigned durationInMicroseconds) {
00415   // Swap the byte order of the 24-bit values that we have just read (in place):
00416   unsigned const numValues = frameSize/3;
00417   u_int8_t* p = fTo;
00418   for (unsigned i = 0; i < numValues; ++i) {
00419     u_int8_t tmp = p[0];
00420     p[0] = p[2];
00421     p[2] = tmp;
00422     p += 3;
00423   }
00424 
00425   // Complete delivery to the client:
00426   fFrameSize = numValues*3;
00427   fNumTruncatedBytes = numTruncatedBytes + (frameSize - fFrameSize);
00428   fPresentationTime = presentationTime;
00429   fDurationInMicroseconds = durationInMicroseconds;
00430   afterGetting(this);
00431 }

Generated on Mon Apr 29 13:28:03 2013 for live by  doxygen 1.5.2