updownmix.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:14k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxassert.h"
  36. #include "mixengine.h"
  37. #include "math64.h"
  38. #ifdef HELIX_FEATURE_LIMITER
  39. #include "limiter.h"
  40. #endif
  41. #define MINUS3DB .707106781186547524 /* sqrt(2)/2 */
  42. /*****************************************************************************
  43.  *
  44.  * The upmix and downmix machinery.
  45.  *
  46.  ****************************************************************************/
  47. typedef struct UpMixMachine {
  48.   int offsetIn, offsetOut ;
  49.   const struct UpMixMachine *nextState ;
  50. } tUpMixMachine ;
  51. static const tUpMixMachine up_id[1] =
  52. {
  53.     {
  54.         1,1,
  55.         &up_id[0]
  56.     }
  57. } ;
  58. static const tUpMixMachine up_1_2[2] =
  59. {
  60.     {
  61.         0,1,
  62.         &up_1_2[1]
  63.     },
  64.     {
  65.         1,1,
  66.         &up_1_2[0]
  67.     }
  68. } ;
  69. /* mix mono into L,R instead of C */
  70. static const tUpMixMachine up_1_5[2] =
  71. {
  72.     {
  73.         0,1,
  74.         &up_1_5[1]
  75.     },
  76.     {
  77.         1,4,
  78.         &up_1_5[0]
  79.     }
  80. } ;
  81. /* mix mono into L,R instead of C */
  82. static const tUpMixMachine up_1_6[2] =
  83. {
  84.     {
  85.         0,1,
  86.         &up_1_6[1]
  87.     },
  88.     {
  89.         1,5,
  90.         &up_1_6[0]
  91.     }
  92. } ;
  93. static const tUpMixMachine up_2_5[2] =
  94. {
  95.     {
  96.         1,1,
  97.         &up_2_5[1]
  98.     },
  99.     {
  100.         1,4,
  101.         &up_2_5[0]
  102.     }
  103. } ;
  104. static const tUpMixMachine up_4_6[5] =
  105. {
  106.     {
  107.         1,1,
  108.         &up_4_6[1]
  109.     },
  110.     {
  111.         1,1,
  112.         &up_4_6[2]
  113.     },
  114.     {
  115.         1,2,
  116.         &up_4_6[3]
  117.     },
  118.     {
  119.         0,1,
  120.         &up_4_6[4]
  121.     },
  122.     {
  123.         1,1,
  124.         &up_4_6[0]
  125.     }
  126. } ;
  127. static const tUpMixMachine up_5_6[5] =
  128. {
  129.     {
  130.         1,1,
  131.         &up_5_6[1]
  132.     },
  133.     {
  134.         1,1,
  135.         &up_5_6[2]
  136.     },
  137.     {
  138.         1,2,
  139.         &up_5_6[3]
  140.     },
  141.     {
  142.         1,1,
  143.         &up_5_6[4]
  144.     },
  145.     {
  146.         1,1,
  147.         &up_5_6[0]
  148.     }
  149. } ;
  150. HX_RESULT HXAudioSvcMixEngine::SetupUpDownmix(void)
  151. {
  152.     // we'll need something more intelligent for multichannel
  153.     m_nChannels_2_3 = MIN(m_nChannels_1, m_nChannels_4) ;
  154.     // initialize downmix
  155.     if (m_nChannels_1 != m_nChannels_2_3)
  156.     {
  157.       if (m_nChannels_1 == 2 && m_nChannels_2_3 == 1)
  158.           m_pfDownmix = &HXAudioSvcMixEngine::downmix2_1 ;
  159.       else if (m_nChannels_1 == 5 && m_nChannels_2_3 == 1)
  160.           m_pfDownmix = &HXAudioSvcMixEngine::downmix5_1 ;
  161.       else if (m_nChannels_1 == 6 && m_nChannels_2_3 == 2)
  162.           m_pfDownmix = &HXAudioSvcMixEngine::downmix6_2_matrix ;
  163.       else if (m_nChannels_1 == 5 && m_nChannels_2_3 == 2)
  164.           m_pfDownmix = &HXAudioSvcMixEngine::downmix5_2_matrix ;
  165.       else if (m_nChannels_1 == 4 && m_nChannels_2_3 == 2)
  166.           m_pfDownmix = &HXAudioSvcMixEngine::downmix4_2_matrix ;
  167.       else
  168.           return HXR_FAIL ;
  169.       /* If we downmix, we limit. Special-case stereo to mono: create one bit of
  170.          headroom, don't limit */
  171. #if HELIX_FEATURE_LIMITER
  172.       if (!(m_nChannels_1 == 2 && m_nChannels_2_3 == 1))
  173.           m_pLimiter = LimiterInit(m_ulSampleRate_3_4, m_nChannels_2_3, HEADROOM) ;
  174.       else
  175. #endif
  176.           m_pLimiter = 0 ;
  177.     }
  178.     // initialize upmix
  179.     if (m_nChannels_2_3 == m_nChannels_4)
  180.         m_upmixMachine = up_id ;
  181.     else if (m_nChannels_2_3 == 1 && m_nChannels_4 == 2)
  182.         m_upmixMachine = up_1_2 ;
  183.     else if (m_nChannels_2_3 == 1 && m_nChannels_4 == 5)
  184.         m_upmixMachine = up_1_5 ;
  185.     else if (m_nChannels_2_3 == 1 && m_nChannels_4 == 6)
  186.         m_upmixMachine = up_1_6 ;
  187.     else if (m_nChannels_2_3 == 2 && m_nChannels_4 == 5)
  188.         m_upmixMachine = up_2_5 ;
  189.     else if (m_nChannels_2_3 == 5 && m_nChannels_4 == 6)
  190.         m_upmixMachine = up_5_6 ;
  191.     else if (m_nChannels_2_3 == 4 && m_nChannels_4 == 6)
  192.         m_upmixMachine = up_4_6 ;
  193.     else
  194.         return HXR_FAIL ;
  195.     m_clev = m_slev = (int)((1UL<<31) * MINUS3DB) ; // -3 dB is default attenuation
  196.     return HXR_OK ;
  197. }
  198. /* saturated 16-bit add */
  199. INT16 adds16(INT16 a, INT16 b)
  200. {
  201.     INT32 s = (INT32)a+b ;
  202.     if (s > 0x7fff) s = 0x7fff ;
  203.     else if (s < -0x8000) s = -0x8000 ;
  204.     return (INT16)s ;
  205. }
  206. /* saturated 32-bit add */
  207. INT32 adds32(INT32 a, INT32 b)
  208. {
  209.     INT32 s = a+b ;
  210.     INT32 ov = ~(a ^ b) & (a ^ s) & 0x80000000 ; // overflow
  211.     if (ov)
  212.         s = (signed)((1UL<<31)-1)-((s ^ ov) >> 31) ;
  213.     return s ;
  214. }
  215. /* mix into a 32-bit buffer. Returns the number of samples written (more precisely,
  216.    if we mix 2 channels into a 5 channel buffer, and feed 2*n samples, then this
  217.    function will return 5*n samples, regardless into how many channels the 2 original
  218.    channels are mixed. */
  219. UINT32 HXAudioSvcMixEngine::upmix(const tAudioSample *pIn, INT32 *pOut0, const tUpMixMachine *pUpmixMachine, int nSamples, BOOL isDirty)
  220. {
  221.     INT32 *pOut = pOut0 ;
  222.     HX_ASSERT(nSamples % m_nChannels_2_3 == 0) ;
  223.     const tAudioSample *pEnd = pIn + nSamples ;
  224.     if (!isDirty)
  225.     {
  226.         while (pIn != pEnd)
  227.         {
  228.             *pOut = adds32(*pIn << (32-NBITS_PER_AUDIOSAMPLE), *pOut);
  229.             pIn  += pUpmixMachine->offsetIn  ;
  230.             pOut += pUpmixMachine->offsetOut ;
  231.             pUpmixMachine = pUpmixMachine->nextState ;
  232.         }
  233.     }
  234.     else
  235.     {
  236.         while (pIn != pEnd)
  237.         {
  238.             INT32 t = (INT32)*pIn << (32-NBITS_PER_AUDIOSAMPLE) ; // -MulShift31(*pIn,pUpmixMachine->gain)
  239.             *pOut = t ;
  240.             pIn  += pUpmixMachine->offsetIn  ;
  241.             pOut += pUpmixMachine->offsetOut ;
  242.             pUpmixMachine = pUpmixMachine->nextState ;
  243.         }
  244.     }
  245.     return pOut - pOut0 ;
  246. }
  247. /* mix into a 16-bit buffer. Returns the number of samples written (more precisely,
  248.    if we mix 2 channels into a 5 channel buffer, and feed 2*n samples, then this
  249.    function will return 5*n samples, regardless into how many channels the 2 original
  250.    channels are mixed. */
  251. UINT32 HXAudioSvcMixEngine::upmix(const tAudioSample *pIn, INT16 *pOut0, const tUpMixMachine *pUpmixMachine, int nSamples, BOOL isDirty)
  252. {
  253.     INT16 *pOut = pOut0 ;
  254.     HX_ASSERT(nSamples % m_nChannels_2_3 == 0) ;
  255.     const tAudioSample *pEnd = pIn + nSamples ;
  256.     if (!isDirty)
  257.     {
  258.         while (pIn != pEnd)
  259.         {
  260.             *pOut = adds16((INT16)(*pIn >> (NBITS_PER_AUDIOSAMPLE-16)), *pOut);
  261.             pIn  += pUpmixMachine->offsetIn  ;
  262.             pOut += pUpmixMachine->offsetOut ;
  263.             pUpmixMachine = pUpmixMachine->nextState ;
  264.         }
  265.     }
  266.     else
  267.     {
  268.         while (pIn != pEnd)
  269.         {
  270.             *pOut = (INT16)(*pIn >> (NBITS_PER_AUDIOSAMPLE-16)) ;
  271.             pIn  += pUpmixMachine->offsetIn  ;
  272.             pOut += pUpmixMachine->offsetOut ;
  273.             pUpmixMachine = pUpmixMachine->nextState ;
  274.         }
  275.     }
  276.     return pOut - pOut0 ;
  277. }
  278. void HXAudioSvcMixEngine::downmix2_1(tAudioSample *pBuffer, int nSamples)
  279. {
  280.     enum { L,R,strideIn } ; // input channel ordering
  281.     HX_ASSERT(nSamples % strideIn == 0) ;
  282.     const tAudioSample *pEnd = pBuffer + nSamples ;
  283.     tAudioSample *pOut = pBuffer;
  284.     while (pBuffer != pEnd)
  285.     {
  286.         *pOut++ = (pBuffer[L]>>1) + (pBuffer[R]>>1) ;
  287.         pBuffer += strideIn ;
  288.     }
  289. }
  290. void HXAudioSvcMixEngine::downmix5_1(tAudioSample *pBuffer, int nSamples)
  291. {
  292.     enum { L,R,C,Ls,Rs,strideIn } ; // input channel ordering
  293.     HX_ASSERT(nSamples % strideIn == 0) ;
  294.     const tAudioSample *pEnd = pBuffer + nSamples ;
  295.     tAudioSample *pOut = pBuffer;
  296.     const int clev = m_clev >> (HEADROOM-1);
  297.     const int slev = m_slev >> (HEADROOM-2);
  298.     while (pBuffer != pEnd)
  299.     {
  300.         INT32 c  = MulShift32(pBuffer[C], clev) ;
  301.         INT32 cs = MulShift32((pBuffer[Ls]>>1) + (pBuffer[Rs]>>1), slev) ;
  302.         *pOut++  = (pBuffer[L]>>HEADROOM) + c + (pBuffer[R]>>HEADROOM) + cs ;
  303.         pBuffer += strideIn ;
  304.     }
  305. }
  306. // Matrix surround downmix
  307. void HXAudioSvcMixEngine::downmix5_2_matrix(tAudioSample *pBuffer, int nSamples)
  308. {
  309.     enum { L,R,C,Ls,Rs,strideIn } ; // input channel ordering
  310.     HX_ASSERT(nSamples % strideIn == 0) ;
  311.     const tAudioSample *pEnd = pBuffer + nSamples ;
  312.     tAudioSample *pOut = pBuffer;
  313.     const int clev = m_clev >> (HEADROOM-1);
  314.     const int slev = m_slev >> (HEADROOM-2);
  315.     while (pBuffer != pEnd)
  316.     {
  317.         INT32 c  = MulShift32(pBuffer[C], clev) ; // creates two bits headroom
  318.         INT32 cs = MulShift32((pBuffer[Ls]>>1) + (pBuffer[Rs]>>1), slev) ; // two bits hr
  319.         pOut[0]  = (pBuffer[L]>>HEADROOM) + c + cs ;
  320.         pOut[1]  = (pBuffer[R]>>HEADROOM) + c - cs ;
  321.         pBuffer += strideIn ;
  322.         pOut    += 2 ;
  323.     }
  324. }
  325. // Stereo downmix
  326. void HXAudioSvcMixEngine::downmix5_2_stereo(tAudioSample *pBuffer, int nSamples)
  327. {
  328.     enum { L,R,C,Ls,Rs,strideIn } ; // input channel ordering
  329.     HX_ASSERT(nSamples % strideIn == 0) ;
  330.     const tAudioSample *pEnd = pBuffer + nSamples ;
  331.     tAudioSample *pOut = pBuffer;
  332.     const int clev = m_clev >> (HEADROOM-1);
  333.     const int slev = m_slev >> (HEADROOM-1);
  334.     while (pBuffer != pEnd)
  335.     {
  336.         INT32 c = MulShift32(pBuffer[C], clev) ;
  337.         pOut[0] = (pBuffer[L]>>HEADROOM) + c + MulShift32(pBuffer[Ls], slev) ;
  338.         pOut[1] = (pBuffer[R]>>HEADROOM) + c + MulShift32(pBuffer[Rs], slev) ;
  339.         pBuffer += strideIn ;
  340.         pOut    += 2 ;
  341.     }
  342. }
  343. // Matrix surround downmix
  344. void HXAudioSvcMixEngine::downmix6_2_matrix(tAudioSample *pBuffer, int nSamples)
  345. {
  346.     enum { L,R,C,LFE,Ls,Rs,strideIn } ; // input channel ordering
  347.     HX_ASSERT(nSamples % strideIn == 0) ;
  348.     const tAudioSample *pEnd = pBuffer + nSamples ;
  349.     tAudioSample *pOut = pBuffer;
  350.     const int clev = m_clev >> (HEADROOM-1);
  351.     const int slev = m_slev >> (HEADROOM-2);
  352.     while (pBuffer != pEnd)
  353.     {
  354.         INT32 c  = MulShift32(pBuffer[C], clev) ; // creates two bits headroom
  355.         INT32 cs = MulShift32((pBuffer[Ls]>>1) + (pBuffer[Rs]>>1), slev) ; // two bits hr
  356.         pOut[0]  = (pBuffer[L]>>HEADROOM) + c + cs ;
  357.         pOut[1]  = (pBuffer[R]>>HEADROOM) + c - cs ;
  358.         pBuffer += strideIn ;
  359.         pOut    += 2 ;
  360.     }
  361. }
  362. // Stereo downmix
  363. void HXAudioSvcMixEngine::downmix6_2_stereo(tAudioSample *pBuffer, int nSamples)
  364. {
  365.     enum { L,R,C,LFE,Ls,Rs,strideIn } ; // input channel ordering
  366.     HX_ASSERT(nSamples % strideIn == 0) ;
  367.     const tAudioSample *pEnd = pBuffer + nSamples ;
  368.     tAudioSample *pOut = pBuffer;
  369.     const int clev = m_clev >> (HEADROOM-1);
  370.     const int slev = m_slev >> (HEADROOM-1);
  371.     while (pBuffer != pEnd)
  372.     {
  373.         INT32 c = MulShift32(pBuffer[C], clev) ;
  374.         pOut[0] = (pBuffer[L]>>HEADROOM) + c + MulShift32(pBuffer[Ls], slev) ;
  375.         pOut[1] = (pBuffer[R]>>HEADROOM) + c + MulShift32(pBuffer[Rs], slev) ;
  376.         pBuffer += strideIn ;
  377.         pOut    += 2 ;
  378.     }
  379. }
  380. // Matrix surround downmix
  381. void HXAudioSvcMixEngine::downmix4_2_matrix(tAudioSample *pBuffer, int nSamples)
  382. {
  383.     enum { L,R,C,Cs,strideIn } ; // input channel ordering
  384.     HX_ASSERT(nSamples % strideIn == 0) ;
  385.     const tAudioSample *pEnd = pBuffer + nSamples ;
  386.     tAudioSample *pOut = pBuffer;
  387.     const int clev = m_clev >> (HEADROOM-1);
  388.     const int slev = m_slev >> (HEADROOM-1);
  389.     while (pBuffer != pEnd)
  390.     {
  391.         INT32 c  = MulShift32(pBuffer[C], clev) ; // creates two bits headroom
  392.         INT32 cs = MulShift32(pBuffer[Cs], slev) ; // two bits hr
  393.         pOut[0]  = (pBuffer[L]>>HEADROOM) + c + cs ;
  394.         pOut[1]  = (pBuffer[R]>>HEADROOM) + c - cs ;
  395.         pBuffer += strideIn ;
  396.         pOut    += 2 ;
  397.     }
  398. }
  399. // Stereo downmix
  400. void HXAudioSvcMixEngine::downmix4_2_stereo(tAudioSample *pBuffer, int nSamples)
  401. {
  402.     enum { L,R,C,Cs,strideIn } ; // input channel ordering
  403.     HX_ASSERT(nSamples % strideIn == 0) ;
  404.     const tAudioSample *pEnd = pBuffer + nSamples ;
  405.     tAudioSample *pOut = pBuffer;
  406.     const int clev = m_clev >> (HEADROOM-1);
  407.     const int slev = m_slev >> (HEADROOM-1);
  408.     while (pBuffer != pEnd)
  409.     {
  410.         INT32 c = MulShift32(pBuffer[C], clev) ;
  411.         INT32 cs = MulShift32(pBuffer[Cs], slev) ; // two bits hr
  412.         pOut[0] = (pBuffer[L]>>HEADROOM) + c + cs ;
  413.         pOut[1] = (pBuffer[R]>>HEADROOM) + c + cs ;
  414.         pBuffer += strideIn ;
  415.         pOut    += 2 ;
  416.     }
  417. }