CPI_Player_Output_DirectSound.c
上传用户:hxb_1234
上传日期:2010-03-30
资源大小:8328k
文件大小:16k
源码类别:

VC书籍

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "globals.h"
  3. #include "CPI_Player.h"
  4. #include "CPI_Player_CoDec.h"
  5. #include "CPI_Player_Output.h"
  6. #include "CPI_Equaliser.h"
  7. #define DIRECTSOUND_VERSION 0x0500  
  8. #include <dsound.h> 
  9. #include <math.h> 
  10. #define CPC_OUTPUTBLOCKSIZE 0x10000 
  11. #define CPC_MAXFILLAMOUNT (CPC_OUTPUTBLOCKSIZE>>4) 
  12. #define CPC_INVALIDCURSORPOS 0xFFFFFFFF
  13. typedef struct __CPs_OutputContext_DirectSound
  14. {
  15.     LPDIRECTSOUNDBUFFER lpDSB;
  16.     LPDIRECTSOUND lpDirectSound;
  17.     WAVEFORMATEX WaveFile;
  18.     DWORD m_WriteCursor;
  19.     BOOL m_TermState_Wrapped;
  20.     DWORD m_TermState_WriteCursor;
  21.     DWORD m_TermState_HighestPlayPos;
  22.     DWORD m_TimerId;
  23.     BOOL m_bStreamRunning;
  24.     CPs_EqualiserModule* m_pEqualiser;
  25.     BYTE* m_pShadowBuffer;
  26. } CPs_OutputContext_DirectSound;
  27. //
  28. void CPP_OMDS_Initialise(CPs_OutputModule* pModule, const CPs_FileInfo* pFileInfo, CP_HEQUALISER hEqualiser);
  29. void CPP_OMDS_Uninitialise(CPs_OutputModule* pModule);
  30. void CPP_OMDS_RefillBuffers(CPs_OutputModule* pModule);
  31. void CPP_OMDS_SetPause(CPs_OutputModule* pModule, const BOOL bPause);
  32. BOOL CPP_OMDS_IsOutputComplete(CPs_OutputModule* pModule);
  33. void CPP_OMDS_Flush(CPs_OutputModule* pModule);
  34. void CPP_OMDS_SetVolume(CPs_OutputModule* pModule, int iVolume);
  35. void CPP_OMDS_GetVolume(CPs_OutputModule* pModule, int *iVolume, HANDLE waitevent);
  36. void CPP_OMDS_EnablePlay(CPs_OutputModule* pModule, const BOOL bEnable);
  37. void CPP_OMDS_OnEQChanged(CPs_OutputModule* pModule);
  38. void CPP_OMDS_SetInternalVolume(CPs_OutputModule* pModule, const int iNewVolume);
  39. ////////////////////////////////////////////////////////////////////////////////
  40. void CPI_Player_Output_Initialise_DirectSound(CPs_OutputModule* pModule)
  41. {
  42.     pModule->Initialise = CPP_OMDS_Initialise;
  43.     pModule->Uninitialise = CPP_OMDS_Uninitialise;
  44.     pModule->RefillBuffers = CPP_OMDS_RefillBuffers;
  45.     pModule->SetPause = CPP_OMDS_SetPause;
  46.     pModule->IsOutputComplete = CPP_OMDS_IsOutputComplete;
  47.     pModule->Flush = CPP_OMDS_Flush;
  48.     pModule->OnEQChanged = CPP_OMDS_OnEQChanged;
  49.     pModule->SetInternalVolume = CPP_OMDS_SetInternalVolume;
  50.     pModule->m_pModuleCookie = NULL;
  51.     pModule->m_pcModuleName = "DirectSound Plugout";
  52.     pModule->m_pCoDec = NULL;
  53.     pModule->m_pEqualiser = NULL;
  54. }
  55. //
  56. void CPP_OMDS_Initialise(CPs_OutputModule* pModule, const CPs_FileInfo* pFileInfo, CP_HEQUALISER hEqualiser)
  57. {
  58.     
  59.     DSBUFFERDESC dsbd;
  60.     HRESULT hrRetVal;
  61.     CPs_OutputContext_DirectSound* pContext;
  62.     CP_ASSERT(pModule->m_pModuleCookie == NULL);
  63.     pContext = (CPs_OutputContext_DirectSound*)malloc(sizeof(CPs_OutputContext_DirectSound));
  64.     pModule->m_pModuleCookie = pContext;
  65.     CP_TRACE0("DirectSound initialising");
  66.     pModule->m_evtBlockFree = CreateEvent(NULL, FALSE, FALSE, NULL);
  67.     if(DirectSoundCreate(NULL,&(pContext->lpDirectSound), NULL))
  68.     {
  69.         CP_FAIL("Cannot create DirectSound Object");
  70.     }
  71.     if(IDirectSound_SetCooperativeLevel(pContext->lpDirectSound, windows.wnd_main, DSSCL_NORMAL))
  72.     {
  73.         CPP_OMDS_Uninitialise(pModule);
  74.         CP_FAIL("Can't set DirectSound Cooperative level");
  75.     }
  76.     if(!pContext->lpDirectSound)
  77.     {
  78.         CPP_OMDS_Uninitialise(pModule);
  79.         CP_FAIL("Unable to initialise DirectSound");
  80.     }
  81.     pContext->WaveFile.wFormatTag = WAVE_FORMAT_PCM;
  82.     pContext->WaveFile.nChannels = pFileInfo->m_bStereo ? 2 : 1;
  83.     pContext->WaveFile.nSamplesPerSec = pFileInfo->m_iFreq_Hz;
  84.     pContext->WaveFile.wBitsPerSample = pFileInfo->m_b16bit ? 16 : 8;
  85.     pContext->WaveFile.nBlockAlign = (pContext->WaveFile.nChannels * pContext->WaveFile.wBitsPerSample)>>3;
  86.     pContext->WaveFile.nAvgBytesPerSec = pContext->WaveFile.nSamplesPerSec * pContext->WaveFile.nBlockAlign;
  87.     pContext->WaveFile.cbSize = 0;
  88.     memset(&dsbd, 0, sizeof(DSBUFFERDESC));
  89.     dsbd.dwSize = sizeof(DSBUFFERDESC);
  90.     dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME;
  91.     dsbd.dwBufferBytes = CPC_OUTPUTBLOCKSIZE;
  92.     dsbd.lpwfxFormat = &pContext->WaveFile;
  93.     hrRetVal = IDirectSound_CreateSoundBuffer(pContext->lpDirectSound,
  94.                &dsbd,
  95.                &(pContext->lpDSB),
  96.                NULL);
  97.     if(FAILED(hrRetVal))
  98.     {
  99.         pContext->lpDSB = NULL;
  100.         CP_FAIL("Cannot create soundbuffer");
  101.     }
  102.     {
  103.         BYTE *pbData = NULL;
  104.         DWORD dwLength;
  105.         IDirectSoundBuffer_Lock(pContext->lpDSB,
  106.                                 0,
  107.                                 CPC_OUTPUTBLOCKSIZE,
  108.                                 &pbData,
  109.                                 &dwLength,
  110.                                 NULL,
  111.                                 NULL,
  112.                                 0);
  113.         if(pbData)
  114.             memset(pbData, 0, dwLength);
  115.         IDirectSoundBuffer_Unlock(pContext->lpDSB,
  116.                                   pbData,
  117.                                   dwLength,
  118.                                   NULL,
  119.                                   0L);
  120.     }
  121.     pContext->m_WriteCursor = CPC_INVALIDCURSORPOS;
  122.     pContext->m_TermState_Wrapped = FALSE;
  123.     pContext->m_TermState_WriteCursor = CPC_INVALIDCURSORPOS;
  124.     pContext->m_TermState_HighestPlayPos = CPC_INVALIDCURSORPOS;
  125.     pContext->m_TimerId = 0;
  126.     pContext->m_bStreamRunning = FALSE;
  127.     pContext->m_pShadowBuffer = (BYTE*)malloc(CPC_OUTPUTBLOCKSIZE);
  128.     memset(pContext->m_pShadowBuffer, 0, CPC_OUTPUTBLOCKSIZE);
  129.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  130.     pModule->m_pEqualiser = hEqualiser;
  131. }
  132. //
  133. void CPP_OMDS_Uninitialise(CPs_OutputModule* pModule)
  134. {
  135.     CPs_OutputContext_DirectSound* pContext = (CPs_OutputContext_DirectSound*)pModule->m_pModuleCookie;
  136.     CP_CHECKOBJECT(pContext);
  137.     CP_TRACE0("DirectSound shutting down");
  138.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  139.     if(pContext->lpDSB)
  140.     {
  141.         IDirectSoundBuffer_Release(pContext->lpDSB);
  142.     }
  143.     if(pContext->lpDirectSound)
  144.     {
  145.         IDirectSound_Release(pContext->lpDirectSound);
  146.         DeleteObject(pModule->m_evtBlockFree);
  147.     }
  148.     if(pContext->m_TimerId)
  149.     {
  150.         timeKillEvent(pContext->m_TimerId);
  151.         pContext->m_TimerId = 0;
  152.     }
  153.     pContext->lpDirectSound=NULL;
  154.     pContext->lpDSB=NULL;
  155.     free(pContext->m_pShadowBuffer);
  156.     free(pContext);
  157.     pContext=NULL;
  158.     pModule->m_pModuleCookie = NULL;
  159. }
  160. void GetPlayPosAndInvalidLength(CPs_OutputContext_DirectSound* pContext, DWORD* pdwPlayPos, DWORD* pdwLength)
  161. {
  162.     HRESULT hrResult;
  163.     hrResult = IDirectSoundBuffer_GetCurrentPosition(pContext->lpDSB, pdwPlayPos, NULL);
  164.     if(FAILED(hrResult))
  165.         CP_TRACE0("Failed call to IDirectSoundBuffer_GetCurrentPosition");
  166.     if(pContext->m_WriteCursor != CPC_INVALIDCURSORPOS)
  167.     {
  168.         if(pContext->m_WriteCursor >= *pdwPlayPos)
  169.             *pdwLength = (CPC_OUTPUTBLOCKSIZE - pContext->m_WriteCursor) + *pdwPlayPos;
  170.         else
  171.             *pdwLength = *pdwPlayPos - pContext->m_WriteCursor;
  172.     }
  173.     else
  174.     {
  175.         pContext->m_WriteCursor = 0;
  176.         *pdwLength = CPC_OUTPUTBLOCKSIZE;
  177.     }
  178. }
  179. //
  180. void CPP_OMDS_RefillBuffers(CPs_OutputModule* pModule)
  181. {
  182.     HRESULT hrRetVal;
  183.     BYTE *pbData;
  184.     DWORD dwLength=0;
  185.     BOOL bMoreData=TRUE;
  186.     DWORD RealLength;
  187.     DWORD dwAmountToFill, dwCurrentPlayCursor;
  188.     CPs_OutputContext_DirectSound* pContext = (CPs_OutputContext_DirectSound*)pModule->m_pModuleCookie;
  189.     CP_CHECKOBJECT(pContext);
  190.     if(!pContext->lpDirectSound)
  191.         return;
  192.     GetPlayPosAndInvalidLength(pContext, &dwCurrentPlayCursor, &dwAmountToFill);
  193.     
  194.     if(dwAmountToFill > CPC_MAXFILLAMOUNT && pContext->m_bStreamRunning == FALSE)
  195.         dwAmountToFill = CPC_MAXFILLAMOUNT;
  196.     
  197.     if(dwAmountToFill > 0)
  198.     {
  199.         hrRetVal = IDirectSoundBuffer_Lock(pContext->lpDSB,
  200.                                            0,
  201.                                            CPC_OUTPUTBLOCKSIZE,
  202.                                            &pbData,
  203.                                            &dwLength,
  204.                                            NULL,
  205.                                            NULL,
  206.                                            0);
  207.         if(FAILED(hrRetVal))
  208.         {
  209.             CPP_OMDS_Uninitialise(pModule);
  210.             CP_FAIL("Cannot lock soundbuffer");
  211.         }
  212.         if( (pContext->m_WriteCursor + dwAmountToFill) >= CPC_OUTPUTBLOCKSIZE)
  213.             RealLength = CPC_OUTPUTBLOCKSIZE - pContext->m_WriteCursor;
  214.         else
  215.             RealLength = dwAmountToFill;
  216.         if(RealLength)
  217.         {
  218.             bMoreData = pModule->m_pCoDec->GetPCMBlock(pModule->m_pCoDec, pContext->m_pShadowBuffer + pContext->m_WriteCursor, &RealLength);
  219.             memcpy(pbData + pContext->m_WriteCursor, pContext->m_pShadowBuffer + pContext->m_WriteCursor, RealLength);
  220.         }
  221.         {
  222.             CPs_EqualiserModule* pEQModule = (CPs_EqualiserModule*)pModule->m_pEqualiser;
  223.             if(RealLength)
  224.                 pEQModule->ApplyEQToBlock_Inplace(pEQModule, pbData + pContext->m_WriteCursor, RealLength);
  225.         }
  226.         pContext->m_WriteCursor += RealLength;
  227.         if(pContext->m_WriteCursor >= CPC_OUTPUTBLOCKSIZE)
  228.             pContext->m_WriteCursor -= CPC_OUTPUTBLOCKSIZE;
  229.         hrRetVal = IDirectSoundBuffer_Unlock(pContext->lpDSB,
  230.                                              pbData,
  231.                                              dwLength,
  232.                                              NULL,
  233.                                              0L);
  234.         if(FAILED(hrRetVal))
  235.         {
  236.             CPP_OMDS_Uninitialise(pModule);
  237.             CP_FAIL("Cannot Unlock soundbuffer");
  238.         }
  239.     }
  240.     if(bMoreData == FALSE)
  241.     {
  242.         CP_TRACE0("Stream exhausted");
  243.         pModule->m_pCoDec->CloseFile(pModule->m_pCoDec);
  244.         pModule->m_pCoDec = NULL;
  245.     }
  246.     pContext->m_TermState_Wrapped = FALSE;
  247.     pContext->m_TermState_WriteCursor = CPC_INVALIDCURSORPOS;
  248.     pContext->m_TermState_HighestPlayPos = CPC_INVALIDCURSORPOS;
  249.     if(!pContext->m_bStreamRunning)
  250.         CPP_OMDS_EnablePlay(pModule, TRUE);
  251. }
  252. //
  253. void CPP_OMDS_SetPause(CPs_OutputModule* pModule, const BOOL bPause)
  254. {
  255.     CPs_OutputContext_DirectSound* pContext = (CPs_OutputContext_DirectSound*)pModule->m_pModuleCookie;
  256.     CP_CHECKOBJECT(pContext);
  257.     if(!pContext->lpDirectSound)
  258.         return;
  259.     CPP_OMDS_EnablePlay(pModule, !bPause);
  260. }
  261. //
  262. BOOL CPP_OMDS_IsOutputComplete(CPs_OutputModule* pModule)
  263. {
  264.     CPs_OutputContext_DirectSound* pContext = (CPs_OutputContext_DirectSound*)pModule->m_pModuleCookie;
  265.     DWORD dwCurrentPlayCursor, dwInvalidLength;
  266.     CP_CHECKOBJECT(pContext);
  267.     if(!pContext->lpDirectSound)
  268.         return TRUE;
  269.     if(pContext->m_WriteCursor == CPC_INVALIDCURSORPOS)
  270.         return TRUE;
  271.     if(pContext->m_TermState_WriteCursor == CPC_INVALIDCURSORPOS)
  272.         pContext->m_TermState_WriteCursor = pContext->m_WriteCursor;
  273.     if(pModule->m_pCoDec)
  274.         return FALSE;
  275.     GetPlayPosAndInvalidLength(pContext, &dwCurrentPlayCursor, &dwInvalidLength);
  276.     if(dwInvalidLength > 0)
  277.     {
  278.         BYTE *pbData = NULL;
  279.         DWORD dwLength=0;
  280.         IDirectSoundBuffer_Lock(pContext->lpDSB,
  281.                                 pContext->m_WriteCursor,
  282.                                 dwInvalidLength,
  283.                                 &pbData,
  284.                                 &dwLength,
  285.                                 NULL,
  286.                                 NULL,
  287.                                 0);
  288.         if(pbData)
  289.             memset(pbData, 0, dwLength);
  290.         IDirectSoundBuffer_Unlock(pContext->lpDSB,
  291.                                   pbData,
  292.                                   dwLength,
  293.                                   NULL,
  294.                                   0L);
  295.         pContext->m_WriteCursor += dwInvalidLength;
  296.         if(pContext->m_WriteCursor >= CPC_OUTPUTBLOCKSIZE)
  297.             pContext->m_WriteCursor -= CPC_OUTPUTBLOCKSIZE;
  298.     }
  299.     if(pContext->m_TermState_HighestPlayPos == CPC_INVALIDCURSORPOS || pContext->m_TermState_HighestPlayPos < dwCurrentPlayCursor)
  300.         pContext->m_TermState_HighestPlayPos = dwCurrentPlayCursor;
  301.     else
  302.         pContext->m_TermState_Wrapped = TRUE;
  303.     if(pContext->m_TermState_Wrapped == FALSE)
  304.         return FALSE;
  305.     if(dwCurrentPlayCursor > pContext->m_TermState_WriteCursor)
  306.         return TRUE;
  307.     return FALSE;
  308. }
  309. //
  310. void CPP_OMDS_Flush(CPs_OutputModule* pModule)
  311. {
  312.     DWORD dwCurrentPlayCursor;
  313.     CPs_OutputContext_DirectSound* pContext = (CPs_OutputContext_DirectSound*)pModule->m_pModuleCookie;
  314.     CP_CHECKOBJECT(pContext);
  315.     if(!pContext->lpDirectSound)
  316.         return;
  317.     CPP_OMDS_EnablePlay(pModule, FALSE);
  318.     IDirectSoundBuffer_GetCurrentPosition(pContext->lpDSB, &dwCurrentPlayCursor, NULL);
  319.     pContext->m_WriteCursor = dwCurrentPlayCursor;
  320. }
  321. //
  322. void CPP_OMDS_EnablePlay(CPs_OutputModule* pModule, const BOOL bEnable)
  323. {
  324.     CPs_OutputContext_DirectSound* pContext = (CPs_OutputContext_DirectSound*)pModule->m_pModuleCookie;
  325.     CP_CHECKOBJECT(pContext);
  326.     pContext->m_bStreamRunning = bEnable;
  327.     if(bEnable)
  328.     {
  329.         IDirectSoundBuffer_Play(pContext->lpDSB,0,0,DSBPLAY_LOOPING);
  330.         if(pContext->m_TimerId == 0)
  331.         {
  332.             pContext->m_TimerId = timeSetEvent(20,
  333.                                                10,
  334.                                                (LPTIMECALLBACK)pModule->m_evtBlockFree,
  335.                                                0,
  336.                                                TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
  337.         }
  338.     }
  339.     else
  340.     {
  341.         IDirectSoundBuffer_Stop(pContext->lpDSB);
  342.         timeKillEvent(pContext->m_TimerId);
  343.         pContext->m_TimerId = 0;
  344.     }
  345. }
  346. //
  347. void CPP_OMDS_OnEQChanged(CPs_OutputModule* pModule)
  348. {
  349.     CPs_OutputContext_DirectSound* pContext = (CPs_OutputContext_DirectSound*)pModule->m_pModuleCookie;
  350.     BYTE *pbData = NULL;
  351.     DWORD dwLength=0;
  352. //    DWORD dwPlayPos;
  353. //    CPs_EqualiserModule* pEQModule;
  354.     CP_CHECKOBJECT(pContext);
  355.   /*  
  356.     IDirectSoundBuffer_GetCurrentPosition(pContext->lpDSB, &dwPlayPos, NULL);
  357.     IDirectSoundBuffer_Lock(pContext->lpDSB,
  358.                             0,
  359.                             CPC_OUTPUTBLOCKSIZE,
  360.                             &pbData,
  361.                             &dwLength,
  362.                             NULL,
  363.                             NULL,
  364.                             0);
  365.     if(pbData)
  366.         memcpy(pbData, pContext->m_pShadowBuffer, dwLength);
  367.    
  368.     pEQModule = (CPs_EqualiserModule*)pModule->m_pEqualiser;
  369.     if(pContext->m_WriteCursor > dwPlayPos)
  370.     {
  371.         
  372.         if(pContext->m_WriteCursor != CPC_INVALIDCURSORPOS)
  373.             pEQModule->ApplyEQToBlock_Inplace(pEQModule, pbData + dwPlayPos, pContext->m_WriteCursor - dwPlayPos);
  374.     }
  375.     else
  376.     {
  377.        
  378.      
  379.         pEQModule->ApplyEQToBlock_Inplace(pEQModule, pbData + dwPlayPos, CPC_OUTPUTBLOCKSIZE - dwPlayPos);
  380.         pEQModule->ApplyEQToBlock_Inplace(pEQModule, pbData, pContext->m_WriteCursor);
  381.     }
  382.     IDirectSoundBuffer_Unlock(pContext->lpDSB,
  383.                               pbData,
  384.                               dwLength,
  385.                               NULL,
  386.                               0L);
  387.   */
  388. }
  389. void CPP_OMDS_SetInternalVolume(CPs_OutputModule* pModule, const int iNewVolume)
  390. {
  391.     CPs_OutputContext_DirectSound* pContext = (CPs_OutputContext_DirectSound*)pModule->m_pModuleCookie;
  392.     LONG lVolume;
  393.     CP_CHECKOBJECT(pContext);
  394.     lVolume = (int)( pow((double)(100-iNewVolume)*0.01, 3) * (double)DSBVOLUME_MIN);  //((100-iNewVolume) * DSBVOLUME_MIN) / 500;
  395.     IDirectSoundBuffer_SetVolume(pContext->lpDSB, lVolume);
  396. }