home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / CDX.ZIP / Src / Cds / WaveFile.cpp < prev   
Encoding:
C/C++ Source or Header  |  1998-09-14  |  6.6 KB  |  273 lines

  1. //////////////////////////////////////////////////////////////////////////////////
  2. // CDS_WaveFile Implementation
  3. //////////////////////////////////////////////////////////////////////////////////
  4. #include "CDS.h"
  5.  
  6. //////////////////////////////////////////////////////////////////////////////////
  7. // Constructor
  8. //////////////////////////////////////////////////////////////////////////////////
  9. CDS_WaveFile::CDS_WaveFile(void)
  10. {
  11.     // Initialise data members
  12.     m_pFormat = NULL;
  13.     m_hmmio = NULL;
  14.     m_nBlockAlign= 0;
  15.     m_nAvgDataRate = 0;
  16.     m_nDataSize = 0;
  17.     m_nBytesPlayed = 0;
  18.     m_nDuration = 0;
  19.     memset(&m_mmckiRiff, 0, sizeof (MMCKINFO));
  20.     memset(&m_mmckiFmt, 0, sizeof (MMCKINFO));
  21.     memset(&m_mmckiData, 0, sizeof (MMCKINFO));
  22. }
  23.  
  24. //////////////////////////////////////////////////////////////////////////////////
  25. // Destructor
  26. //////////////////////////////////////////////////////////////////////////////////
  27. CDS_WaveFile::~CDS_WaveFile(void)
  28. {
  29.     // Free memory
  30.     if(m_pFormat) GlobalFree(m_pFormat);
  31.  
  32.     // Close file
  33.     if(m_hmmio) mmioClose(m_hmmio, 0);
  34. }
  35.  
  36. //////////////////////////////////////////////////////////////////////////////////
  37. // Open
  38. //////////////////////////////////////////////////////////////////////////////////
  39. BOOL CDS_WaveFile::Open(LPSTR pszFilename)
  40. {
  41.     WORD cbExtra = 0;
  42.     BOOL fRtn = TRUE;
  43.  
  44.     // Open the requested file
  45.     if((m_hmmio = mmioOpen(pszFilename, NULL, MMIO_ALLOCBUF | MMIO_READ)) == NULL)
  46.     {
  47.         m_mmr = MMIOERR_CANNOTOPEN;
  48.         goto OPEN_ERROR;
  49.     }
  50.  
  51.     // Descend into initial chunk ('RIFF')
  52.     if(m_mmr = mmioDescend(m_hmmio, &m_mmckiRiff, NULL, 0))
  53.     {
  54.         goto OPEN_ERROR;
  55.     }
  56.  
  57.     // Validate that it's a WAVE file
  58.     if((m_mmckiRiff.ckid != FOURCC_RIFF) || (m_mmckiRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
  59.     {
  60.         m_mmr = MMIOERR_INVALIDFILE;
  61.         goto OPEN_ERROR;
  62.     }
  63.  
  64.     // Find format chunk ('fmt '), allocate and fill WAVEFORMATEX structure
  65.     m_mmckiFmt.ckid = mmioFOURCC('f', 'm', 't', ' ');
  66.     if(m_mmr = mmioDescend(m_hmmio, &m_mmckiFmt, &m_mmckiRiff, MMIO_FINDCHUNK))
  67.     {
  68.         goto OPEN_ERROR;
  69.     }
  70.  
  71.     // Read the format chunk into temporary structure
  72.     PCMWAVEFORMAT pcmwf;
  73.     if(mmioRead (m_hmmio, (CHAR *) &pcmwf, sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
  74.     {
  75.         m_mmr = MMIOERR_CANNOTREAD;
  76.         goto OPEN_ERROR;
  77.     }
  78.  
  79.   // If format is not PCM then there are extra bytes appended to WAVEFORMATEX
  80.     if(pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM)
  81.     {
  82.         // Read WORD specifying number of extra bytes
  83.         if(mmioRead(m_hmmio, (LPSTR) &cbExtra, sizeof (cbExtra)) != sizeof(cbExtra))
  84.         {
  85.             m_mmr = MMIOERR_CANNOTREAD;
  86.             goto OPEN_ERROR;
  87.         }
  88.     }
  89.  
  90.     // Allocate memory for WAVEFORMATEX structure + extra bytes
  91.     if(m_pFormat = (WAVEFORMATEX *) GlobalAlloc(GMEM_FIXED, sizeof(WAVEFORMATEX)+cbExtra))
  92.     {
  93.         // Copy bytes from temporary format structure
  94.         memcpy(m_pFormat, &pcmwf, sizeof(pcmwf));
  95.         m_pFormat->cbSize = cbExtra;
  96.  
  97.         // Read those extra bytes and append to WAVEFORMATEX structure
  98.         if(cbExtra != 0)
  99.         {
  100.             if((m_mmr = mmioRead(m_hmmio, (LPSTR) ((BYTE *)(m_pFormat) + sizeof (WAVEFORMATEX)), cbExtra)) != cbExtra)
  101.             {
  102.                 // Error reading extra bytes
  103.                 m_mmr = MMIOERR_CANNOTREAD;
  104.                 goto OPEN_ERROR;
  105.             }
  106.         }
  107.     }
  108.   else
  109.     {
  110.         // Error allocating memory
  111.         m_mmr = MMIOERR_OUTOFMEMORY;
  112.         goto OPEN_ERROR;
  113.     }
  114.  
  115.     // Init some member data from format chunk
  116.     m_nBlockAlign = m_pFormat->nBlockAlign;
  117.     m_nAvgDataRate = m_pFormat->nAvgBytesPerSec;
  118.  
  119.     // Ascend out of format chunk
  120.     if(m_mmr = mmioAscend(m_hmmio, &m_mmckiFmt, 0))
  121.     {
  122.         goto OPEN_ERROR;
  123.     }
  124.  
  125.     // Cue for streaming
  126.     Cue();
  127.  
  128.     // Init some member data from data chunk
  129.     m_nDataSize = m_mmckiData.cksize;
  130.     m_nDuration = (UINT)(((__int64) m_nDataSize * 1000) / m_nAvgDataRate);
  131.  
  132.     // Successful open!
  133.     goto OPEN_DONE;
  134.     
  135. OPEN_ERROR:
  136.  
  137.     fRtn = FALSE;
  138.     if(m_hmmio)
  139.     {
  140.         // Close file
  141.         mmioClose(m_hmmio, 0);
  142.         m_hmmio = NULL;
  143.     }
  144.     if(m_pFormat)
  145.     {
  146.         // Free memory
  147.         GlobalFree (m_pFormat);
  148.         m_pFormat = NULL;
  149.     }
  150.  
  151. OPEN_DONE:
  152.  
  153.     return fRtn;
  154. }
  155.  
  156. //////////////////////////////////////////////////////////////////////////////////
  157. // Cue
  158. //////////////////////////////////////////////////////////////////////////////////
  159. BOOL CDS_WaveFile::Cue(void)
  160. {
  161.     BOOL fRtn = TRUE;
  162.  
  163.     // Seek to 'data' chunk from beginning of file
  164.     if(mmioSeek (m_hmmio, m_mmckiRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET) != -1)
  165.     {
  166.         // Descend into 'data' chunk
  167.         m_mmckiData.ckid = mmioFOURCC('d', 'a', 't', 'a');
  168.         if((m_mmr = mmioDescend(m_hmmio, &m_mmckiData, &m_mmckiRiff, MMIO_FINDCHUNK)) == MMSYSERR_NOERROR)
  169.         {
  170.             // Reset byte counter
  171.             m_nBytesPlayed = 0;
  172.         }
  173.         else
  174.         {
  175.             fRtn = FALSE;
  176.         }
  177.     }
  178.     else
  179.     {
  180.         // mmioSeek error
  181.         m_mmr = MMIOERR_CANNOTSEEK;
  182.         fRtn = FALSE;
  183.     }
  184.  
  185.     return fRtn;
  186. }
  187.  
  188. //////////////////////////////////////////////////////////////////////////////////
  189. // Read
  190. //////////////////////////////////////////////////////////////////////////////////
  191. UINT CDS_WaveFile::Read(BYTE * pbDest, UINT cbSize)
  192. {
  193.     MMIOINFO mmioinfo;
  194.     UINT cb;
  195.  
  196.     // Use direct buffer access for reads to maximize performance
  197.     if(m_mmr = mmioGetInfo(m_hmmio, &mmioinfo, 0))
  198.     {
  199.         goto READ_ERROR;
  200.     }
  201.  
  202.     // Limit read size to chunk size
  203.     cbSize = (cbSize > m_mmckiData.cksize) ? m_mmckiData.cksize : cbSize;
  204.  
  205.     // Adjust chunk size
  206.     m_mmckiData.cksize -= cbSize;
  207.  
  208.     // Copy bytes from MMIO buffer
  209.     for(cb = 0; cb < cbSize; cb++)
  210.     {
  211.         // Advance buffer if necessary
  212.         if(mmioinfo.pchNext == mmioinfo.pchEndRead)
  213.         {
  214.             if(m_mmr = mmioAdvance(m_hmmio, &mmioinfo, MMIO_READ))
  215.             {
  216.                 goto READ_ERROR;
  217.             }
  218.  
  219.             if(mmioinfo.pchNext == mmioinfo.pchEndRead)
  220.             {
  221.                 m_mmr = MMIOERR_CANNOTREAD;
  222.                 goto READ_ERROR;
  223.             }
  224.         }
  225.  
  226.         // Actual copy
  227.         *(pbDest+cb) = *(mmioinfo.pchNext)++;
  228.     }
  229.  
  230.     // End direct buffer access
  231.     if(m_mmr = mmioSetInfo(m_hmmio, &mmioinfo, 0))
  232.     {
  233.         goto READ_ERROR;
  234.     }
  235.  
  236.     // Successful read keep running total of number of data bytes read
  237.     m_nBytesPlayed += cbSize;
  238.     goto READ_DONE;
  239.  
  240. READ_ERROR:
  241.     cbSize = 0;
  242.  
  243. READ_DONE:
  244.     return cbSize;
  245. }
  246.  
  247. //////////////////////////////////////////////////////////////////////////////////
  248. // GetSilenceData
  249. //////////////////////////////////////////////////////////////////////////////////
  250. BYTE CDS_WaveFile::GetSilenceData(void)
  251. {
  252.     BYTE bSilenceData = 0;
  253.  
  254.     // Silence data depends on format of Wave file
  255.     if(m_pFormat)
  256.     {
  257.         if(m_pFormat->wBitsPerSample == 8)
  258.         {
  259.             // For 8-bit formats (unsigned, 0 to 255)
  260.             // Packed DWORD = 0x80808080;
  261.             bSilenceData = 0x80;
  262.         }
  263.         else if(m_pFormat->wBitsPerSample == 16)
  264.         {
  265.             // For 16-bit formats (signed, -32768 to 32767)
  266.             // Packed DWORD = 0x00000000;
  267.             bSilenceData = 0x00;
  268.         }
  269.     }
  270.  
  271.     return bSilenceData;
  272. }
  273.