VocPlay.cpp
上传用户:zctools
上传日期:2013-04-03
资源大小:26k
文件大小:5k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include <mmsystem.h>         // waveOutxxx
  3. #include <io.h>               // fileLength
  4. #include "VocPlay.h"
  5. CVocPlayer::CVocPlayer()
  6.            :pData(NULL), hWaveOut(0), boPlaying(false)
  7. {
  8. }
  9. CVocPlayer::~CVocPlayer()
  10. {
  11.    if ( boPlaying )
  12.       Clear();
  13. }
  14. void CVocPlayer::Play( const CString &rcFileName, CWnd *pCallbackWnd )
  15. {
  16.    Clear();
  17.    // Decode the file
  18.    FILEINFO sFileInfo;
  19.    Decode( rcFileName, &sFileInfo );
  20.    // Prepare a WAVEFORMATEX required for opening the device driver
  21.    WAVEFORMATEX sWaveFormat;
  22.    sWaveFormat.wFormatTag           = WAVE_FORMAT_PCM;
  23.    sWaveFormat.nChannels            = sFileInfo.ucChannels;
  24.    sWaveFormat.nSamplesPerSec       = sFileInfo.lSamplesPerSeconds;
  25.    sWaveFormat.nAvgBytesPerSec      = sFileInfo.lSamplesPerSeconds;
  26.    sWaveFormat.nBlockAlign          = 1;
  27.    sWaveFormat.wBitsPerSample       = sFileInfo.ucBitsPerSample;
  28.    sWaveFormat.cbSize               = sizeof(WAVEFORMATEX);
  29.    // Try to open the device driver
  30.    MMRESULT Result = waveOutOpen( &hWaveOut, WAVE_MAPPER, &sWaveFormat,
  31.                                   (ULONG)pCallbackWnd->m_hWnd, 0, 
  32.                                   CALLBACK_WINDOW );
  33.    if ( Result != MMSYSERR_NOERROR )
  34.    {
  35.       hWaveOut = 0;
  36.       return;
  37.    }
  38.    // Prepare the header
  39.    sWaveHdr.lpData            = pData;
  40.    sWaveHdr.dwBufferLength    = sFileInfo.lTotalLength;
  41.    sWaveHdr.dwFlags           = 0;
  42.    sWaveHdr.dwLoops           = 0;
  43.    waveOutPrepareHeader( hWaveOut, &sWaveHdr, sizeof(sWaveHdr) );
  44.    // Play the file
  45.    boPlaying = true;
  46.    waveOutWrite( hWaveOut, &sWaveHdr, sizeof(sWaveHdr) );
  47. }
  48. void CVocPlayer::Clear()
  49. {
  50.    if ( !boPlaying )
  51.       return;
  52.    waveOutUnprepareHeader( hWaveOut, &sWaveHdr, sizeof(sWaveHdr) );
  53.    delete [] pData;
  54.    pData = NULL;
  55.    waveOutClose( hWaveOut );
  56.    boPlaying = false;
  57. }
  58. void CVocPlayer::Decode( const CString &rcFileName, FILEINFO *psFileInfo )
  59. {
  60.    // Open the file and allocate the memory
  61.    FILE *pFile = fopen( rcFileName, "rb" );
  62.    long lFileLength = _filelength( _fileno(pFile) );
  63.    pData = new char[ lFileLength ];
  64.    char *pDataPos = pData;
  65.    // Place the file pointer at the beginning of the data
  66.    fseek( pFile, 0x1A, SEEK_SET );
  67.    BYTE bType;
  68.    signed long int lLen;
  69.    do
  70.    {
  71.       // Read the block type
  72.       fread( &bType, sizeof(bType), 1, pFile );
  73.       
  74.       lLen = 0;
  75.       switch( bType )
  76.       {
  77.          case 1:
  78.          {
  79.             fread( &lLen, 3, 1, pFile );
  80.             lLen -= 2;     // Remove Time Constant and File Format bytes
  81.             fread( &psFileInfo->usTimeConstant, 1, 1, pFile );
  82.             fread( &psFileInfo->usFileFormat, 1, 1, pFile );
  83.             // For the moment, it's a plain 8-bit mono file
  84.             psFileInfo->ucBitsPerSample    = 8;
  85.             psFileInfo->ucChannels         = 1;
  86.             psFileInfo->lSamplesPerSeconds = 1000000 /
  87.                                     (256-(psFileInfo->usTimeConstant % 256));
  88.             // Store this sample in memory
  89.             fread( pDataPos, lLen, 1, pFile );
  90.             pDataPos += lLen;
  91.             break;
  92.          }
  93.          case 8:
  94.          {
  95.             fseek( pFile, 3, SEEK_CUR );     // Skip the length
  96.             fread( &psFileInfo->usTimeConstant, 2, 1, pFile );
  97.             fread( &psFileInfo->usFileFormat, 1, 1, pFile );
  98.             fread( &psFileInfo->ucChannels, 1, 1, pFile );
  99.             // Block of type 8 is always followed by a block of type 1
  100.             fread( &bType, sizeof(bType), 1, pFile );
  101.             fread( &lLen, 3, 1, pFile );
  102.             lLen -= 2;     // Remove Time Constant and File Format bytes
  103.             fseek( pFile, 2, SEEK_CUR );     // Skip T.C. and F.F.
  104.             psFileInfo->ucBitsPerSample    = 8;
  105.             psFileInfo->ucChannels++;
  106.             psFileInfo->usTimeConstant >>= 8;
  107.             psFileInfo->lSamplesPerSeconds = 1000000 /
  108.                                     (256-(psFileInfo->usTimeConstant % 256));
  109.             // Store this sample in memory
  110.             fread( pDataPos, lLen, 1, pFile );
  111.             pDataPos += lLen;
  112.             break;
  113.          }
  114.          case 9:
  115.          {
  116.             fread( &lLen, 3, 1, pFile );
  117.             lLen -= 12;
  118.             fread( &psFileInfo->lSamplesPerSeconds, 4, 1, pFile );
  119.             fread( &psFileInfo->ucBitsPerSample, 1, 1, pFile );
  120.             fread( &psFileInfo->ucChannels, 1, 1, pFile );
  121.             fread( &psFileInfo->usFileFormat, 2, 1, pFile );
  122.             // Store this sample in memory
  123.             fread( pDataPos, lLen, 1, pFile );
  124.             pDataPos += lLen;
  125.             break;
  126.          }
  127.       };
  128.    } while ( bType != 0 );
  129.    psFileInfo->lTotalLength = pDataPos-pData;
  130.    fclose( pFile );
  131. }