CPI_Player_CoDec_WAV.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:9k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "globals.h"
  3. #include "CPI_Player_CoDec.h"
  4. #include "CP_RIFFStructs.h"
  5. #include "CPI_ID3.h"
  6. void CPP_OMWAV_Uninitialise(CPs_CoDecModule* pModule);
  7. BOOL CPP_OMWAV_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner);
  8. void CPP_OMWAV_CloseFile(CPs_CoDecModule* pModule);
  9. void CPP_OMWAV_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator);
  10. void CPP_OMWAV_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo);
  11. //
  12. BOOL CPP_OMWAV_GetPCMBlock(CPs_CoDecModule* pModule, void* pBlock, DWORD* pdwBlockSize);
  13. int CPP_OMWAV_GetCurrentPos_secs(CPs_CoDecModule* pModule);
  14. typedef struct __CPs_CoDec_Wave
  15. {
  16.     HANDLE m_hFile;
  17.     unsigned int m_iStartOfWavData;
  18.     unsigned int m_iLengthOfWavData;
  19.     CPs_FileInfo m_FileInfo;
  20.     int m_iBytesPerSecond;
  21.     int m_iCurrentOffset_Secs;
  22.     int m_iCurrentOffset_Fraction_Bytes;
  23. } CPs_CoDec_Wave;
  24. BOOL SkipToChunk(HANDLE hFile, CPs_RIFFChunk* pChunk, const char cChunkID[4]);
  25. //
  26. void CP_InitialiseCodec_WAV(CPs_CoDecModule* pCoDec)
  27. {
  28.     CPs_CoDec_Wave *pContext;
  29.     pCoDec->Uninitialise = CPP_OMWAV_Uninitialise;
  30.     pCoDec->OpenFile = CPP_OMWAV_OpenFile;
  31.     pCoDec->CloseFile = CPP_OMWAV_CloseFile;
  32.     pCoDec->Seek = CPP_OMWAV_Seek;
  33.     pCoDec->GetFileInfo = CPP_OMWAV_GetFileInfo;
  34.     pCoDec->GetPCMBlock = CPP_OMWAV_GetPCMBlock;
  35.     pCoDec->GetCurrentPos_secs = CPP_OMWAV_GetCurrentPos_secs;
  36.     pCoDec->m_pModuleCookie = malloc(sizeof(CPs_CoDec_Wave));
  37.     pContext = (CPs_CoDec_Wave*)pCoDec->m_pModuleCookie;
  38.     pContext->m_hFile = INVALID_HANDLE_VALUE;
  39.     CPFA_InitialiseFileAssociations(pCoDec);
  40.     CPFA_AddFileAssociation(pCoDec, "WAV", 0L);
  41. }
  42. //
  43. void CPP_OMWAV_Uninitialise(CPs_CoDecModule* pModule)
  44. {
  45.     CPs_CoDec_Wave *pContext = (CPs_CoDec_Wave*)pModule->m_pModuleCookie;
  46.     CP_CHECKOBJECT(pContext);
  47.     CP_ASSERT(pContext->m_hFile == INVALID_HANDLE_VALUE)
  48.     free(pContext);
  49.     CPFA_EmptyFileAssociations(pModule);
  50. }
  51. //
  52. BOOL CPP_OMWAV_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner)
  53. {
  54.     CPs_CoDec_Wave *pContext = (CPs_CoDec_Wave*)pModule->m_pModuleCookie;
  55.     CP_CHECKOBJECT(pContext);
  56.     if(pContext->m_hFile)
  57.     {
  58.         CloseHandle(pContext->m_hFile);
  59.         pContext->m_hFile = INVALID_HANDLE_VALUE;
  60.     }
  61.     CP_TRACE1("Openfile "%s"", pcFilename);
  62.     pContext->m_hFile = CreateFile(pcFilename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
  63.     if(pContext->m_hFile == INVALID_HANDLE_VALUE)
  64.     {
  65.         CP_TRACE0("Failed to open file");
  66.         return FALSE;
  67.     }
  68.     {
  69.         CIs_ID3v2Tag tag;
  70.         DWORD dwBytesRead;
  71.         int iStreamStart = 0;
  72.         memset(&tag, 0, sizeof(tag));
  73.         ReadFile(pContext->m_hFile, &tag, sizeof(tag), &dwBytesRead, NULL);
  74.         if(memcmp(tag.m_cTAG, "ID3", 3) == 0)
  75.         {
  76.             iStreamStart = sizeof(CIs_ID3v2Tag);
  77.             iStreamStart += (tag.m_cSize_Encoded[0] << 21)
  78.                             | (tag.m_cSize_Encoded[1] << 14)
  79.                             | (tag.m_cSize_Encoded[2] << 7)
  80.                             | tag.m_cSize_Encoded[3];
  81.         }
  82.         SetFilePointer(pContext->m_hFile, iStreamStart, NULL, FILE_BEGIN);
  83.     }
  84.     {
  85.         CPs_RIFFHeader RIFFHeader;
  86.         DWORD dwBytesRead;
  87.         ReadFile(pContext->m_hFile, &RIFFHeader, sizeof(RIFFHeader), &dwBytesRead, NULL);
  88.         if(memcmp(RIFFHeader.m_cID, "RIFF", 4) || memcmp(RIFFHeader.m_cFileType, "WAVE", 4))
  89.         {
  90.             CP_TRACE0("File not of RIFF WAVE type");
  91.             CloseHandle(pContext->m_hFile);
  92.             pContext->m_hFile = INVALID_HANDLE_VALUE;
  93.             return FALSE;
  94.         }
  95.     }
  96.     {
  97.         CPs_RIFFChunk chunk;
  98.         PCMWAVEFORMAT* pFormat;
  99.         DWORD dwBytesRead;
  100.         BOOL bSuccess = SkipToChunk(pContext->m_hFile, &chunk, "fmt ");
  101.         if( bSuccess == FALSE || chunk.m_dwLength < sizeof(PCMWAVEFORMAT) )
  102.         {
  103.             CP_TRACE0("Failed to find FMT chunk");
  104.             CloseHandle(pContext->m_hFile);
  105.             pContext->m_hFile = INVALID_HANDLE_VALUE;
  106.             return FALSE;
  107.         }
  108.         pFormat = (PCMWAVEFORMAT*)malloc(chunk.m_dwLength);
  109.         ReadFile(pContext->m_hFile, pFormat, chunk.m_dwLength, &dwBytesRead, NULL);
  110.        
  111.         if(dwBytesRead != chunk.m_dwLength || pFormat->wf.wFormatTag != WAVE_FORMAT_PCM)
  112.         {
  113.             CP_TRACE0("Only PCM data supported!");
  114.             free(pFormat);
  115.             CloseHandle(pContext->m_hFile);
  116.             pContext->m_hFile = INVALID_HANDLE_VALUE;
  117.             return FALSE;
  118.         }
  119.         pContext->m_FileInfo.m_iBitRate_Kbs = 0;
  120.         pContext->m_FileInfo.m_iFreq_Hz = pFormat->wf.nSamplesPerSec;
  121.         pContext->m_FileInfo.m_bStereo = pFormat->wf.nChannels == 2 ? TRUE : FALSE;
  122.         pContext->m_FileInfo.m_b16bit = pFormat->wBitsPerSample == 16 ? TRUE : FALSE;
  123.         pContext->m_iBytesPerSecond = pContext->m_FileInfo.m_iFreq_Hz
  124.                                       * (pContext->m_FileInfo.m_bStereo == TRUE ? 2 : 1)
  125.                                       * (pContext->m_FileInfo.m_b16bit == TRUE ? 2: 1);
  126.         free(pFormat);
  127.     }
  128.     {
  129.         CPs_RIFFChunk chunk;
  130.         BOOL bSuccess = SkipToChunk(pContext->m_hFile, &chunk, "data");
  131.         if( bSuccess == FALSE)
  132.         {
  133.             CP_TRACE0("Failed to find WAVE chunk");
  134.             CloseHandle(pContext->m_hFile);
  135.             pContext->m_hFile = INVALID_HANDLE_VALUE;
  136.             return FALSE;
  137.         }
  138.         pContext->m_iLengthOfWavData = chunk.m_dwLength;
  139.         pContext->m_iStartOfWavData = SetFilePointer(pContext->m_hFile, 0, NULL, FILE_CURRENT);
  140.     }
  141.     pContext->m_FileInfo.m_iFileLength_Secs = pContext->m_iLengthOfWavData / pContext->m_iBytesPerSecond;
  142.     pContext->m_iCurrentOffset_Secs = 0;
  143.     pContext->m_iCurrentOffset_Fraction_Bytes = 0;
  144.     return TRUE;
  145. }
  146. //
  147. void CPP_OMWAV_CloseFile(CPs_CoDecModule* pModule)
  148. {
  149.     CPs_CoDec_Wave *pContext = (CPs_CoDec_Wave*)pModule->m_pModuleCookie;
  150.     CP_CHECKOBJECT(pContext);
  151.     if(pContext->m_hFile != INVALID_HANDLE_VALUE)
  152.     {
  153.         CP_TRACE0("Close WAV file");
  154.         CloseHandle(pContext->m_hFile);
  155.         pContext->m_hFile = INVALID_HANDLE_VALUE;
  156.     }
  157. }
  158. //
  159. BOOL SkipToChunk(HANDLE hFile, CPs_RIFFChunk* pChunk, const char cChunkID[4])
  160. {
  161.     DWORD dwBytesRead;
  162.     while(ReadFile(hFile, pChunk, sizeof(*pChunk), &dwBytesRead, NULL)
  163.             && dwBytesRead == sizeof(*pChunk) )
  164.     {
  165.         if(memcmp(pChunk->m_cID, cChunkID, 4) == 0)
  166.             return TRUE;
  167.         SetFilePointer(hFile, pChunk->m_dwLength, NULL, FILE_CURRENT);
  168.     }
  169.     return FALSE;
  170. }
  171. //
  172. void CPP_OMWAV_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator)
  173. {
  174.     unsigned int iSeekPos;
  175.     div_t progress;
  176.     CPs_CoDec_Wave *pContext = (CPs_CoDec_Wave*)pModule->m_pModuleCookie;
  177.     CP_CHECKOBJECT(pContext);
  178.     iSeekPos = (int)( ((float)iNumerator/(float)iDenominator) * (float)pContext->m_iLengthOfWavData);
  179.     iSeekPos &= ~0x3;
  180.     progress = div(iSeekPos, pContext->m_iBytesPerSecond);
  181.     pContext->m_iCurrentOffset_Secs = progress.quot;
  182.     pContext->m_iCurrentOffset_Fraction_Bytes = progress.rem;
  183.     SetFilePointer(pContext->m_hFile, pContext->m_iStartOfWavData + iSeekPos, NULL, FILE_BEGIN);
  184. }
  185. //
  186. BOOL CPP_OMWAV_GetPCMBlock(CPs_CoDecModule* pModule, void* pBlock, DWORD* pdwBlockSize)
  187. {
  188.     BOOL bSuccess;
  189.     CPs_CoDec_Wave *pContext = (CPs_CoDec_Wave*)pModule->m_pModuleCookie;
  190.     CP_CHECKOBJECT(pContext);
  191.     CP_ASSERT(pContext->m_hFile != INVALID_HANDLE_VALUE);
  192.     bSuccess = ReadFile(pContext->m_hFile, pBlock, *pdwBlockSize, pdwBlockSize, NULL);
  193.     if(bSuccess == FALSE || *pdwBlockSize == 0)
  194.         return FALSE;
  195.     pContext->m_iCurrentOffset_Fraction_Bytes += *pdwBlockSize;
  196.     if(pContext->m_iCurrentOffset_Fraction_Bytes > pContext->m_iBytesPerSecond)
  197.     {
  198.         pContext->m_iCurrentOffset_Secs++;
  199.         pContext->m_iCurrentOffset_Fraction_Bytes -= pContext->m_iBytesPerSecond;
  200.     }
  201.     return TRUE;
  202. }
  203. //
  204. void CPP_OMWAV_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo)
  205. {
  206.     CPs_CoDec_Wave *pContext = (CPs_CoDec_Wave*)pModule->m_pModuleCookie;
  207.     CP_CHECKOBJECT(pContext);
  208.     memcpy(pInfo, &pContext->m_FileInfo, sizeof(*pInfo));
  209. }
  210. //
  211. int CPP_OMWAV_GetCurrentPos_secs(CPs_CoDecModule* pModule)
  212. {
  213.     CPs_CoDec_Wave *pContext = (CPs_CoDec_Wave*)pModule->m_pModuleCookie;
  214.     CP_CHECKOBJECT(pContext);
  215.     return pContext->m_iCurrentOffset_Secs;
  216. }
  217. //