home *** CD-ROM | disk | FTP | other *** search
/ Game Audio Programming / GameAudioProgramming.iso / Game_Audio / audio_sdk / src / AudioLib / WMA.cpp < prev    next >
C/C++ Source or Header  |  2002-07-15  |  17KB  |  715 lines

  1. /***********************************************************\
  2. Copyright (C) James Boer, 2002. 
  3. All rights reserved worldwide.
  4.  
  5. This software is provided "as is" without express or implied
  6. warranties. You may freely copy and compile this source into
  7. applications you distribute provided that the copyright text
  8. below is included in the resulting source code, for example:
  9. "Portions Copyright (C) James Boer, 2002"
  10. \***********************************************************/
  11.  
  12. #include "Audio.h"
  13. #include "WMA.h"
  14. #include "AudioMgr.h"
  15.  
  16. #ifdef USE_WMA
  17. using namespace std;
  18. using namespace Audio;
  19.  
  20.  
  21. const uint32 DECODING_BUFFER_ERROR = 8192;
  22.  
  23. //------------------------------------------------------------------------//
  24. WMACallback::WMACallback()
  25. {
  26.     Clear();
  27. }
  28.  
  29. //------------------------------------------------------------------------//
  30. WMACallback::~WMACallback()
  31. {
  32.     assert(!m_iRefCount);
  33. }
  34.  
  35. //------------------------------------------------------------------------//
  36. void WMACallback::Clear()
  37. {
  38.     m_iRefCount = 0;
  39. }
  40.  
  41.  
  42. //------------------------------------------------------------------------//
  43. HRESULT WMACallback::QueryInterface(
  44.     const struct _GUID& guid, 
  45.     void** ppInterface)
  46. {
  47.     if ( guid == IID_IWMReaderCallback )
  48.         *ppInterface = ( IWMReaderCallback* )this;
  49.     else if( guid == IID_IWMReaderCallbackAdvanced )
  50.         *ppInterface = ( IWMReaderCallbackAdvanced* )this;
  51.     else
  52.         return E_NOINTERFACE;
  53.     return S_OK;
  54. }
  55.  
  56. //------------------------------------------------------------------------//
  57. ULONG WMACallback::AddRef()
  58. {
  59.     return 1;
  60. }
  61.  
  62. //------------------------------------------------------------------------//
  63. ULONG WMACallback::Release()
  64. {
  65.     return 1;
  66. }
  67.  
  68. //------------------------------------------------------------------------//
  69. HRESULT WMACallback::OnStatus(
  70.     WMT_STATUS  Status,
  71.     HRESULT  hr,
  72.     WMT_ATTR_DATATYPE  dwType,
  73.     BYTE*  pValue,
  74.     void*  pvContext)
  75. {
  76.     if(!pvContext)
  77.         return E_FAIL;
  78.     WMA* pWMA = static_cast<WMA*>(pvContext);
  79.     return pWMA->OnStatus(Status, hr, dwType, pValue);
  80. }
  81.  
  82. //------------------------------------------------------------------------//
  83. HRESULT WMACallback::OnSample(
  84.     DWORD  dwOutputNum,
  85.     QWORD  cnsSampleTime,
  86.     QWORD  cnsSampleDuration,
  87.     DWORD  dwFlags,
  88.     INSSBuffer*  pSample,
  89.     void*  pvContext)
  90. {
  91.     if(!pvContext)
  92.         return E_FAIL;
  93.     WMA* pWMA = static_cast<WMA*>(pvContext);
  94.     return pWMA->OnSample(dwOutputNum, cnsSampleTime, cnsSampleDuration, dwFlags, pSample);
  95. }
  96.  
  97. //------------------------------------------------------------------------//
  98. HRESULT WMACallback::OnStreamSample( 
  99.     WORD wStreamNum,
  100.     QWORD cnsSampleTime,
  101.     QWORD cnsSampleDuration,
  102.     DWORD dwFlags,
  103.     INSSBuffer __RPC_FAR *pSample,
  104.     void __RPC_FAR *pvContext)
  105. {
  106.     return E_NOTIMPL;
  107. }
  108.  
  109. //------------------------------------------------------------------------//
  110. HRESULT WMACallback::OnTime( 
  111.     QWORD qwCurrentTime,
  112.     void __RPC_FAR *pvContext)
  113. {
  114.     if(!pvContext)
  115.         return E_FAIL;
  116.     WMA* pWMA = static_cast<WMA*>(pvContext);
  117.     return pWMA->OnTime(qwCurrentTime);
  118. }
  119.  
  120. //------------------------------------------------------------------------//
  121. HRESULT WMACallback::OnStreamSelection( 
  122.     WORD wStreamCount,
  123.     WORD __RPC_FAR *pStreamNumbers,
  124.     WMT_STREAM_SELECTION __RPC_FAR *pSelections,
  125.     void __RPC_FAR *pvContext)
  126. {
  127.     return S_OK;
  128. }
  129.  
  130. //------------------------------------------------------------------------//
  131. HRESULT WMACallback::OnOutputPropsChanged( 
  132.     DWORD dwOutputNum,
  133.     WM_MEDIA_TYPE __RPC_FAR *pMediaType,
  134.     void __RPC_FAR *pvContext )
  135. {
  136.     return S_OK;
  137. }
  138.  
  139. //------------------------------------------------------------------------//
  140. HRESULT WMACallback::AllocateForOutput( 
  141.     DWORD dwOutputNum,
  142.     DWORD cbBuffer,
  143.     INSSBuffer __RPC_FAR *__RPC_FAR *ppBuffer,
  144.     void __RPC_FAR *pvContext)
  145. {
  146.     return E_NOTIMPL;
  147. }
  148.  
  149. //------------------------------------------------------------------------//
  150. HRESULT WMACallback::AllocateForStream( 
  151.     WORD wStreamNum,
  152.     DWORD cbBuffer,
  153.     INSSBuffer __RPC_FAR *__RPC_FAR *ppBuffer,
  154.     void __RPC_FAR *pvContext)
  155. {
  156.     return E_NOTIMPL;
  157. }
  158.  
  159.  
  160. IMPLEMENT_POOL(WMA);
  161.  
  162.  
  163. //------------------------------------------------------------------------//
  164. WMA::WMA()
  165. {
  166.     FN("WMA::WMA()");
  167.     m_pBuffer = 0;
  168.     m_nBufferSize = 0;
  169.     Clear();
  170. }
  171.  
  172. //------------------------------------------------------------------------//
  173. WMA::~WMA()
  174. {
  175.     FN("WMA::~WMA()");
  176.     Close();
  177.     SAFE_DELETE_ARRAY(m_pBuffer);
  178.     m_nBufferSize = 0;
  179. }
  180.  
  181. //------------------------------------------------------------------------//
  182. void WMA::Clear()
  183. {
  184.     FN("WMA::Clear()");
  185.     m_pReader = 0;
  186.     m_pReaderAdvanced = 0;
  187.     m_pReaderAdvanced2 = 0;
  188.     m_pHeaderInfo = 0;
  189.     ZeroMemory(&m_WaveFormatEx, sizeof(WAVEFORMATEX));
  190.     m_hWaitEvent = 0;
  191.     m_hRespondEvent = 0;
  192.     m_bOpen = false;
  193.     m_Callback.Clear();
  194.     m_hrCallbackResult = 0;
  195.     m_nStreamSize = 0;
  196.     m_nBytesRead = 0;
  197.     m_bFirstRead = true;
  198.     m_nTargetPtr = 0;
  199.     m_nWritePtr = 0;
  200.     m_bEOF = false;
  201.     m_qwTime = 0;
  202.  
  203.     ZeroMemory(&m_csTerm, sizeof(CRITICAL_SECTION));
  204. }
  205.  
  206.  
  207. //------------------------------------------------------------------------//
  208. bool WMA::PreOpen()
  209. {
  210.     InitializeCriticalSection(&m_csTerm);
  211.  
  212.     m_hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  213.     m_hRespondEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  214.  
  215.     HRESULT hr = WMCreateReader(0, 0, &m_pReader);
  216.     if(FAILED(hr))
  217.         return false;
  218.  
  219.     hr = m_pReader->QueryInterface(
  220.         IID_IWMReaderAdvanced, 
  221.         (void**)&m_pReaderAdvanced);
  222.     if(FAILED(hr))
  223.         return false;
  224.  
  225.     hr = m_pReaderAdvanced->QueryInterface(
  226.         IID_IWMReaderAdvanced2, 
  227.         (void**)&m_pReaderAdvanced2);
  228.     if(FAILED(hr))
  229.         return false;
  230.  
  231.     hr = m_pReader->QueryInterface(
  232.         IID_IWMHeaderInfo, 
  233.         (void**)&m_pHeaderInfo);
  234.     if(FAILED(hr))
  235.         return false;
  236.  
  237.     return true;
  238. }
  239.  
  240.  
  241. //------------------------------------------------------------------------//
  242. // This Open function is used if the source is either streaming or a 
  243. // one-shot load.  It also is used for custom file systems.
  244. bool WMA::Open(string sFileName)
  245. {
  246.     FN("WMA::Open()");
  247.  
  248.     if(!PreOpen())
  249.         return false;
  250.     
  251.     IAudioStream* pStream;
  252.     CreateAudioStream cas(pStream);
  253.     if(!pStream)
  254.         return false;
  255.  
  256.     HRESULT hr = pStream->Open(sFileName);
  257.     if(FAILED(hr))
  258.         return false;
  259.  
  260.     hr = m_pReaderAdvanced2->OpenStream(pStream, &m_Callback, this);
  261.     if(FAILED(hr))
  262.         return false;
  263.  
  264.     if(!PostOpen())
  265.         return false;
  266.  
  267.     return true;
  268. }
  269.  
  270. //------------------------------------------------------------------------//
  271. // This Open function is used for loading directly from memory
  272. bool WMA::Open(uint8* pbData, uint32 dwDataSize)
  273. {
  274.     FN("WMA::Open()");
  275.  
  276.     if(!PreOpen())
  277.         return false;
  278.  
  279.     HGLOBAL hMem;
  280.     IStream* pStream;
  281.  
  282.     hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD | GMEM_SHARE, dwDataSize);
  283.  
  284.     LPVOID pMem = GlobalLock(hMem);
  285.     CopyMemory(pMem, pbData, dwDataSize);
  286.     GlobalUnlock(hMem);
  287.  
  288.     HRESULT hr = CreateStreamOnHGlobal(hMem, TRUE, &pStream);
  289.     if(FAILED(hr))
  290.         return false;
  291.     
  292.     hr = m_pReaderAdvanced2->OpenStream(pStream, &m_Callback, this);
  293.     if(FAILED(hr))
  294.         return false;
  295.  
  296.     if(!PostOpen())
  297.         return false;
  298.  
  299.     return true;
  300. }
  301.  
  302.  
  303. //------------------------------------------------------------------------//
  304. bool WMA::PostOpen()
  305. {
  306.     WaitForSingleObject(m_hRespondEvent, INFINITE);
  307.     if(FAILED(m_hrCallbackResult))
  308.         return false;
  309.  
  310.     uint32 nOutputCount;
  311.     HRESULT hr = m_pReader->GetOutputCount(&nOutputCount);
  312.     if(FAILED(hr))
  313.         return false;
  314.     if(nOutputCount != 1)
  315.         return false;
  316.  
  317.     uint32 nOutputFormatCount;
  318.     hr = m_pReader->GetOutputFormatCount(0, &nOutputFormatCount);
  319.     if(FAILED(hr))
  320.         return false;
  321.  
  322.     uint32 nFormatSize = 0;    
  323.     BYTE* pBuf = 0;
  324.     IWMOutputMediaProps* pProps;
  325.     for(uint32 j = 0; j < nOutputFormatCount; j++)
  326.     {
  327.         hr = m_pReader->GetOutputFormat(0, j, &pProps);
  328.         if(FAILED(hr))
  329.             continue;
  330.  
  331.         // Get the required size of the media type structure
  332.         uint32 nNewSize = 0;
  333.         hr = pProps->GetMediaType(NULL, &nNewSize);
  334.         if(FAILED(hr))
  335.             continue;
  336.         if(nNewSize > nFormatSize)
  337.         {
  338.             SAFE_DELETE_ARRAY(pBuf);
  339.             nFormatSize = nNewSize;
  340.             pBuf = new BYTE[nFormatSize];
  341.         }
  342.  
  343.         WM_MEDIA_TYPE* pType = (WM_MEDIA_TYPE*) pBuf;
  344.         hr = pProps->GetMediaType(pType, &nFormatSize);
  345.         if(FAILED(hr))
  346.             continue;
  347.  
  348.         if(pType->formattype == WMFORMAT_WaveFormatEx)
  349.         {
  350.             memcpy(&m_WaveFormatEx, pType->pbFormat, pType->cbFormat);
  351.             if((m_WaveFormatEx.nChannels == 2) &&
  352.                 (m_WaveFormatEx.wBitsPerSample == DXAudioMgr()->GetOptimalSampleBits()) &&
  353.                 (m_WaveFormatEx.nSamplesPerSec == DXAudioMgr()->GetOptimalSampleRate()))
  354.             {
  355.                 break;
  356.             }
  357.         }
  358.         SAFE_RELEASE(pProps);
  359.     }
  360.     SAFE_DELETE_ARRAY(pBuf);
  361.  
  362.     // Now set the format we want
  363.     hr = m_pReader->SetOutputProps(0, pProps);
  364.     if(FAILED(hr))
  365.         return false;
  366.  
  367.     SAFE_RELEASE(pProps);
  368.  
  369.     // Tell the reader to read as fast as possible
  370.     hr = m_pReaderAdvanced->SetUserProvidedClock(true);
  371.     if(FAILED(hr))
  372.         return false;
  373.  
  374.     // Determine the size of the opened file
  375.     WORD wStreamNum = 0;
  376.     WMT_ATTR_DATATYPE Type;
  377.     DWORD dwDuration = 0;
  378.     WORD wLength = 8;
  379.     hr = m_pHeaderInfo->GetAttributeByName(
  380.         &wStreamNum,
  381.         g_wszWMDuration,
  382.         &Type,
  383.         (unsigned char*)&dwDuration,
  384.         &wLength);
  385.     if(FAILED(hr))
  386.         return false;
  387.  
  388.     // divide by 10 million to get seconds
  389.     double fTime = double(dwDuration) / 10000000.0f;
  390.         
  391.     // Calculate the stream size
  392.     m_nStreamSize = fTime * m_WaveFormatEx.nAvgBytesPerSec;
  393.  
  394.     // Create a default one-point-five second scratch buffer for decoding streams
  395.     if(!m_pBuffer)
  396.     {
  397.         m_nBufferSize = m_WaveFormatEx.nAvgBytesPerSec * 1.5;
  398.         m_pBuffer = new uint8[m_nBufferSize];
  399.     }
  400.  
  401.     m_nTargetPtr = 0;
  402.     m_nWritePtr = 0;
  403.  
  404.     m_bOpen = true;
  405.  
  406.     return true;
  407. }
  408.  
  409. //------------------------------------------------------------------------//
  410. bool WMA::Close()
  411. {
  412.     FN("WMA::Close()");
  413.  
  414.     m_bOpen = false;
  415.  
  416.     if(m_hWaitEvent)
  417.     {
  418.         if(m_pReader)
  419.             m_pReader->Stop();
  420.  
  421.         SetEvent(m_hWaitEvent);
  422.         EnterCriticalSection(&m_csTerm);
  423.         LeaveCriticalSection(&m_csTerm);
  424.         DeleteCriticalSection(&m_csTerm);
  425.     }
  426.  
  427.     if(m_hWaitEvent)
  428.     {
  429.         CloseHandle(m_hWaitEvent);
  430.         m_hWaitEvent = 0;
  431.     }
  432.     if(m_hRespondEvent)
  433.     {
  434.         CloseHandle(m_hRespondEvent);
  435.         m_hRespondEvent = 0;
  436.     }
  437.  
  438.     SAFE_RELEASE(m_pHeaderInfo);
  439.     SAFE_RELEASE(m_pReaderAdvanced2);
  440.     SAFE_RELEASE(m_pReaderAdvanced);
  441.     SAFE_RELEASE(m_pReader);
  442.  
  443.     Clear();
  444.  
  445.     return true;
  446. }
  447.  
  448.  
  449. //------------------------------------------------------------------------//
  450. bool WMA::Read(uint8* pBuffer, uint32 dwSizeToRead, uint32* pdwSizeRead )
  451. {
  452.     FN("WMA::Read()");
  453.  
  454.     if(!m_bOpen)
  455.         return false;
  456.     DebugOut(5, "Reading %d bytes from WMA file", dwSizeToRead);
  457.  
  458.     m_nTargetPtr = dwSizeToRead - m_nWritePtr;
  459.  
  460.     // First, we have to check to see if we have enough extra data
  461.     // stored in the buffer to satisfy the read without doing
  462.     // any decoding.
  463.     if(dwSizeToRead > m_nWritePtr)
  464.     {
  465.         if(m_bFirstRead)
  466.         {
  467.             // Grow the decoding buffer if necessary
  468.             if(dwSizeToRead > m_nBufferSize - DECODING_BUFFER_ERROR)
  469.             {
  470.                 SAFE_DELETE(m_pBuffer);
  471.                 m_nBufferSize = dwSizeToRead;
  472.                 m_pBuffer = new uint8[m_nBufferSize + DECODING_BUFFER_ERROR];
  473.             }
  474.  
  475.             // Start decoding now
  476.             HRESULT hr;
  477.             hr = m_pReader->Start(0, 0, 1.0f, this);
  478.             m_bFirstRead = false;
  479.             if(FAILED(hr))
  480.                 return false;
  481.         }
  482.         else
  483.         {
  484.             // Release the decoding thread so decoding continues
  485.             SetEvent(m_hWaitEvent);
  486.         }
  487.  
  488.         WaitForSingleObject(m_hRespondEvent, INFINITE);
  489.         if(FAILED(m_hrCallbackResult))
  490.             return false;
  491.     }
  492.  
  493.     // Normally we should have more than enough data in the buffer...
  494.     if(m_nWritePtr >= dwSizeToRead)
  495.     {
  496.         memcpy(pBuffer, m_pBuffer, dwSizeToRead);
  497.         *pdwSizeRead = dwSizeToRead;
  498.         memmove(m_pBuffer, m_pBuffer + dwSizeToRead, m_nWritePtr - dwSizeToRead);
  499.         m_nWritePtr -= dwSizeToRead;
  500.     }
  501.     // but if we're at the end of the file, we may have less than requested
  502.     else
  503.     {
  504.         memcpy(pBuffer, m_pBuffer, m_nWritePtr);
  505.         *pdwSizeRead = m_nWritePtr;
  506.         m_nWritePtr = 0;
  507.     }
  508.  
  509.     m_nBytesRead += *pdwSizeRead;
  510.  
  511.     if(m_bEOF)
  512.         m_pReader->Stop();
  513.  
  514.     return true;
  515. }
  516.  
  517. //------------------------------------------------------------------------//
  518. uint32 WMA::GetSize()
  519. {
  520.     FN("WMA::GetSize()");
  521.     return m_nStreamSize;
  522. }
  523.  
  524. //------------------------------------------------------------------------//
  525. bool WMA::Reset()
  526. {
  527.     FN("WMA::Reset()");
  528.  
  529.     if(!m_bOpen)
  530.         return false;
  531.  
  532.     m_nBytesRead = 0;
  533.     m_pReader->Stop();
  534.     m_bFirstRead = true;
  535.     m_bEOF = false;
  536.     m_nTargetPtr = 0;
  537.     m_nWritePtr = 0;
  538.     m_qwTime = 0;
  539.     ZeroMemory(m_pBuffer, m_nBufferSize);
  540.     SetEvent(m_hWaitEvent);
  541.  
  542.     return true;
  543. }
  544.  
  545. //------------------------------------------------------------------------//
  546. WAVEFORMATEX* WMA::GetFormat()
  547. {
  548.     FN("WMA::GetFormat()");
  549.     return &m_WaveFormatEx;
  550. }
  551.  
  552. //------------------------------------------------------------------------//
  553. bool WMA::IsEOF()
  554. {
  555.     FN("WMA::IsEOF()");
  556.     return m_bEOF;
  557. }
  558.  
  559. //------------------------------------------------------------------------//
  560. void WMA::Destroy()
  561. {
  562.     Close();
  563.     WMA::DestroyObject(this);
  564. }
  565.  
  566.  
  567. //------------------------------------------------------------------------//
  568. HRESULT WMA::OnStatus(
  569.     WMT_STATUS  Status,
  570.     HRESULT  hr,
  571.     WMT_ATTR_DATATYPE  dwType,
  572.     BYTE*  pValue)
  573. {
  574.  
  575.     m_hrCallbackResult = hr;
  576.     switch(Status)
  577.     {
  578.     case WMT_ERROR:
  579.         SetEvent(m_hWaitEvent);
  580.         SetEvent(m_hRespondEvent);
  581.         DebugOut(1, "Status: WMT_ERROR");
  582.         return E_FAIL;
  583.     case WMT_OPENED:
  584.         DebugOut(5, "Status: WMT_OPENED");
  585.         SetEvent(m_hRespondEvent);
  586.         break;
  587.     case WMT_BUFFERING_START:
  588.         DebugOut(5, "Status: WMT_BUFFERING_START");
  589.         break;
  590.     case WMT_BUFFERING_STOP:
  591.         DebugOut(5, "Status: WMT_BUFFERING_STOP");
  592.         break;
  593.     case WMT_END_OF_FILE:
  594.         DebugOut(5, "Status: WMT_END_OF_FILE");
  595.         m_bEOF = true;
  596.         // Make sure no threads are kept waiting, since no more reads will come
  597.         SetEvent(m_hWaitEvent);
  598.         SetEvent(m_hRespondEvent);
  599.         break;
  600.     case WMT_END_OF_SEGMENT:
  601.         DebugOut(5, "Status: WMT_END_OF_SEGMENT");
  602.         break;
  603.     case WMT_END_OF_STREAMING:
  604.         DebugOut(5, "Status: WMT_END_OF_STREAMING");
  605.         break;
  606.     case WMT_STARTED:
  607.         DebugOut(5, "Status: WMT_STARTED");
  608.         DebugOut(5, "Advancing deliver time at start");
  609.         m_qwTime += 1000000;
  610.         if(m_pReaderAdvanced)
  611.             m_pReaderAdvanced->DeliverTime(m_qwTime);
  612.         break;
  613.     case WMT_STOPPED:
  614.         DebugOut(5, "Status: WMT_STOPPED");
  615.         SetEvent(m_hWaitEvent);
  616.         SetEvent(m_hRespondEvent);
  617.         break;
  618.     case WMT_CLOSED:
  619.         DebugOut(5, "Status: WMT_CLOSED");
  620.         break;
  621.     case WMT_TIMER:
  622.         DebugOut(5, "Status: WMT_TIMER");
  623.         break;
  624.     case WMT_SOURCE_SWITCH:
  625.         DebugOut(5, "Status: WMT_SOURCE_SWITCH");
  626.         break;
  627.  
  628.     };
  629.  
  630.     return S_OK;
  631. }
  632.  
  633.  
  634. //------------------------------------------------------------------------//
  635. HRESULT WMA::OnTime( 
  636.     QWORD qwCurrentTime)
  637. {
  638.  
  639.     // Keep asking for the specific duration of the stream till EOF
  640.     if ( !m_bEOF )
  641.     {
  642.         DebugOut(5, "Advancing deliver time in OnTime() function");
  643.         m_qwTime += 1000000;
  644.  
  645.         if(m_pReaderAdvanced)
  646.             m_pReaderAdvanced->DeliverTime( m_qwTime );
  647.     }
  648.  
  649.     return S_OK;
  650. }
  651.  
  652.  
  653. //------------------------------------------------------------------------//
  654. HRESULT WMA::OnSample(
  655.     DWORD  dwOutputNum,
  656.     QWORD  cnsSampleTime,
  657.     QWORD  cnsSampleDuration,
  658.     DWORD  dwFlags,
  659.     INSSBuffer*  pSample)
  660. {
  661.  
  662.     if(!m_bOpen)
  663.     {
  664.         if(m_hRespondEvent)
  665.             SetEvent(m_hRespondEvent);
  666.         return S_OK;
  667.     }
  668.  
  669.     if(m_bEOF)
  670.     {
  671.         SetEvent(m_hRespondEvent);
  672.         return S_OK;
  673.     }
  674.  
  675.     BYTE* pBuf;
  676.     DWORD dwLen;
  677.     if(!pSample)
  678.         return E_FAIL;
  679.  
  680.     HRESULT hr = pSample->GetBuffer(&pBuf);
  681.     if(FAILED(hr))
  682.         return E_FAIL;
  683.     hr = pSample->GetLength(&dwLen);
  684.     if(FAILED(hr))
  685.         return E_FAIL;
  686.  
  687.     // Expand the decoding buffer if needed
  688.     if((m_nWritePtr + dwLen) > m_nBufferSize)
  689.     {
  690.         uint32 nNewBufferSize = m_nWritePtr + dwLen + DECODING_BUFFER_ERROR;
  691.         DebugOut(1, "Expanding buffer from length %d to %d", m_nBufferSize, nNewBufferSize);
  692.         uint8* pNewBuffer = new uint8[nNewBufferSize];
  693.         memcpy(pNewBuffer, m_pBuffer, m_nWritePtr);
  694.         SAFE_DELETE_ARRAY(m_pBuffer);
  695.         m_pBuffer = pNewBuffer;
  696.         m_nBufferSize = nNewBufferSize;
  697.     }
  698.  
  699.     memcpy(m_pBuffer + m_nWritePtr, pBuf, dwLen);
  700.     m_nWritePtr += dwLen;
  701.  
  702.     if(m_nWritePtr >= m_nTargetPtr)
  703.     {
  704.         SetEvent(m_hRespondEvent);
  705.         CRITICAL_FUNCTION(&m_csTerm);
  706.         WaitForSingleObject(m_hWaitEvent, INFINITE);
  707.     }
  708.  
  709.     return S_OK;
  710. }
  711.  
  712.  
  713. #endif // USE_WMA
  714.  
  715.