home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / IKLOWNS / CGWAVE.CPP < prev    next >
C/C++ Source or Header  |  1996-08-28  |  10KB  |  337 lines

  1. /*===========================================================================*\
  2. |
  3. |  File:        cgwave.cpp
  4. |
  5. |  Description: 
  6. |       
  7. |-----------------------------------------------------------------------------
  8. |
  9. |  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
  10. |
  11. |  Written by Moss Bay Engineering, Inc. under contract to Microsoft Corporation
  12. |
  13. \*===========================================================================*/
  14.  
  15. /**************************************************************************
  16.  
  17.     (C) Copyright 1995-1996 Microsoft Corp.  All rights reserved.
  18.  
  19.     You have a royalty-free right to use, modify, reproduce and 
  20.     distribute the Sample Files (and/or any modified version) in 
  21.     any way you find useful, provided that you agree that 
  22.     Microsoft has no warranty obligations or liability for any 
  23.     Sample Application Files which are modified. 
  24.  
  25.     we do not recomend you base your game on IKlowns, start with one of
  26.     the other simpler sample apps in the GDK
  27.  
  28.  **************************************************************************/
  29.  
  30. //** include files **
  31. #ifndef __WATCOMC__
  32. #define WIN32_LEAN_AND_MEAN
  33. #endif
  34. #include <windows.h>
  35. #include <windowsx.h>
  36. #include "cgwave.h"
  37.  
  38. //** local definitions **
  39. //** external functions **
  40. //** external data **
  41. //** public data **
  42. //** private data **
  43. //** public functions **
  44. //** private functions **
  45.  
  46. // ----------------------------------------------------------
  47. // WaveOpenFile - 
  48. //  This function will open a wave input file and prepare 
  49. //  it for reading, so the data can be easily read with 
  50. //  WaveReadFile. Returns 0 if successful, the error code 
  51. //  if not.
  52. //      pszFileName     - Input filename to load.
  53. //      phmmioIn    - Pointer to handle which will 
  54. //              be used for further mmio routines.
  55. //      ppwfxInfo   - Ptr to ptr to WaveFormatEx 
  56. //              structure with all info about the file.
  57. // ----------------------------------------------------------
  58. int WaveOpenFile(
  59.     char        *pszFileName,
  60.     HMMIO       *phmmioIn,
  61.     WAVEFORMATEX    **ppwfxInfo,
  62.     MMCKINFO    *pckInRIFF
  63. )
  64. {
  65.  
  66.     HMMIO       hmmioIn;
  67.     MMCKINFO    ckIn;       // chunk info. for general use.
  68.     PCMWAVEFORMAT   pcmWaveFormat;  // Temporary PCM format structure to load in.   
  69.     WORD        cbExtraAlloc;   // Extra bytes for waveformatex structure for weird formats.
  70.     int         nError;     // Return value.
  71.  
  72.  
  73.     // Initialization...
  74.     *ppwfxInfo = NULL;
  75.     nError = 0;
  76.     hmmioIn = NULL;
  77.     
  78.     if ((hmmioIn = mmioOpen(pszFileName, NULL, MMIO_ALLOCBUF | MMIO_READ)) == NULL)
  79.     {
  80.         nError = ER_CANNOTOPEN;
  81.         goto ERROR_READING_WAVE;
  82.     }
  83.  
  84.     if ((nError = (int)mmioDescend(hmmioIn, pckInRIFF, NULL, 0)) != 0)
  85.     {
  86.         goto ERROR_READING_WAVE;
  87.     }
  88.  
  89.  
  90.     if ((pckInRIFF->ckid != FOURCC_RIFF) || (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E')))
  91.     {
  92.         nError = ER_NOTWAVEFILE;
  93.         goto ERROR_READING_WAVE;
  94.     }
  95.             
  96.     /* Search the input file for for the 'fmt ' chunk.     */
  97.     ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
  98.     if ((nError = (int)mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK)) != 0)
  99.     {
  100.         goto ERROR_READING_WAVE;        
  101.     }
  102.                     
  103.     /* Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
  104.     * if there are extra parameters at the end, we'll ignore them */
  105.     
  106.     if (ckIn.cksize < (long) sizeof(PCMWAVEFORMAT))
  107.     {
  108.         nError = ER_NOTWAVEFILE;
  109.         goto ERROR_READING_WAVE;
  110.     }
  111.                                                                 
  112.     /* Read the 'fmt ' chunk into <pcmWaveFormat>.*/     
  113.     if (mmioRead(hmmioIn, (HPSTR) &pcmWaveFormat, (long) sizeof(pcmWaveFormat)) != (long) sizeof(pcmWaveFormat))
  114.     {
  115.         nError = ER_CANNOTREAD;
  116.         goto ERROR_READING_WAVE;
  117.     }
  118.                             
  119.  
  120.     // Ok, allocate the waveformatex, but if its not pcm
  121.     // format, read the next word, and thats how many extra
  122.     // bytes to allocate.
  123.     if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM)
  124.         cbExtraAlloc = 0;               
  125.                             
  126.     else
  127.     {
  128.         // Read in length of extra bytes.
  129.         if (mmioRead(hmmioIn, (LPSTR) &cbExtraAlloc,
  130.         (long) sizeof(cbExtraAlloc)) != (long) sizeof(cbExtraAlloc))
  131.         {
  132.             nError = ER_CANNOTREAD;
  133.             goto ERROR_READING_WAVE;
  134.         }
  135.  
  136.     }
  137.                             
  138.     // Ok, now allocate that waveformatex structure.
  139.     if ((*ppwfxInfo = (LPWAVEFORMATEX)GlobalAlloc(GMEM_FIXED
  140.     , sizeof(WAVEFORMATEX)+cbExtraAlloc)) == NULL)
  141.     {
  142.         nError = ER_MEM;
  143.         goto ERROR_READING_WAVE;
  144.     }
  145.  
  146.     // Copy the bytes from the pcm structure to the waveformatex structure
  147.     memcpy(*ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat));
  148.     (*ppwfxInfo)->cbSize = cbExtraAlloc;
  149.  
  150.     // Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
  151.     if (cbExtraAlloc != 0)
  152.     {
  153.         if (mmioRead(hmmioIn, (LPSTR) (((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(cbExtraAlloc)),
  154.         (long) (cbExtraAlloc)) != (long) (cbExtraAlloc))
  155.         {
  156.             nError = ER_NOTWAVEFILE;
  157.             goto ERROR_READING_WAVE;
  158.         }
  159.     }
  160.  
  161.     /* Ascend the input file out of the 'fmt ' chunk. */                                
  162.     if ((nError = mmioAscend(hmmioIn, &ckIn, 0)) != 0)
  163.     {
  164.         goto ERROR_READING_WAVE;
  165.     }
  166.     
  167.  
  168.     goto TEMPCLEANUP;       
  169.  
  170. ERROR_READING_WAVE:
  171.     if (*ppwfxInfo != NULL)
  172.     {
  173.         GlobalFree(*ppwfxInfo);
  174.         *ppwfxInfo = NULL;
  175.     }       
  176.  
  177.     if (hmmioIn != NULL)
  178.         {
  179.             mmioClose(hmmioIn, 0);
  180.         hmmioIn = NULL;
  181.     }
  182.     
  183. TEMPCLEANUP:
  184.     *phmmioIn = hmmioIn;
  185.  
  186.     return(nError);
  187.  
  188. }
  189.  
  190.  
  191. // ----------------------------------------------------------
  192. // WaveStartDataRead - 
  193. //  This routine has to be called before WaveReadFile as 
  194. //  it searchs for the chunk to descend into for reading, 
  195. //  that is, the 'data' chunk.  For simplicity, this used 
  196. //  to be in the open routine, but was taken out and moved 
  197. //  to a separate routine so there was more control on the 
  198. //  chunks that are before the data chunk, such as 'fact', 
  199. //  etc...
  200. // ----------------------------------------------------------
  201. int WaveStartDataRead(
  202.     HMMIO       *phmmioIn,
  203.     MMCKINFO    *pckIn,
  204.     MMCKINFO    *pckInRIFF
  205. )
  206. {
  207.     int nError;
  208.  
  209.     nError = 0;
  210.     
  211.     // Do a nice little seek...
  212.     if ((nError = mmioSeek(*phmmioIn, pckInRIFF->dwDataOffset 
  213.     + sizeof(FOURCC), SEEK_SET)) == -1)
  214.     {
  215.         //Assert(FALSE);
  216.         goto ERROR_READING_WAVE;
  217.     }
  218.  
  219.     nError = 0;
  220.     //  Search the input file for for the 'data' chunk.
  221.     pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a');
  222.     if ((nError = mmioDescend(*phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK)) != 0)
  223.     {
  224.         goto ERROR_READING_WAVE;
  225.     }
  226.  
  227.     goto CLEANUP;
  228.  
  229. ERROR_READING_WAVE:
  230.  
  231. CLEANUP:    
  232.     return(nError);
  233. }
  234.  
  235.  
  236. // ----------------------------------------------------------
  237. // WaveReadFile - 
  238. //  This will read wave data from the wave file.  Make 
  239. //  sure we're descended into the data chunk, else this 
  240. //  will fail bigtime!
  241. //      hmmioIn     - Handle to mmio.
  242. //      cbRead      - # of bytes to read.   
  243. //      pbDest      - Destination buffer to put bytes.
  244. //      cbActualRead    - # of bytes actually read.
  245. // ----------------------------------------------------------
  246. int WaveReadFile(
  247.     HMMIO       hmmioIn,
  248.     UINT        cbRead,
  249.     BYTE        *pbDest,
  250.     MMCKINFO    *pckIn,
  251.     UINT        *cbActualRead
  252. )
  253. {
  254.  
  255.     MMIOINFO    mmioinfoIn;         // current status of <hmmioIn>
  256.     int     nError;
  257.     UINT        cT, cbDataIn;
  258.  
  259.     nError = 0;
  260.  
  261.     if (nError = mmioGetInfo(hmmioIn, &mmioinfoIn, 0) != 0)
  262.     {
  263.         goto ERROR_CANNOT_READ;
  264.     }
  265.                 
  266.     cbDataIn = cbRead;
  267.     if (cbDataIn > pckIn->cksize) 
  268.         cbDataIn = pckIn->cksize;   
  269.  
  270.     pckIn->cksize -= cbDataIn;
  271.     
  272.     for (cT = 0; cT < cbDataIn; cT++)
  273.     {
  274.         /* Copy the bytes from the io to the buffer. */
  275.         if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
  276.         {
  277.             if ((nError = mmioAdvance(hmmioIn, &mmioinfoIn, MMIO_READ)) != 0)
  278.             {
  279.                         goto ERROR_CANNOT_READ;
  280.             } 
  281.             if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
  282.             {
  283.                 nError = ER_CORRUPTWAVEFILE;
  284.                         goto ERROR_CANNOT_READ;
  285.             }
  286.         }
  287.         
  288.         // Actual copy.
  289.         *((BYTE*)pbDest+cT) = *((BYTE*)mmioinfoIn.pchNext++);
  290.     }
  291.  
  292.     if ((nError = mmioSetInfo(hmmioIn, &mmioinfoIn, 0)) != 0)
  293.     {
  294.         goto ERROR_CANNOT_READ;
  295.     }
  296.  
  297.     *cbActualRead = cbDataIn;
  298.     goto FINISHED_READING;
  299.  
  300. ERROR_CANNOT_READ:
  301.     *cbActualRead = 0;
  302.  
  303. FINISHED_READING:
  304.     return(nError);
  305.  
  306. }
  307.  
  308. // ----------------------------------------------------------
  309. // WaveCloseFile - 
  310. //  This will close the wave file openned with WaveOpenFile.  
  311. //      phmmioIn - Pointer to the handle to input MMIO.
  312. //      ppwfxSrc - Pointer to pointer to WaveFormatEx structure.
  313. //
  314. //  Returns 0 if successful, non-zero if there was a warning.
  315. // ----------------------------------------------------------
  316. int WaveCloseReadFile(
  317.     HMMIO       *phmmio,
  318.     WAVEFORMATEX    **ppwfxSrc
  319. )
  320. {
  321.  
  322.     if (*ppwfxSrc != NULL)
  323.     {
  324.         GlobalFree(*ppwfxSrc);
  325.         *ppwfxSrc = NULL;
  326.     }
  327.  
  328.     if (*phmmio != NULL)
  329.     {
  330.         mmioClose(*phmmio, 0);
  331.         *phmmio = NULL;
  332.     }
  333.  
  334.     return(0);
  335.  
  336. }
  337.