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

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. //////////////////////////////////////////////////////////////////////////////
  36. // 
  37. //  audio format for QuickTime renderer for RealMedia Architecture.
  38. //
  39. // Notes:
  40. // This class puts together the audio packets and decodes the audio data.
  41. // There are still unresolved problems with this code - audio data gets
  42. // dropped. This only occurs when there is more than one frame of audio
  43. // data per packet - like MP3. Also, audio services doesn't seem to be 
  44. // releasing the audio buffers. This is a huge problem when trying to 
  45. // listen to CD quality audio for any amount of time. Another problem - 
  46. // the current implementation will not work when one audio frame spans 
  47. // multiple rtp packets. The code from the video renderer will need to be 
  48. // adapted to work with audio. The class CQTPacket does all the QuickTime
  49. // header parsing. See the notes in that file for more info on the QT header
  50. // structure.
  51. // 
  52. /****************************************************************************
  53.  *  Defines
  54.  */
  55. #define MAX_DECODE_GRANULARITY     200     // in milliseconds
  56. #define DEFAULT_AUDIO_PREROLL     2000    // in milliseconds
  57. #if defined(HELIX_FEATURE_MIN_HEAP)
  58. #define MAXIMUM_AUDIO_PREROLL     3000    // in milliseconds
  59. #else
  60. #define MAXIMUM_AUDIO_PREROLL     15000    // in milliseconds
  61. #endif
  62. /****************************************************************************
  63.  *  Includes
  64.  */
  65. #include "hlxclib/stdio.h"
  66. #include "hlxclib/string.h"
  67. // #include "netbyte.h"
  68. #include "hxtypes.h"
  69. #include "hxresult.h"
  70. #include "hxcom.h"
  71. #include "hxcomm.h"
  72. #include "hxausvc.h"
  73. #include "ihxpckts.h"
  74. #include "hxerror.h"
  75. #include "hxcore.h"
  76. #include "hxupgrd.h"
  77. #include "hxslist.h"
  78. #include "hxassert.h"
  79. #include "hxstrutl.h"
  80. #include "hxheap.h"
  81. #ifdef _DEBUG
  82. #undef HX_THIS_FILE
  83. static const char HX_THIS_FILE[] = __FILE__;
  84. #endif
  85. #include "hxtick.h"
  86. #include "audrend.h"
  87. #include "audrendf.h"
  88. /****************************************************************************
  89.  *  CAudioFormat
  90.  */
  91. /****************************************************************************
  92.  *  Constructor/Destructor
  93.  */
  94. CAudioFormat::CAudioFormat(IHXCommonClassFactory* pCommonClassFactory,
  95.    CAudioRenderer* pAudioRenderer)
  96.     : m_pCommonClassFactory(pCommonClassFactory)
  97.     , m_pContext(NULL)
  98.     , m_pPendingPacketQueue(NULL)
  99.     , m_ulForceDiscardUntilTime(NO_TIME_SET)
  100.     , m_bPostStartTime(FALSE)
  101.     , m_ulTrackStartTime(0)
  102.     , m_ulTrackEndTime(NO_TIME_SET)
  103.     , m_pAudioFmt(NULL)
  104.     , m_fCompressionRatio(1.0)
  105.     , m_ulStartTime(0)
  106.     , m_lRefCount(0)
  107. {
  108.     if (m_pCommonClassFactory)
  109.     {
  110. m_pCommonClassFactory->AddRef();
  111.     }
  112.     m_pContext = pAudioRenderer->GetContext();
  113.     if (m_pContext)
  114.     {
  115. m_pContext->AddRef();
  116.     }
  117.     // NULL out the AU String
  118.     memset(&m_szAUStr[0], 0, MAX_AUSTR_SIZE);
  119. }
  120. CAudioFormat::~CAudioFormat()
  121. {
  122.     HX_DELETE(m_pAudioFmt);
  123.     FlushQueues();    
  124.     HX_DELETE(m_pPendingPacketQueue);
  125.     HX_RELEASE(m_pCommonClassFactory);
  126.     HX_RELEASE(m_pContext);
  127. }
  128. /****************************************************************************
  129.  *  CAudioFormat::Init
  130.  */
  131. HX_RESULT CAudioFormat::Init(IHXValues* pHeader)
  132. {
  133.     HX_RESULT retVal = HXR_FAIL;
  134.     if (pHeader)
  135.     {
  136.         m_pAudioFmt = new HXAudioFormat;
  137.         if (m_pAudioFmt)
  138.         {
  139.             m_pPendingPacketQueue = new CHXSimpleList;
  140.             if (m_pPendingPacketQueue)
  141.             {
  142.                 m_pAudioFmt->uChannels       = (UINT16) GetULONG32Property(pHeader, "Channels", 1);
  143.                 m_pAudioFmt->uBitsPerSample  = (UINT16) GetULONG32Property(pHeader, "BitsPerSample", 16);
  144.                 m_pAudioFmt->ulSamplesPerSec = GetULONG32Property(pHeader, "SamplesPerSecond", 8000);
  145.                 // MaxBlockSize - default to 200ms of data
  146. #ifdef HELIX_FEATURE_FLP_AUDREND
  147.                 m_pAudioFmt->uMaxBlockSize = (UINT16)
  148.                     (((double) (m_pAudioFmt->ulSamplesPerSec)) * 
  149.                      ((double) (m_pAudioFmt->uBitsPerSample)) * 
  150.                      ((double) (m_pAudioFmt->uChannels)) *
  151.                      MAX_DECODE_GRANULARITY /
  152.                      8000.0 +
  153.                      ((double) (m_pAudioFmt->uBitsPerSample)) * // Compensate for possible round off
  154.                      ((double) (m_pAudioFmt->uChannels)) /
  155.                      8.0);
  156. #else   // HELIX_FEATURE_FLP_AUDREND
  157.                 HX_ASSERT((((UINT32) (m_pAudioFmt->ulSamplesPerSec)) * 
  158.                            ((UINT32) (m_pAudioFmt->uBitsPerSample)) * 
  159.                            ((UINT32) (m_pAudioFmt->uChannels))) < 
  160.                           (((ULONG32) 0xFFFFFFFF) / MAX_DECODE_GRANULARITY));
  161.                 m_pAudioFmt->uMaxBlockSize = (UINT16)
  162.                     (((UINT32) (m_pAudioFmt->ulSamplesPerSec)) * 
  163.                      ((UINT32) (m_pAudioFmt->uBitsPerSample)) * 
  164.                      ((UINT32) (m_pAudioFmt->uChannels)) *
  165.                      MAX_DECODE_GRANULARITY /
  166.                      8000 +
  167.                      ((UINT32) (m_pAudioFmt->uBitsPerSample)) * // Compensate for possible round off
  168.                      ((UINT32) (m_pAudioFmt->uChannels)) /
  169.                      8);
  170. #endif  // HELIX_FEATURE_FLP_AUDREND
  171.                 // Clear return value
  172.                 retVal = HXR_OK;
  173.             }
  174.         }
  175.     }
  176.     return retVal;
  177. }
  178. /****************************************************************************
  179.  *    CAudioFormat::GetDefaultPreroll
  180.  */
  181. ULONG32 CAudioFormat::GetDefaultPreroll(IHXValues* pValues)
  182. {
  183.     return DEFAULT_AUDIO_PREROLL;
  184. }
  185. ULONG32 CAudioFormat::GetMaximumPreroll(IHXValues* pValues)
  186. {
  187.     return MAXIMUM_AUDIO_PREROLL;
  188. }
  189. void CAudioFormat::FlushQueues(void)
  190. {
  191.     if (m_pPendingPacketQueue != NULL)
  192.     {
  193. CMediaPacket* pQTPkt;
  194. while (!m_pPendingPacketQueue->IsEmpty())
  195. {
  196.     // empty all of the pending packets
  197.     // and delete them
  198.     pQTPkt = (CMediaPacket*) m_pPendingPacketQueue->RemoveHead();
  199.     CMediaPacket::DeletePacket(pQTPkt);
  200. }
  201.     }
  202. }
  203. HX_RESULT CAudioFormat::GetAudioFormat(HXAudioFormat& audioFmt)
  204. {
  205.     audioFmt.uChannels = m_pAudioFmt->uChannels;
  206.     audioFmt.uBitsPerSample = m_pAudioFmt->uBitsPerSample;
  207.     audioFmt.ulSamplesPerSec = m_pAudioFmt->ulSamplesPerSec;
  208.     audioFmt.uMaxBlockSize = m_pAudioFmt->uMaxBlockSize;
  209.     return HXR_OK;
  210. }
  211. /****************************************************************************
  212.  *  CAudioFormat::Enqueue
  213.  */
  214. BOOL CAudioFormat::Enqueue(IHXPacket* pPacket)
  215. {
  216.     CMediaPacket* pFramePacket = NULL;
  217.     HX_RESULT retVal = HXR_OK;
  218.     HX_ASSERT(m_pPendingPacketQueue);
  219.     pFramePacket = CreateAssembledPacket(pPacket);
  220.     if (pFramePacket)
  221.     {
  222. m_pPendingPacketQueue->AddTail(pFramePacket);
  223.     }
  224.     
  225.     return retVal;
  226. }
  227. HX_RESULT CAudioFormat::CreateAudioFrame(HXAudioData& audioData, 
  228.  AUDIO_STATE audioState)
  229. {
  230.     HX_RESULT retVal = HXR_NO_DATA;
  231.     BOOL bTryAgain;
  232.     do
  233.     {
  234. bTryAgain = FALSE;
  235. HX_RELEASE(audioData.pData);
  236. audioData.ulAudioTime = 0;
  237. retVal = DecodeAudioData(audioData, audioState == AUDIO_END_OF_PACKETS);
  238. if (retVal == HXR_OK)
  239. {
  240.     if (AdjustAudioData(audioData))
  241.     {
  242. // once we are passed the start time, disable it as a
  243. // a requirement to prevent clipping on wrap-around
  244. m_bPostStartTime = TRUE;
  245. // if we've fulfilled the discard, reset state
  246. if ((m_ulForceDiscardUntilTime != NO_TIME_SET) && 
  247.     IsTimeGreater(audioData.ulAudioTime + 
  248.     ConvertBytesToMs(audioData.pData->GetSize()),
  249.     m_ulForceDiscardUntilTime))
  250. {
  251.     m_ulForceDiscardUntilTime = NO_TIME_SET;
  252. }
  253.     }
  254.     else
  255.     {
  256. retVal = HXR_NO_DATA;
  257. HX_RELEASE(audioData.pData);
  258. bTryAgain = TRUE;
  259.     }
  260. }
  261.     } while (bTryAgain);
  262.     return retVal;
  263. }
  264. CMediaPacket* CAudioFormat::PeekAudioPacket(void)
  265. {
  266.     CMediaPacket* pAudioPacket = NULL;
  267.     if (m_pPendingPacketQueue && (!m_pPendingPacketQueue->IsEmpty()))
  268.     {
  269. pAudioPacket = (CMediaPacket*) m_pPendingPacketQueue->GetHead();
  270.     }
  271.     return pAudioPacket;
  272. }
  273. CMediaPacket* CAudioFormat::GetAudioPacket(void)
  274. {
  275.     CMediaPacket* pAudioPacket = NULL;
  276.     if (m_pPendingPacketQueue && (!m_pPendingPacketQueue->IsEmpty()))
  277.     {
  278. pAudioPacket = (CMediaPacket*) m_pPendingPacketQueue->RemoveHead();
  279.     }
  280.     return pAudioPacket;
  281. }
  282. HX_RESULT CAudioFormat::PutAudioPacket(CMediaPacket* pMediaPacket)
  283. {
  284.     HX_RESULT retVal = HXR_FAIL;
  285.     HX_ASSERT(m_pPendingPacketQueue);
  286.     if (m_pPendingPacketQueue && pMediaPacket)
  287.     {
  288. m_pPendingPacketQueue->AddTail(pMediaPacket);
  289. retVal = HXR_OK;
  290.     }
  291.     return retVal;
  292. }
  293. CMediaPacket* CAudioFormat::CreateAssembledPacket(IHXPacket* pPayloadPacket)
  294. {
  295.     return NULL;
  296. }
  297. HX_RESULT CAudioFormat::DecodeAudioData(HXAudioData& audioData,
  298. BOOL bFlushCodec)
  299. {
  300.     return HXR_NOTIMPL;
  301. }
  302.     
  303. void CAudioFormat::DiscardAudioUntil(UINT32 ulTimestamp)
  304. {
  305.     BOOL bDone = FALSE;
  306.     // cannot equal NO_TIME_SET so we bump it up one
  307.     if (ulTimestamp == NO_TIME_SET)
  308.     {
  309. ulTimestamp += 1;
  310.     }
  311.     m_ulForceDiscardUntilTime = ulTimestamp;
  312.     // look through the re-assembled packet queue and delete data
  313.     // from there that's earlier than the discard until time
  314.     CMediaPacket* pQTPkt;
  315.     while (!m_pPendingPacketQueue->IsEmpty())
  316.     {
  317. pQTPkt = (CMediaPacket*) m_pPendingPacketQueue->GetHead();
  318. if (pQTPkt->m_ulTime >= ulTimestamp)
  319. {
  320.     break;
  321. }
  322. m_pPendingPacketQueue->RemoveHead();
  323. CMediaPacket::DeletePacket(pQTPkt);
  324.     }
  325. }
  326. void CAudioFormat::Reset(void)
  327. {
  328.     m_bPostStartTime = FALSE;
  329.     m_ulForceDiscardUntilTime = NO_TIME_SET;
  330.     FlushQueues();
  331. }
  332. void CAudioFormat::OverrideFactory(IHXCommonClassFactory* pCommonClassFactory)
  333. {
  334.     HX_ASSERT(pCommonClassFactory);
  335.     if (pCommonClassFactory)
  336.     {
  337. HX_RELEASE(m_pCommonClassFactory);
  338. m_pCommonClassFactory = pCommonClassFactory;
  339. m_pCommonClassFactory->AddRef();
  340.     }
  341. }
  342. void CAudioFormat::SetCompressionRation(double fCompressionRatio)
  343. {
  344.     HX_ASSERT(fCompressionRatio > 0.0);
  345.     
  346.     if (fCompressionRatio > 0.0)
  347.     {
  348. m_fCompressionRatio = fCompressionRatio;
  349.     }
  350. }
  351. UINT32 CAudioFormat::ConvertMsToBytes(UINT32 ulMs)
  352. {
  353. #ifdef HELIX_FEATURE_FLP_AUDREND
  354.     return (UINT32)(((double) ulMs) * 
  355.     ((double) m_pAudioFmt->uChannels) * 
  356.     ((double) m_pAudioFmt->uBitsPerSample) *
  357.     ((double) m_pAudioFmt->ulSamplesPerSec) / 
  358.     8000.0 + 
  359.     0.5);
  360. #else // HELIX_FEATURE_FLP_AUDREND
  361.     UINT32 ulBitsPerSecond = ((UINT32) m_pAudioFmt->uChannels) * 
  362.      ((UINT32) m_pAudioFmt->uBitsPerSample) *
  363.      ((UINT32) m_pAudioFmt->ulSamplesPerSec);
  364.     HX_ASSERT(ulMs < (((ULONG32) 0xFFFFF05F) / ulBitsPerSecond));
  365.     return (ulMs * ulBitsPerSecond + 4000) / 8000;
  366. #endif // HELIX_FEATURE_FLP_AUDREND
  367. }
  368. UINT32 CAudioFormat::ConvertBytesToMs(UINT32 ulBytes)
  369. {    
  370. #ifdef HELIX_FEATURE_FLP_AUDREND
  371.     return (UINT32)(((double) ulBytes) * 
  372.     8000.0 /
  373.     (((double) m_pAudioFmt->uChannels) * 
  374.      ((double) m_pAudioFmt->uBitsPerSample) *
  375.      ((double) m_pAudioFmt->ulSamplesPerSec)) + 
  376.     0.5);
  377. #else // HELIX_FEATURE_FLP_AUDREND
  378.     UINT32 ulBitsPerSecond = ((UINT32) m_pAudioFmt->uChannels) * 
  379.      ((UINT32) m_pAudioFmt->uBitsPerSample) *
  380.      ((UINT32) m_pAudioFmt->ulSamplesPerSec);
  381.     HX_ASSERT(ulBytes < 536871);
  382.     return ((ulBytes * 8000) / ulBitsPerSecond + 
  383.     ((ulBytes * 8000) % ulBitsPerSecond + (ulBitsPerSecond >> 1)) / ulBitsPerSecond);
  384. #endif // HELIX_FEATURE_FLP_AUDREND
  385. }
  386. UINT32 CAudioFormat::ConvertMsToSamples(UINT32 ulMs)
  387. {
  388. #ifdef HELIX_FEATURE_FLP_AUDREND
  389.     return (UINT32)(((double) ulMs) /
  390.     1000.0 *
  391.     ((double) m_pAudioFmt->uChannels) *
  392.     ((double) m_pAudioFmt->ulSamplesPerSec) +
  393.     0.5);
  394. #else // HELIX_FEATURE_FLP_AUDREND
  395.     UINT32 ulCombinedSamplesPerSecond = ((UINT32) m_pAudioFmt->uChannels) *
  396.         ((UINT32) m_pAudioFmt->ulSamplesPerSec);
  397.     return ((ulMs / 1000) * ulCombinedSamplesPerSecond +
  398.     ((ulMs % 1000) * ulCombinedSamplesPerSecond + 500) / 1000);
  399. #endif // HELIX_FEATURE_FLP_AUDREND
  400. }
  401. UINT32 CAudioFormat::ConvertSamplesToMs(UINT32 ulSamples)
  402. {
  403. #ifdef HELIX_FEATURE_FLP_AUDREND
  404.     return (UINT32)(((double) ulSamples) /
  405.     (((double) m_pAudioFmt->uChannels) *
  406.      ((double) m_pAudioFmt->ulSamplesPerSec)) *
  407.     1000.0 + 
  408.     0.5);
  409. #else // HELIX_FEATURE_FLP_AUDREND
  410.     UINT32 ulCombinedSamplesPerSecond = ((UINT32) m_pAudioFmt->uChannels) *
  411.         ((UINT32) m_pAudioFmt->ulSamplesPerSec);
  412.     return ((ulSamples / ulCombinedSamplesPerSecond) * 1000 +
  413.     ((ulSamples % ulCombinedSamplesPerSecond) * 1000 + 500) / ulCombinedSamplesPerSecond);
  414. #endif // HELIX_FEATURE_FLP_AUDREND
  415. }
  416. UINT32 CAudioFormat::ConvertBytesToSamples(UINT32 ulBytes)
  417. {
  418. #ifdef HELIX_FEATURE_FLP_AUDREND
  419.     return (UINT32)(((double) ulBytes) *
  420.     8.0 /
  421.     ((double) m_pAudioFmt->uBitsPerSample) +
  422.     0.5);
  423. #else // HELIX_FEATURE_FLP_AUDREND
  424.     UINT32 ulBitsPerSample = ((UINT32) m_pAudioFmt->uBitsPerSample);
  425.     return (((ulBytes / ulBitsPerSample) << 3) +
  426.     (((ulBytes % ulBitsPerSample) << 3) + (ulBitsPerSample >> 1)) / ulBitsPerSample);
  427. #endif // HELIX_FEATURE_FLP_AUDREND
  428. }
  429. UINT32 CAudioFormat::ConvertSamplesToBytes(UINT32 ulSamples)
  430. {    
  431. #ifdef HELIX_FEATURE_FLP_AUDREND
  432.     return (UINT32)(((double) ulSamples) *
  433.     ((double) m_pAudioFmt->uBitsPerSample) /
  434.     8.0 + 
  435.     0.5);
  436. #else // HELIX_FEATURE_FLP_AUDREND
  437.     UINT32 ulBitsPerSample = ((UINT32) m_pAudioFmt->uBitsPerSample);
  438.     return ((ulSamples / 8) * ulBitsPerSample +
  439.     ((ulSamples % 8) * ulBitsPerSample + 4) / 8);
  440. #endif // HELIX_FEATURE_FLP_AUDREND
  441. }
  442. UINT32 CAudioFormat::ConvertCompressedBytesToMs(UINT32 ulBytes)
  443. {
  444.     return (UINT32)(((double) ulBytes) * 
  445.     8000.0 /
  446.     ((double) m_pAudioFmt->uChannels) * 
  447.     ((double) m_pAudioFmt->uBitsPerSample) *
  448.     ((double) m_pAudioFmt->ulSamplesPerSec) *
  449.     m_fCompressionRatio +
  450.     0.5);
  451. }
  452. UINT32 CAudioFormat::ConvertMsToCompressedBytes(UINT32 ulMs)
  453. {
  454.     return (UINT32)(((double) ulMs) * 
  455.     ((double) m_pAudioFmt->uChannels) * 
  456.     ((double) m_pAudioFmt->uBitsPerSample) *
  457.     ((double) m_pAudioFmt->ulSamplesPerSec) / 
  458.     8000.0 /
  459.     m_fCompressionRatio + 
  460.     0.5);
  461. }
  462. UINT32 CAudioFormat::ConvertMsToTime(UINT32 ulMs)
  463. {
  464. #ifdef HELIX_FEATURE_FLP_AUDREND
  465.     return (UINT32)(((double) ulMs) /
  466.     1000.0 *
  467.     ((double) m_pAudioFmt->ulSamplesPerSec) +
  468.     0.5);
  469. #else // HELIX_FEATURE_FLP_AUDREND
  470.     UINT32 ulSamplesPerSec = ((UINT32) m_pAudioFmt->ulSamplesPerSec);
  471.     return ((ulMs / 1000) * ulSamplesPerSec +
  472.     ((ulMs % 1000) * ulSamplesPerSec + 500) / 1000);
  473. #endif // HELIX_FEATURE_FLP_AUDREND
  474. }
  475. UINT32 CAudioFormat::ConvertTimeToMs(UINT32 ulTime)
  476. {   
  477. #ifdef HELIX_FEATURE_FLP_AUDREND
  478.     return (UINT32)(((double) ulTime) /
  479.     ((double) m_pAudioFmt->ulSamplesPerSec) *
  480.     1000.0 + 
  481.     0.5);
  482. #else // HELIX_FEATURE_FLP_AUDREND
  483.     UINT32 ulSamplesPerSec = ((UINT32) m_pAudioFmt->ulSamplesPerSec);
  484.     return ((ulTime / ulSamplesPerSec) * 1000 +
  485.     ((ulTime % ulSamplesPerSec) * 1000 + (ulSamplesPerSec >> 1)) / ulSamplesPerSec);
  486. #endif // HELIX_FEATURE_FLP_AUDREND
  487. }
  488. BOOL CAudioFormat::ClipAudioBuffer(HXAudioData* pAudioData, 
  489.      UINT32 ulAudioTime, 
  490.      BOOL bFromStart)
  491. {
  492.     BOOL bResult = FALSE;
  493.     UINT32 ulDuration = 0;
  494.     UINT32 ulSize = 0;
  495.     UINT32 ulExtraInMs = 0;
  496.     UINT32 ulExtraInBytes = 0;
  497.     IHXBuffer* pBuffer = NULL;
  498.     HX_ASSERT(pAudioData);
  499.     HX_ASSERT(pAudioData->pData);
  500.     ulSize = (pAudioData->pData)->GetSize();
  501.     // caculate the worth of this data in ms
  502.     ulDuration = ConvertBytesToMs(ulSize);
  503.     
  504.     // trim off any extra bytes
  505.     if (bFromStart)
  506.     {
  507. HX_ASSERT(IsTimeLess(pAudioData->ulAudioTime, ulAudioTime));
  508. if (IsTimeGreater(pAudioData->ulAudioTime + ulDuration, ulAudioTime))
  509. {       
  510.     // trim off partial data
  511.     ulExtraInMs = ulAudioTime - pAudioData->ulAudioTime;
  512.     // convert to bytes
  513.     ulExtraInBytes = ConvertMsToBytes(ulExtraInMs);
  514.     // align in sample boundary
  515.     ulExtraInBytes -= (ulExtraInBytes % (m_pAudioFmt->uBitsPerSample * 
  516.        m_pAudioFmt->uChannels / 8));
  517.     m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, 
  518. (void**) &pBuffer);
  519.     if (pBuffer)
  520.     {
  521. if (pBuffer->Set((pAudioData->pData)->GetBuffer() + ulExtraInBytes, 
  522.   ulSize - ulExtraInBytes)
  523.     == HXR_OK)
  524. {
  525.     pAudioData->pData->Release();
  526.     pAudioData->pData = pBuffer;    
  527.     pAudioData->ulAudioTime = ulAudioTime;
  528.     bResult = TRUE;
  529. }
  530. else
  531. {
  532.     pBuffer->Release();
  533. }
  534.     }
  535. }
  536.     }
  537.     else
  538.     {
  539. HX_ASSERT(IsTimeGreater(pAudioData->ulAudioTime + ulDuration, ulAudioTime));
  540. if (IsTimeLess(pAudioData->ulAudioTime, ulAudioTime))
  541. {
  542.     // trim off the extra ones
  543.     ulExtraInMs = pAudioData->ulAudioTime + ulDuration - ulAudioTime;
  544.     // convert to bytes
  545.     ulExtraInBytes = ConvertMsToBytes(ulExtraInMs);
  546.     // align in sample boundary
  547.     ulExtraInBytes -= (ulExtraInBytes % (m_pAudioFmt->uBitsPerSample * 
  548.        m_pAudioFmt->uChannels / 8));
  549.     m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, 
  550. (void**) &pBuffer);
  551.     if (pBuffer)
  552.     {
  553. if (pBuffer->Set((pAudioData->pData)->GetBuffer(), 
  554.  ulSize - ulExtraInBytes)
  555.     == HXR_OK)
  556. {
  557.     pAudioData->pData->Release();
  558.     pAudioData->pData = pBuffer;
  559.     bResult = TRUE;
  560. }
  561. else
  562. {
  563.     pAudioData->pData;
  564. }
  565.     }   
  566. }
  567.     }
  568.     return bResult;
  569. }
  570. inline BOOL CAudioFormat::AdjustAudioData(REF(HXAudioData) audioData)
  571. {
  572.     BOOL bResult = TRUE;
  573.     UINT32 ulDuration = 0;
  574.     UINT32 ulSize = 0;
  575.     UINT32 ulExtraInMs = 0;
  576.     UINT32 ulExtraInBytes = 0;
  577.     IHXBuffer* pBuffer = NULL;
  578.     if (((!m_bPostStartTime) && (m_ulTrackStartTime != NO_TIME_SET)) || 
  579. (m_ulTrackEndTime != NO_TIME_SET) ||
  580. (m_ulForceDiscardUntilTime != NO_TIME_SET))
  581.     {
  582. ulSize = (audioData.pData)->GetSize();
  583. // caculate the worth of this data in ms
  584. ulDuration = ConvertBytesToMs(ulSize);
  585. // trim off any extra bytes
  586. if (((!m_bPostStartTime) &&
  587.      (m_ulTrackStartTime != NO_TIME_SET) && 
  588.      IsTimeLess(audioData.ulAudioTime, m_ulTrackStartTime)) ||
  589.     ((m_ulForceDiscardUntilTime != NO_TIME_SET) && 
  590.      IsTimeLess(audioData.ulAudioTime, m_ulForceDiscardUntilTime)))
  591. {
  592.     UINT32 ulStartTimeToUse = m_ulTrackStartTime;
  593.     
  594.     if (m_bPostStartTime ||
  595. (ulStartTimeToUse == NO_TIME_SET) ||
  596. IsTimeLess(m_ulTrackStartTime, m_ulForceDiscardUntilTime))
  597.     {
  598. ulStartTimeToUse = m_ulForceDiscardUntilTime;
  599.     }
  600.     bResult = ClipAudioBuffer(&audioData,
  601.       ulStartTimeToUse,
  602.       TRUE);
  603. }
  604. if ((m_ulTrackEndTime != NO_TIME_SET) &&
  605.     bResult &&
  606.     IsTimeGreater((audioData.ulAudioTime + ulDuration), m_ulTrackEndTime))
  607. {
  608.     bResult = ClipAudioBuffer(&audioData,
  609.       m_ulTrackEndTime,
  610.       FALSE);
  611. }
  612.     }
  613.     return bResult;
  614. }
  615. // *** IUnknown methods ***
  616. /****************************************************************************
  617. *  IUnknown::QueryInterface                                    ref:  hxcom.h
  618. *
  619. *  This routine indicates which interfaces this object supports. If a given
  620. *  interface is supported, the object's reference count is incremented, and
  621. *  a reference to that interface is returned. Otherwise a NULL object and
  622. *  error code are returned. This method is called by other objects to
  623. *  discover the functionality of this object.
  624. */
  625. STDMETHODIMP CAudioFormat::QueryInterface(REFIID riid, void** ppvObj)
  626. {
  627.     if (IsEqualIID(riid, IID_IUnknown))
  628.     {
  629. AddRef();
  630. *ppvObj = (IUnknown*) this;
  631. return HXR_OK;
  632.     }
  633.     
  634.     *ppvObj = NULL;
  635.     return HXR_NOINTERFACE;
  636. }
  637. /****************************************************************************
  638. *  IUnknown::AddRef                                            ref:  hxcom.h
  639. *
  640. *  This routine increases the object reference count in a thread safe
  641. *  manner. The reference count is used to manage the lifetime of an object.
  642. *  This method must be explicitly called by the user whenever a new
  643. *  reference to an object is used.
  644. */
  645. STDMETHODIMP_(ULONG32) CAudioFormat::AddRef()
  646. {
  647.     return InterlockedIncrement(&m_lRefCount);
  648. }
  649. /****************************************************************************
  650. *  IUnknown::Release                                           ref:  hxcom.h
  651. *
  652. *  This routine decreases the object reference count in a thread safe
  653. *  manner, and deletes the object if no more references to it exist. It must
  654. *  be called explicitly by the user whenever an object is no longer needed.
  655. */
  656. STDMETHODIMP_(ULONG32) CAudioFormat::Release()
  657. {
  658.     if (InterlockedDecrement(&m_lRefCount) > 0)
  659.     {
  660.         return m_lRefCount;
  661.     }
  662.     
  663.     delete this;
  664.     return 0;
  665. }
  666. UINT32 CAudioFormat::GetULONG32Property(IHXValues*  pValues,
  667.                                         const char* pszName,
  668.                                         UINT32      ulDefault)
  669. {
  670.     UINT32 ulRet = ulDefault;
  671.     if (pValues && pszName)
  672.     {
  673.         pValues->GetPropertyULONG32(pszName, ulRet);
  674.     }
  675.     return ulRet;
  676. }