updownmix.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:15k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: updownmix.cpp,v 1.3.8.1 2004/07/09 02:08:08 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 "hxassert.h"
  50. #include "mixengine.h"
  51. #include "math64.h"
  52. #ifdef HELIX_FEATURE_LIMITER
  53. #include "limiter.h"
  54. #endif
  55. #define MINUS3DB .707106781186547524 /* sqrt(2)/2 */
  56. /*****************************************************************************
  57.  *
  58.  * The upmix and downmix machinery.
  59.  *
  60.  ****************************************************************************/
  61. typedef struct UpMixMachine {
  62.   int offsetIn, offsetOut ;
  63.   const struct UpMixMachine *nextState ;
  64. } tUpMixMachine ;
  65. static const tUpMixMachine up_id[1] =
  66. {
  67.     {
  68.         1,1,
  69.         &up_id[0]
  70.     }
  71. } ;
  72. static const tUpMixMachine up_1_2[2] =
  73. {
  74.     {
  75.         0,1,
  76.         &up_1_2[1]
  77.     },
  78.     {
  79.         1,1,
  80.         &up_1_2[0]
  81.     }
  82. } ;
  83. /* mix mono into L,R instead of C */
  84. static const tUpMixMachine up_1_5[2] =
  85. {
  86.     {
  87.         0,1,
  88.         &up_1_5[1]
  89.     },
  90.     {
  91.         1,4,
  92.         &up_1_5[0]
  93.     }
  94. } ;
  95. /* mix mono into L,R instead of C */
  96. static const tUpMixMachine up_1_6[2] =
  97. {
  98.     {
  99.         0,1,
  100.         &up_1_6[1]
  101.     },
  102.     {
  103.         1,5,
  104.         &up_1_6[0]
  105.     }
  106. } ;
  107. static const tUpMixMachine up_2_5[2] =
  108. {
  109.     {
  110.         1,1,
  111.         &up_2_5[1]
  112.     },
  113.     {
  114.         1,4,
  115.         &up_2_5[0]
  116.     }
  117. } ;
  118. static const tUpMixMachine up_4_6[5] =
  119. {
  120.     {
  121.         1,1,
  122.         &up_4_6[1]
  123.     },
  124.     {
  125.         1,1,
  126.         &up_4_6[2]
  127.     },
  128.     {
  129.         1,2,
  130.         &up_4_6[3]
  131.     },
  132.     {
  133.         0,1,
  134.         &up_4_6[4]
  135.     },
  136.     {
  137.         1,1,
  138.         &up_4_6[0]
  139.     }
  140. } ;
  141. static const tUpMixMachine up_5_6[5] =
  142. {
  143.     {
  144.         1,1,
  145.         &up_5_6[1]
  146.     },
  147.     {
  148.         1,1,
  149.         &up_5_6[2]
  150.     },
  151.     {
  152.         1,2,
  153.         &up_5_6[3]
  154.     },
  155.     {
  156.         1,1,
  157.         &up_5_6[4]
  158.     },
  159.     {
  160.         1,1,
  161.         &up_5_6[0]
  162.     }
  163. } ;
  164. HX_RESULT HXAudioSvcMixEngine::SetupUpDownmix(void)
  165. {
  166.     // we'll need something more intelligent for multichannel
  167.     m_nChannels_2_3 = MIN(m_nChannels_1, m_nChannels_4) ;
  168.     // initialize downmix
  169.     if (m_nChannels_1 != m_nChannels_2_3)
  170.     {
  171.       if (m_nChannels_1 == 2 && m_nChannels_2_3 == 1)
  172.           m_pfDownmix = &HXAudioSvcMixEngine::downmix2_1 ;
  173.       else if (m_nChannels_1 == 5 && m_nChannels_2_3 == 1)
  174.           m_pfDownmix = &HXAudioSvcMixEngine::downmix5_1 ;
  175.       else if (m_nChannels_1 == 6 && m_nChannels_2_3 == 2)
  176.           m_pfDownmix = &HXAudioSvcMixEngine::downmix6_2_matrix ;
  177.       else if (m_nChannels_1 == 5 && m_nChannels_2_3 == 2)
  178.           m_pfDownmix = &HXAudioSvcMixEngine::downmix5_2_matrix ;
  179.       else if (m_nChannels_1 == 4 && m_nChannels_2_3 == 2)
  180.           m_pfDownmix = &HXAudioSvcMixEngine::downmix4_2_matrix ;
  181.       else
  182.           return HXR_FAIL ;
  183.       /* If we downmix, we limit. Special-case stereo to mono: create one bit of
  184.          headroom, don't limit */
  185. #if HELIX_FEATURE_LIMITER
  186.       if (!(m_nChannels_1 == 2 && m_nChannels_2_3 == 1))
  187.           m_pLimiter = LimiterInit(m_ulSampleRate_3_4, m_nChannels_2_3, HEADROOM) ;
  188.       else
  189. #endif
  190.           m_pLimiter = 0 ;
  191.     }
  192.     // initialize upmix
  193.     if (m_nChannels_2_3 == m_nChannels_4)
  194.         m_upmixMachine = up_id ;
  195.     else if (m_nChannels_2_3 == 1 && m_nChannels_4 == 2)
  196.         m_upmixMachine = up_1_2 ;
  197.     else if (m_nChannels_2_3 == 1 && m_nChannels_4 == 5)
  198.         m_upmixMachine = up_1_5 ;
  199.     else if (m_nChannels_2_3 == 1 && m_nChannels_4 == 6)
  200.         m_upmixMachine = up_1_6 ;
  201.     else if (m_nChannels_2_3 == 2 && m_nChannels_4 == 5)
  202.         m_upmixMachine = up_2_5 ;
  203.     else if (m_nChannels_2_3 == 5 && m_nChannels_4 == 6)
  204.         m_upmixMachine = up_5_6 ;
  205.     else if (m_nChannels_2_3 == 4 && m_nChannels_4 == 6)
  206.         m_upmixMachine = up_4_6 ;
  207.     else
  208.         return HXR_FAIL ;
  209.     m_clev = m_slev = (int)((1UL<<31) * MINUS3DB) ; // -3 dB is default attenuation
  210.     return HXR_OK ;
  211. }
  212. /* saturated 16-bit add */
  213. INT16 adds16(INT16 a, INT16 b)
  214. {
  215.     INT32 s = (INT32)a+b ;
  216.     if (s > 0x7fff) s = 0x7fff ;
  217.     else if (s < -0x8000) s = -0x8000 ;
  218.     return (INT16)s ;
  219. }
  220. /* saturated 32-bit add */
  221. INT32 adds32(INT32 a, INT32 b)
  222. {
  223.     INT32 s = a+b ;
  224.     INT32 ov = ~(a ^ b) & (a ^ s) & 0x80000000 ; // overflow
  225.     if (ov)
  226.         s = (signed)((1UL<<31)-1)-((s ^ ov) >> 31) ;
  227.     return s ;
  228. }
  229. /* mix into a 32-bit buffer. Returns the number of samples written (more precisely,
  230.    if we mix 2 channels into a 5 channel buffer, and feed 2*n samples, then this
  231.    function will return 5*n samples, regardless into how many channels the 2 original
  232.    channels are mixed. */
  233. UINT32 HXAudioSvcMixEngine::upmix(const tAudioSample *pIn, INT32 *pOut0, const tUpMixMachine *pUpmixMachine, int nSamples, BOOL isDirty)
  234. {
  235.     INT32 *pOut = pOut0 ;
  236.     HX_ASSERT(nSamples % m_nChannels_2_3 == 0) ;
  237.     const tAudioSample *pEnd = pIn + nSamples ;
  238.     if (!isDirty)
  239.     {
  240.         while (pIn != pEnd)
  241.         {
  242.             *pOut = adds32(*pIn << (32-NBITS_PER_AUDIOSAMPLE), *pOut);
  243.             pIn  += pUpmixMachine->offsetIn  ;
  244.             pOut += pUpmixMachine->offsetOut ;
  245.             pUpmixMachine = pUpmixMachine->nextState ;
  246.         }
  247.     }
  248.     else
  249.     {
  250.         while (pIn != pEnd)
  251.         {
  252.             INT32 t = (INT32)*pIn << (32-NBITS_PER_AUDIOSAMPLE) ; // -MulShift31(*pIn,pUpmixMachine->gain)
  253.             *pOut = t ;
  254.             pIn  += pUpmixMachine->offsetIn  ;
  255.             pOut += pUpmixMachine->offsetOut ;
  256.             pUpmixMachine = pUpmixMachine->nextState ;
  257.         }
  258.     }
  259.     return pOut - pOut0 ;
  260. }
  261. /* mix into a 16-bit buffer. Returns the number of samples written (more precisely,
  262.    if we mix 2 channels into a 5 channel buffer, and feed 2*n samples, then this
  263.    function will return 5*n samples, regardless into how many channels the 2 original
  264.    channels are mixed. */
  265. UINT32 HXAudioSvcMixEngine::upmix(const tAudioSample *pIn, INT16 *pOut0, const tUpMixMachine *pUpmixMachine, int nSamples, BOOL isDirty)
  266. {
  267.     INT16 *pOut = pOut0 ;
  268.     HX_ASSERT(nSamples % m_nChannels_2_3 == 0) ;
  269.     const tAudioSample *pEnd = pIn + nSamples ;
  270.     if (!isDirty)
  271.     {
  272.         while (pIn != pEnd)
  273.         {
  274.             *pOut = adds16((INT16)(*pIn >> (NBITS_PER_AUDIOSAMPLE-16)), *pOut);
  275.             pIn  += pUpmixMachine->offsetIn  ;
  276.             pOut += pUpmixMachine->offsetOut ;
  277.             pUpmixMachine = pUpmixMachine->nextState ;
  278.         }
  279.     }
  280.     else
  281.     {
  282.         while (pIn != pEnd)
  283.         {
  284.             *pOut = (INT16)(*pIn >> (NBITS_PER_AUDIOSAMPLE-16)) ;
  285.             pIn  += pUpmixMachine->offsetIn  ;
  286.             pOut += pUpmixMachine->offsetOut ;
  287.             pUpmixMachine = pUpmixMachine->nextState ;
  288.         }
  289.     }
  290.     return pOut - pOut0 ;
  291. }
  292. void HXAudioSvcMixEngine::downmix2_1(tAudioSample *pBuffer, int nSamples)
  293. {
  294.     enum { L,R,strideIn } ; // input channel ordering
  295.     HX_ASSERT(nSamples % strideIn == 0) ;
  296.     const tAudioSample *pEnd = pBuffer + nSamples ;
  297.     tAudioSample *pOut = pBuffer;
  298.     while (pBuffer != pEnd)
  299.     {
  300.         *pOut++ = (pBuffer[L]>>1) + (pBuffer[R]>>1) ;
  301.         pBuffer += strideIn ;
  302.     }
  303. }
  304. void HXAudioSvcMixEngine::downmix5_1(tAudioSample *pBuffer, int nSamples)
  305. {
  306.     enum { L,R,C,Ls,Rs,strideIn } ; // input channel ordering
  307.     HX_ASSERT(nSamples % strideIn == 0) ;
  308.     const tAudioSample *pEnd = pBuffer + nSamples ;
  309.     tAudioSample *pOut = pBuffer;
  310.     const int clev = m_clev >> (HEADROOM-1);
  311.     const int slev = m_slev >> (HEADROOM-2);
  312.     while (pBuffer != pEnd)
  313.     {
  314.         INT32 c  = MulShift32(pBuffer[C], clev) ;
  315.         INT32 cs = MulShift32((pBuffer[Ls]>>1) + (pBuffer[Rs]>>1), slev) ;
  316.         *pOut++  = (pBuffer[L]>>HEADROOM) + c + (pBuffer[R]>>HEADROOM) + cs ;
  317.         pBuffer += strideIn ;
  318.     }
  319. }
  320. // Matrix surround downmix
  321. void HXAudioSvcMixEngine::downmix5_2_matrix(tAudioSample *pBuffer, int nSamples)
  322. {
  323.     enum { L,R,C,Ls,Rs,strideIn } ; // input channel ordering
  324.     HX_ASSERT(nSamples % strideIn == 0) ;
  325.     const tAudioSample *pEnd = pBuffer + nSamples ;
  326.     tAudioSample *pOut = pBuffer;
  327.     const int clev = m_clev >> (HEADROOM-1);
  328.     const int slev = m_slev >> (HEADROOM-2);
  329.     while (pBuffer != pEnd)
  330.     {
  331.         INT32 c  = MulShift32(pBuffer[C], clev) ; // creates two bits headroom
  332.         INT32 cs = MulShift32((pBuffer[Ls]>>1) + (pBuffer[Rs]>>1), slev) ; // two bits hr
  333.         pOut[0]  = (pBuffer[L]>>HEADROOM) + c + cs ;
  334.         pOut[1]  = (pBuffer[R]>>HEADROOM) + c - cs ;
  335.         pBuffer += strideIn ;
  336.         pOut    += 2 ;
  337.     }
  338. }
  339. // Stereo downmix
  340. void HXAudioSvcMixEngine::downmix5_2_stereo(tAudioSample *pBuffer, int nSamples)
  341. {
  342.     enum { L,R,C,Ls,Rs,strideIn } ; // input channel ordering
  343.     HX_ASSERT(nSamples % strideIn == 0) ;
  344.     const tAudioSample *pEnd = pBuffer + nSamples ;
  345.     tAudioSample *pOut = pBuffer;
  346.     const int clev = m_clev >> (HEADROOM-1);
  347.     const int slev = m_slev >> (HEADROOM-1);
  348.     while (pBuffer != pEnd)
  349.     {
  350.         INT32 c = MulShift32(pBuffer[C], clev) ;
  351.         pOut[0] = (pBuffer[L]>>HEADROOM) + c + MulShift32(pBuffer[Ls], slev) ;
  352.         pOut[1] = (pBuffer[R]>>HEADROOM) + c + MulShift32(pBuffer[Rs], slev) ;
  353.         pBuffer += strideIn ;
  354.         pOut    += 2 ;
  355.     }
  356. }
  357. // Matrix surround downmix
  358. void HXAudioSvcMixEngine::downmix6_2_matrix(tAudioSample *pBuffer, int nSamples)
  359. {
  360.     enum { L,R,C,LFE,Ls,Rs,strideIn } ; // input channel ordering
  361.     HX_ASSERT(nSamples % strideIn == 0) ;
  362.     const tAudioSample *pEnd = pBuffer + nSamples ;
  363.     tAudioSample *pOut = pBuffer;
  364.     const int clev = m_clev >> (HEADROOM-1);
  365.     const int slev = m_slev >> (HEADROOM-2);
  366.     while (pBuffer != pEnd)
  367.     {
  368.         INT32 c  = MulShift32(pBuffer[C], clev) ; // creates two bits headroom
  369.         INT32 cs = MulShift32((pBuffer[Ls]>>1) + (pBuffer[Rs]>>1), slev) ; // two bits hr
  370.         pOut[0]  = (pBuffer[L]>>HEADROOM) + c + cs ;
  371.         pOut[1]  = (pBuffer[R]>>HEADROOM) + c - cs ;
  372.         pBuffer += strideIn ;
  373.         pOut    += 2 ;
  374.     }
  375. }
  376. // Stereo downmix
  377. void HXAudioSvcMixEngine::downmix6_2_stereo(tAudioSample *pBuffer, int nSamples)
  378. {
  379.     enum { L,R,C,LFE,Ls,Rs,strideIn } ; // input channel ordering
  380.     HX_ASSERT(nSamples % strideIn == 0) ;
  381.     const tAudioSample *pEnd = pBuffer + nSamples ;
  382.     tAudioSample *pOut = pBuffer;
  383.     const int clev = m_clev >> (HEADROOM-1);
  384.     const int slev = m_slev >> (HEADROOM-1);
  385.     while (pBuffer != pEnd)
  386.     {
  387.         INT32 c = MulShift32(pBuffer[C], clev) ;
  388.         pOut[0] = (pBuffer[L]>>HEADROOM) + c + MulShift32(pBuffer[Ls], slev) ;
  389.         pOut[1] = (pBuffer[R]>>HEADROOM) + c + MulShift32(pBuffer[Rs], slev) ;
  390.         pBuffer += strideIn ;
  391.         pOut    += 2 ;
  392.     }
  393. }
  394. // Matrix surround downmix
  395. void HXAudioSvcMixEngine::downmix4_2_matrix(tAudioSample *pBuffer, int nSamples)
  396. {
  397.     enum { L,R,C,Cs,strideIn } ; // input channel ordering
  398.     HX_ASSERT(nSamples % strideIn == 0) ;
  399.     const tAudioSample *pEnd = pBuffer + nSamples ;
  400.     tAudioSample *pOut = pBuffer;
  401.     const int clev = m_clev >> (HEADROOM-1);
  402.     const int slev = m_slev >> (HEADROOM-1);
  403.     while (pBuffer != pEnd)
  404.     {
  405.         INT32 c  = MulShift32(pBuffer[C], clev) ; // creates two bits headroom
  406.         INT32 cs = MulShift32(pBuffer[Cs], slev) ; // two bits hr
  407.         pOut[0]  = (pBuffer[L]>>HEADROOM) + c + cs ;
  408.         pOut[1]  = (pBuffer[R]>>HEADROOM) + c - cs ;
  409.         pBuffer += strideIn ;
  410.         pOut    += 2 ;
  411.     }
  412. }
  413. // Stereo downmix
  414. void HXAudioSvcMixEngine::downmix4_2_stereo(tAudioSample *pBuffer, int nSamples)
  415. {
  416.     enum { L,R,C,Cs,strideIn } ; // input channel ordering
  417.     HX_ASSERT(nSamples % strideIn == 0) ;
  418.     const tAudioSample *pEnd = pBuffer + nSamples ;
  419.     tAudioSample *pOut = pBuffer;
  420.     const int clev = m_clev >> (HEADROOM-1);
  421.     const int slev = m_slev >> (HEADROOM-1);
  422.     while (pBuffer != pEnd)
  423.     {
  424.         INT32 c = MulShift32(pBuffer[C], clev) ;
  425.         INT32 cs = MulShift32(pBuffer[Cs], slev) ; // two bits hr
  426.         pOut[0] = (pBuffer[L]>>HEADROOM) + c + cs ;
  427.         pOut[1] = (pBuffer[R]>>HEADROOM) + c + cs ;
  428.         pBuffer += strideIn ;
  429.         pOut    += 2 ;
  430.     }
  431. }