home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Riza / source / ac_xlaw.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  8.6 KB  |  314 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    A/V interface library
  3. //    Copyright (C) 1998-2007 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <vd2/system/VDRingBuffer.h>
  20. #include <vd2/system/vdstl.h>
  21. #include <vd2/system/vdalloc.h>
  22. #include <vd2/Riza/audiocodec.h>
  23.  
  24. class VDAudioDecompressorXLaw : public IVDAudioCodec {
  25. public:
  26.     VDAudioDecompressorXLaw();
  27.     ~VDAudioDecompressorXLaw();
  28.  
  29.     bool Init(const VDWaveFormat *srcFormat, const VDWaveFormat *dstFormat, bool doALaw);
  30.     void Shutdown();
  31.  
  32.     bool IsEnded() const;
  33.  
  34.     unsigned    GetInputLevel() const;
  35.     unsigned    GetInputSpace() const;
  36.     unsigned    GetOutputLevel() const;
  37.     const VDWaveFormat *GetOutputFormat() const;
  38.     unsigned    GetOutputFormatSize() const;
  39.  
  40.     void        Restart();
  41.     bool        Convert(bool flush, bool requireOutput);
  42.  
  43.     void        *LockInputBuffer(unsigned& bytes);
  44.     void        UnlockInputBuffer(unsigned bytes);
  45.     const void    *LockOutputBuffer(unsigned& bytes);
  46.     void        UnlockOutputBuffer(unsigned bytes);
  47.     unsigned    CopyOutput(void *dst, unsigned bytes);
  48.  
  49. protected:
  50.     bool    mbEnded;
  51.     bool    mbPCM16Mode;
  52.  
  53.     VDRingBuffer<uint8>        mInputBuffer;
  54.     VDRingBuffer<uint8>        mOutputBuffer;
  55.     vdstructex<VDWaveFormat>    mSrcFormat;
  56.     vdstructex<VDWaveFormat>    mDstFormat;
  57.  
  58.     uint8 mLookup8[256];
  59.     sint16 mLookup16[256];
  60. };
  61.  
  62. IVDAudioCodec *VDCreateAudioDecompressorMuLaw(const VDWaveFormat *srcFormat, const VDWaveFormat *dstFormat) {
  63.     vdautoptr<VDAudioDecompressorXLaw> codec(new VDAudioDecompressorXLaw);
  64.  
  65.     if (!codec->Init(srcFormat, dstFormat, false))
  66.         return NULL;
  67.  
  68.     return codec.release();
  69. }
  70.  
  71. IVDAudioCodec *VDCreateAudioDecompressorALaw(const VDWaveFormat *srcFormat, const VDWaveFormat *dstFormat) {
  72.     vdautoptr<VDAudioDecompressorXLaw> codec(new VDAudioDecompressorXLaw);
  73.  
  74.     if (!codec->Init(srcFormat, dstFormat, true))
  75.         return NULL;
  76.  
  77.     return codec.release();
  78. }
  79.  
  80. VDAudioDecompressorXLaw::VDAudioDecompressorXLaw()
  81.     : mbEnded(false)
  82.     , mbPCM16Mode(false)
  83. {
  84. }
  85.  
  86. VDAudioDecompressorXLaw::~VDAudioDecompressorXLaw() {
  87. }
  88.  
  89. bool VDAudioDecompressorXLaw::Init(const VDWaveFormat *srcFormat, const VDWaveFormat *dstFormat, bool doALaw) {
  90.     if (srcFormat->mTag != (doALaw ? VDWaveFormat::kTagCCITTALaw : VDWaveFormat::kTagCCITTMuLaw))
  91.         return false;
  92.  
  93.     if (srcFormat->mBlockSize != srcFormat->mChannels)
  94.         return false;
  95.  
  96.     if (srcFormat->mDataRate != srcFormat->mChannels * srcFormat->mSamplingRate)
  97.         return false;
  98.  
  99.     if (srcFormat->mSampleBits != 8)
  100.         return false;
  101.  
  102.     if (dstFormat) {
  103.         if (dstFormat->mTag != VDWaveFormat::kTagPCM)
  104.             return false;
  105.  
  106.         if (dstFormat->mChannels != srcFormat->mChannels)
  107.             return false;
  108.  
  109.         if (dstFormat->mSamplingRate != srcFormat->mSamplingRate)
  110.             return false;
  111.  
  112.         if (dstFormat->mSampleBits == 8) {
  113.             if (dstFormat->mBlockSize != dstFormat->mChannels)
  114.                 return false;
  115.  
  116.             if (dstFormat->mDataRate != dstFormat->mChannels * dstFormat->mSamplingRate)
  117.                 return false;
  118.         } else if (dstFormat->mSampleBits == 16) {
  119.             if (dstFormat->mBlockSize != dstFormat->mChannels * 2)
  120.                 return false;
  121.  
  122.             if (dstFormat->mDataRate != dstFormat->mChannels * dstFormat->mSamplingRate * 2)
  123.                 return false;
  124.         } else {
  125.             return false;
  126.         }
  127.  
  128.         mDstFormat.assign(dstFormat, sizeof(VDWaveFormat) + dstFormat->mExtraSize);
  129.     } else {
  130.         mDstFormat.resize(sizeof(VDWaveFormat));
  131.         mDstFormat->mTag = VDWaveFormat::kTagPCM;
  132.         mDstFormat->mChannels = srcFormat->mChannels;
  133.         mDstFormat->mSamplingRate = srcFormat->mSamplingRate;
  134.         mDstFormat->mSampleBits = 16;
  135.         mDstFormat->mBlockSize = 2 * srcFormat->mChannels;
  136.         mDstFormat->mDataRate = mDstFormat->mBlockSize * mDstFormat->mSamplingRate;
  137.         mDstFormat->mExtraSize = 0;
  138.     }
  139.  
  140.     mSrcFormat.assign(srcFormat, sizeof(VDWaveFormat) + srcFormat->mExtraSize);
  141.  
  142.     mbPCM16Mode = (mDstFormat->mSampleBits >= 16);
  143.  
  144.     // Initialize positive conversion table (see ITU-T Rec. G.711 for details).
  145.     // This has been checked to be exact against the Microsoft codecs.
  146.     if (doALaw) {
  147.         // A-Law has a larger linear ramp than mu-law. It also inverts even bits
  148.         // (but note that the spec numbers bits starting at 1). Interestingly,
  149.         // A-Law can't represent 0.
  150.         for(int i=0; i<32; ++i) {
  151.             int j = i ^ 0x15;
  152.             mLookup16[0xc0 + i] =    1*8 + (j <<  4);
  153.         }
  154.  
  155.         for(int i=0; i<16; ++i) {
  156.             int j = i ^ 0x05;
  157.  
  158.             mLookup16[0xf0 + i] =   66*8 + (j <<  5);
  159.             mLookup16[0xe0 + i] =  132*8 + (j <<  6);
  160.             mLookup16[0x90 + i] =  264*8 + (j <<  7);
  161.             mLookup16[0x80 + i] =  528*8 + (j <<  8);
  162.             mLookup16[0xb0 + i] = 1056*8 + (j <<  9);
  163.             mLookup16[0xa0 + i] = 2112*8 + (j << 10);
  164.         }
  165.     } else {
  166.         for(int i=0; i<16; ++i) {
  167.             mLookup16[0xff - i] =    0*4 + (i <<  3);
  168.             mLookup16[0xef - i] =   33*4 + (i <<  4);
  169.             mLookup16[0xdf - i] =   99*4 + (i <<  5);
  170.             mLookup16[0xcf - i] =  231*4 + (i <<  6);
  171.             mLookup16[0xbf - i] =  495*4 + (i <<  7);
  172.             mLookup16[0xaf - i] = 1023*4 + (i <<  8);
  173.             mLookup16[0x9f - i] = 2079*4 + (i <<  9);
  174.             mLookup16[0x8f - i] = 4191*4 + (i << 10);
  175.         }
  176.  
  177.         // fixup zero
  178.         mLookup16[0xff] = 0;
  179.     }
  180.  
  181.     // initialize negative conversion table
  182.     for(int i=0; i<128; ++i)
  183.         mLookup16[i] = -mLookup16[i + 0x80];
  184.  
  185.     // initialize 8-bit table
  186.     for(int i=0; i<256; ++i) {
  187.         int y = (mLookup16[i] + 0x8080) >> 8;
  188.         mLookup8[i] = (uint8)(y > 255 ? 255 : y);
  189.     }
  190.  
  191.     mInputBuffer.Init(4096 * mSrcFormat->mBlockSize);
  192.     mOutputBuffer.Init(4096 * mDstFormat->mBlockSize);
  193.  
  194.     return true;
  195. }
  196.  
  197. void VDAudioDecompressorXLaw::Shutdown() {
  198.     mSrcFormat.clear();
  199.     mDstFormat.clear();
  200.     mInputBuffer.Shutdown();
  201.     mOutputBuffer.Shutdown();
  202. }
  203.  
  204. bool VDAudioDecompressorXLaw::IsEnded() const {
  205.     return mbEnded;
  206. }
  207.  
  208. unsigned VDAudioDecompressorXLaw::GetInputLevel() const {
  209.     return mInputBuffer.getLevel();
  210. }
  211.  
  212. unsigned VDAudioDecompressorXLaw::GetInputSpace() const {
  213.     return mInputBuffer.getSpace();
  214. }
  215.  
  216. unsigned VDAudioDecompressorXLaw::GetOutputLevel() const {
  217.     return mOutputBuffer.getLevel();
  218. }
  219.  
  220. const VDWaveFormat *VDAudioDecompressorXLaw::GetOutputFormat() const {
  221.     return mDstFormat.data();
  222. }
  223.  
  224. unsigned VDAudioDecompressorXLaw::GetOutputFormatSize() const {
  225.     return mDstFormat.size();
  226. }
  227.  
  228. void VDAudioDecompressorXLaw::Restart() {
  229.     mInputBuffer.Flush();
  230.     mOutputBuffer.Flush();
  231.     mbEnded = false;
  232. }
  233.  
  234. bool VDAudioDecompressorXLaw::Convert(bool flush, bool requireOutput) {
  235.     bool didSomething = false;
  236.  
  237.     for(;;) {
  238.         int writeSpace;
  239.         void *dst0 = mOutputBuffer.LockWriteAll(writeSpace);
  240.  
  241.         if (mbPCM16Mode)
  242.             writeSpace >>= 1;
  243.  
  244.         if (!writeSpace)
  245.             break;
  246.  
  247.         int count;
  248.         const uint8 *src = (const uint8 *)mInputBuffer.LockRead(writeSpace, count);
  249.  
  250.         if (!count)
  251.             break;
  252.  
  253.         didSomething = true;
  254.  
  255.         if (mbPCM16Mode) {
  256.             sint16 *dst16 = (sint16 *)dst0;
  257.             const sint16 *const VDRESTRICT lookup = mLookup16;
  258.  
  259.             for(int i=0; i<count; ++i)
  260.                 dst16[i] = lookup[src[i]];
  261.  
  262.             mOutputBuffer.UnlockWrite(count * 2);
  263.         } else {
  264.             uint8 *dst8 = (uint8 *)dst0;
  265.             const uint8 *const VDRESTRICT lookup = mLookup8;
  266.  
  267.             for(int i=0; i<count; ++i)
  268.                 dst8[i] = lookup[src[i]];
  269.  
  270.             mOutputBuffer.UnlockWrite(count);
  271.         }
  272.  
  273.         mInputBuffer.UnlockRead(count);
  274.     }
  275.  
  276.     if (!didSomething && flush)
  277.         mbEnded = true;
  278.  
  279.     return didSomething;
  280. }
  281.  
  282. void *VDAudioDecompressorXLaw::LockInputBuffer(unsigned& bytes) {
  283.     int actual;
  284.     uint8 *p = mInputBuffer.LockWriteAll(actual);
  285.     bytes = actual;
  286.     return p;
  287. }
  288.  
  289. void VDAudioDecompressorXLaw::UnlockInputBuffer(unsigned bytes) {
  290.     mInputBuffer.UnlockWrite(bytes);
  291. }
  292.  
  293. const void    *VDAudioDecompressorXLaw::LockOutputBuffer(unsigned& bytes) {
  294.     int actual;
  295.     const uint8 *p = mOutputBuffer.LockReadAll(actual);
  296.     bytes = actual;
  297.     return p;
  298. }
  299.  
  300. void VDAudioDecompressorXLaw::UnlockOutputBuffer(unsigned bytes) {
  301.     mOutputBuffer.UnlockRead(bytes);
  302. }
  303.  
  304. unsigned VDAudioDecompressorXLaw::CopyOutput(void *dst, unsigned bytes) {
  305.     if (!dst) {
  306.         int actual;
  307.         mOutputBuffer.LockRead(bytes, actual);
  308.         mOutputBuffer.UnlockRead(actual);
  309.         return actual;
  310.     }
  311.  
  312.     return mOutputBuffer.Read((uint8 *)dst, bytes);
  313. }
  314.