hxrsmp2.cpp
Upload User: dangjiwu
Upload Date: 2013-07-19
Package Size: 42019k
Code Size: 11k
Category:

Symbian

Development Platform:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxrsmp2.cpp,v 1.8.20.1 2004/07/09 02:01:17 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxcom.h"
  50. #include "hxtypes.h"
  51. #include "hxresult.h"
  52. #ifdef _WINDOWS
  53. #include <windows.h>
  54. #endif
  55. #include "hlxclib/string.h"
  56. #include "timeval.h"
  57. #include "ihxpckts.h"
  58. #include "hxfiles.h"
  59. #include "hxengin.h"
  60. #include "hxcore.h"
  61. #include "hxprefs.h"
  62. #include "hxtick.h"
  63. #ifdef _MACINTOSH
  64. #include "hxmm.h"
  65. #endif
  66. #include "hxthread.h"
  67. //#include "resampl2.h"
  68. #include "hxausvc.h"
  69. #include "hxrsmp2.h"
  70. #include "hxheap.h"
  71. #ifdef _DEBUG
  72. #undef HX_THIS_FILE
  73. static const char HX_THIS_FILE[] = __FILE__;
  74. #endif
  75. // HXScheduler...
  76. HXCDQualityResampler::HXCDQualityResampler() 
  77.     :   m_lRefCount (0)
  78.     , m_pResampler(NULL)
  79.     , m_audioChannelConversion(AUDIO_CHANNEL_NONE)
  80.     , m_audioSampleConversion(AUDIO_SAMPLE_NONE)
  81.     , m_ulSamplesSaved(0)
  82.     , m_ulSamplesFixed(0)
  83.     , m_ulBytesFixed(0)
  84.     ,   m_pBPS8To16Out(NULL)
  85. {
  86. }
  87. HXCDQualityResampler::~HXCDQualityResampler()
  88. {
  89.     Close();
  90. }
  91. /*
  92.  * IUnknown methods
  93.  */
  94. /////////////////////////////////////////////////////////////////////////
  95. // Method:
  96. // IUnknown::QueryInterface
  97. // Purpose:
  98. // Implement this to export the interfaces supported by your 
  99. // object.
  100. //
  101. STDMETHODIMP HXCDQualityResampler::QueryInterface(REFIID riid, void** ppvObj)
  102. {
  103.     QInterfaceList qiList[] =
  104.         {
  105.             { GET_IIDHANDLE(IID_IHXAudioResampler), (IHXAudioResampler*)this },
  106.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXAudioResampler*)this },
  107.         };
  108.     
  109.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  110. }
  111. /////////////////////////////////////////////////////////////////////////
  112. // Method:
  113. // IUnknown::AddRef
  114. // Purpose:
  115. // Everyone usually implements this the same... feel free to use
  116. // this implementation.
  117. //
  118. STDMETHODIMP_(ULONG32) HXCDQualityResampler::AddRef()
  119. {
  120.     return InterlockedIncrement(&m_lRefCount);
  121. }
  122. /////////////////////////////////////////////////////////////////////////
  123. // Method:
  124. // IUnknown::Release
  125. // Purpose:
  126. // Everyone usually implements this the same... feel free to use
  127. // this implementation.
  128. //
  129. STDMETHODIMP_(ULONG32) HXCDQualityResampler::Release()
  130. {
  131.     if (InterlockedDecrement(&m_lRefCount) > 0)
  132.     {
  133. return m_lRefCount;
  134.     }
  135.     delete this;
  136.     return 0;
  137. }
  138. /*
  139.  * IHXResampler methods
  140.  */
  141. STDMETHODIMP_(UINT32) 
  142. HXCDQualityResampler::Resample(UINT16* pInput, 
  143. UINT32 ulInputBytes, 
  144.                                 UINT16* pOutput) 
  145. {
  146.     UINT32  ulOutputBytes = 0;
  147.     UINT32  ulSamplesIn = 0;
  148.     UINT32  ulFramesIn = 0;
  149.     UINT32  ulSamplesOut = 0;
  150.     UINT32  ulBytesSaved = 0;   
  151.     UINT32  ulOut = 0;
  152.     ulSamplesIn = (ulInputBytes * 8) / m_inAudioFormat.uBitsPerSample;
  153.     
  154.     ulSamplesOut = ulSamplesIn;
  155.     ulOutputBytes = ulInputBytes;
  156.     // channel conversion first(STEREO -> MONO)
  157.     // MONO -> STEREO is handled by the caller(AudioStream)
  158.     if (AUDIO_CHANNEL_DOWN == m_audioChannelConversion)
  159.     {
  160. Downmix16((short*)pInput, ulSamplesIn);
  161. // half the output samples after channel conversion
  162. ulSamplesIn /= 2;
  163. ulSamplesOut = ulSamplesIn;
  164.     }
  165.     // resampler's output always be 16bits
  166.     if (m_inAudioFormat.uBitsPerSample == 8 && m_outAudioFormat.uBitsPerSample == 16)
  167.     {
  168. ulFramesIn = ulSamplesIn / m_inAudioFormat.uChannels;
  169. ulOut = m_inAudioFormat.uChannels * 2 * ulFramesIn;
  170. if (!m_pBPS8To16Out)
  171. {
  172.     m_pBPS8To16Out = (short*)new char[ulOut];
  173. }
  174. BPS8To16((short*)pInput, ulInputBytes, (short*)m_pBPS8To16Out, ulOut);
  175. pInput = (UINT16*)m_pBPS8To16Out;
  176.     }
  177.     if (m_pResampler)
  178.     {
  179. if (m_ulSamplesSaved)
  180. {
  181.     ulBytesSaved = m_ulSamplesSaved * m_outAudioFormat.uBitsPerSample / 8;
  182.     HX_ASSERT(ulBytesSaved < m_ulBytesFixed);
  183.             if (ulBytesSaved >= m_ulBytesFixed) ulBytesSaved = m_ulBytesFixed;
  184.     ::memcpy(pOutput, (UCHAR*)pOutput+m_ulBytesFixed, ulBytesSaved); /* Flawfinder: ignore */
  185. }
  186. ulSamplesOut = m_pResampler->Resample((short*)pInput,
  187.      ulSamplesIn,
  188.      (short*)((UCHAR*)pOutput + ulBytesSaved));
  189. m_ulSamplesSaved += ulSamplesOut - m_ulSamplesFixed;
  190. ulOutputBytes = m_ulBytesFixed;
  191.     }
  192.     else
  193.     {
  194. ulOutputBytes = (ulSamplesOut * m_outAudioFormat.uBitsPerSample) / 8;
  195.         HX_ASSERT(ulOutputBytes < m_ulBytesFixed);
  196.         if (ulOutputBytes >= m_ulBytesFixed) ulOutputBytes = m_ulBytesFixed;
  197. ::memcpy(pOutput, pInput, ulOutputBytes); /* Flawfinder: ignore */
  198.     }
  199.     return ulOutputBytes;
  200. }
  201. STDMETHODIMP_(UINT32) 
  202. HXCDQualityResampler::Requires(UINT32 outputFrames)
  203. {
  204.     UINT32 inputFrames = 0;
  205.     UINT32 ulSamplesRequired = 0;
  206.     // we only need to resample half of the output frames
  207.     // since the caller will do the MONO -> STEREO channel conversion
  208.     if (AUDIO_CHANNEL_UP == m_audioChannelConversion)
  209.     {
  210. outputFrames /= 2;
  211.     }
  212.     // take into account of the extra samples from the last Resample()
  213.     ulSamplesRequired = outputFrames * m_outAudioFormat.uChannels - m_ulSamplesSaved;
  214.     m_ulSamplesFixed = outputFrames * m_outAudioFormat.uChannels;
  215.     m_ulBytesFixed = (outputFrames * m_outAudioFormat.uChannels * m_outAudioFormat.uBitsPerSample) / 8;;
  216.     if (m_pResampler)
  217.     {
  218. inputFrames = m_pResampler->GetMinInput(ulSamplesRequired) / m_inAudioFormat.uChannels;
  219.     }
  220.     else
  221.     {
  222. inputFrames = ulSamplesRequired / m_inAudioFormat.uChannels;
  223.     }
  224.     // we need to double the input frames for STEREO -> MONO channel
  225.     // conversion
  226.     if (AUDIO_CHANNEL_DOWN == m_audioChannelConversion)
  227.     {
  228. inputFrames *= 2;
  229.     }
  230.     return inputFrames;
  231. }
  232. HX_RESULT
  233. HXCDQualityResampler::Init(HXAudioFormat inAudioFormat,
  234.     REF(HXAudioFormat) outAudioFormat)
  235. {
  236.     HX_RESULT rc = HXR_OK;
  237.     CopyAudioFormat(inAudioFormat, m_inAudioFormat);
  238.     CopyAudioFormat(outAudioFormat, m_outAudioFormat);
  239.     INT32   actualMaxSamplesIn = (m_inAudioFormat.uMaxBlockSize * 8) / m_inAudioFormat.uBitsPerSample;
  240.     INT32   actualMaxSamplesOut = 0;
  241.     INT32   actualMaxInputBytes = m_inAudioFormat.uMaxBlockSize;
  242.     INT32   actualResamplerChannel = m_inAudioFormat.uChannels;
  243.     // cleanup the mess
  244.     Close();
  245.     // this wrapper class will do the STEREO -> MONO channel conversion
  246.     // MONO -> STEREO channel conversion will be done by the caller
  247.     if (m_outAudioFormat.uChannels > m_inAudioFormat.uChannels)
  248.     {
  249. m_audioChannelConversion = AUDIO_CHANNEL_UP;
  250.     }
  251.     else if (m_outAudioFormat.uChannels < m_inAudioFormat.uChannels)
  252.     {
  253. m_audioChannelConversion = AUDIO_CHANNEL_DOWN;
  254. actualMaxInputBytes /= 2;
  255. actualResamplerChannel = m_outAudioFormat.uChannels;
  256.     }
  257.     else
  258.     {
  259. m_audioChannelConversion = AUDIO_CHANNEL_NONE;
  260.     }
  261.     if (m_outAudioFormat.ulSamplesPerSec == m_inAudioFormat.ulSamplesPerSec)
  262.     {
  263. m_audioSampleConversion = AUDIO_SAMPLE_NONE;
  264.     }
  265.     else
  266.     {
  267. m_audioSampleConversion = AUDIO_SAMPLE_NEEDED;
  268.     }
  269.     if (AUDIO_SAMPLE_NONE != m_audioSampleConversion)
  270.     {
  271. if (HXR_OK == RAExactResampler::Create(&m_pResampler,
  272.        m_inAudioFormat.ulSamplesPerSec,
  273.        m_outAudioFormat.ulSamplesPerSec,
  274.        actualResamplerChannel,
  275.            RAExactResampler::_INT16)) // 16bit per sample output
  276. {
  277.     actualMaxSamplesOut = m_pResampler->GetMaxOutput(actualMaxSamplesIn);
  278. }
  279. else
  280. {
  281.     HX_DELETE(m_pResampler);
  282.     rc = HXR_FAILED;
  283. }
  284.     }
  285.     else
  286.     {
  287. actualMaxSamplesOut = actualMaxSamplesIn;
  288.     }
  289.     outAudioFormat.uMaxBlockSize = m_outAudioFormat.uMaxBlockSize = (actualMaxSamplesOut * m_outAudioFormat.uBitsPerSample) / 8;
  290.     
  291.     return rc;
  292. }
  293. void
  294. HXCDQualityResampler::Downmix16(INT16* pIn, UINT32 nSamplesIn)
  295. {
  296.     UINT32 i ;
  297.     for (i = 0 ; i < nSamplesIn / 2 ; i++)
  298.     {
  299. INT32 t = (INT32)pIn[2*i] + (INT32)pIn[2*i+1] ;
  300. pIn[i] = (INT16)(t>>1);
  301.     }
  302. }
  303. void
  304. HXCDQualityResampler::BPS8To16(INT16* pInput, UINT32 ulBytesIn, INT16* pOutput, UINT32& ulBytesOut)
  305. {
  306.     long inputFrames = ulBytesIn / (m_inAudioFormat.uBitsPerSample/8) / m_inAudioFormat.uChannels;
  307.     long n = 0;
  308.     if (1 == m_outAudioFormat.uChannels) 
  309.     {
  310. unsigned char* pIn = (unsigned char*) pInput;
  311. for (n = 0; n < inputFrames; n++) 
  312. {
  313.     pOutput[n] = (short) (((short)*pIn++ - 128) << 8);
  314. }
  315.     }
  316.     else if (2 == m_outAudioFormat.uChannels) 
  317.     { 
  318.         unsigned char* pIn = (unsigned char*) pInput;
  319. long m = 0;
  320. for (n = 0; n < inputFrames; n++ ) 
  321. {
  322.     pOutput[m] = (short) (((short)*pIn++ - 128) << 8);
  323.     m++;
  324.     pOutput[m] = (short) (((short)*pIn++ - 128) << 8);
  325.     m++;
  326. }
  327.     } 
  328.     ulBytesOut = m_inAudioFormat.uChannels * 2 * inputFrames;
  329.     return;
  330. }
  331. void
  332. HXCDQualityResampler::CopyAudioFormat(HXAudioFormat from, REF(HXAudioFormat) to)
  333. {
  334.     to.uChannels = from.uChannels;
  335.     to.uBitsPerSample = from.uBitsPerSample;
  336.     to.ulSamplesPerSec = from.ulSamplesPerSec;
  337.     to.uMaxBlockSize = from.uMaxBlockSize;
  338. }
  339. void
  340. HXCDQualityResampler::Close()
  341. {
  342.     HX_VECTOR_DELETE(m_pBPS8To16Out);
  343.     HX_DELETE(m_pResampler);
  344. }