home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / acmapp / waveio.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  10KB  |  353 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. //  waveio.c
  13. //
  14. //  Description:
  15. //      Contains routines for opening and closing RIFF WAVE files.
  16. //
  17. //
  18. //==========================================================================;
  19.  
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include <mmsystem.h>
  23. #include <mmreg.h>
  24. #include <memory.h>
  25.  
  26. #include "appport.h"
  27. #include "waveio.h"
  28.  
  29. #include "debug.h"
  30.  
  31.  
  32. //--------------------------------------------------------------------------;
  33. //  
  34. //  WIOERR wioFileClose
  35. //  
  36. //  Description:
  37. //  
  38. //  
  39. //  Arguments:
  40. //      LPWAVEIOCB pwio:
  41. //  
  42. //      DWORD fdwClose:
  43. //  
  44. //  Return (WIOERR):
  45. //  
  46. //--------------------------------------------------------------------------;
  47.  
  48. WIOERR WIOAPI wioFileClose
  49. (
  50.     LPWAVEIOCB      pwio,
  51.     DWORD           fdwClose
  52. )
  53. {
  54.     //
  55.     //  validate a couple of things...
  56.     //
  57.     if (NULL == pwio)
  58.         return (WIOERR_BADPARAM);
  59.  
  60.  
  61.     //
  62.     //  get rid of stuff...
  63.     //
  64. //  wioStopWave(pwio);
  65.     
  66.     if (NULL != pwio->hmmio)
  67.     {
  68.         mmioClose(pwio->hmmio, 0);
  69.     }
  70.     
  71. //  FreeWaveHeaders(lpwio);
  72.  
  73. #if 0
  74.     if (pwio->pInfo)
  75.         riffFreeINFO(&(lpwio->pInfo));
  76.     
  77.     if (pwio->pDisp)
  78.         riffFreeDISP(&(lpwio->pDisp));
  79. #endif
  80.  
  81.     if (NULL != pwio->pwfx)
  82.         GlobalFreePtr(pwio->pwfx);
  83.  
  84.     _fmemset(pwio, 0, sizeof(*pwio));
  85.  
  86.     return (WIOERR_NOERROR);
  87. } // wioFileClose()
  88.  
  89.  
  90. //--------------------------------------------------------------------------;
  91. //  
  92. //  WIOERR wioFileOpen
  93. //  
  94. //  Description:
  95. //  
  96. //  
  97. //  Arguments:
  98. //      LPWAVEIOCB pwio:
  99. //  
  100. //      LPCTSTR pszFilePath:
  101. //  
  102. //      DWORD fdwOpen:
  103. //  
  104. //  Return (WIOERR):
  105. //  
  106. //  
  107. //--------------------------------------------------------------------------;
  108.  
  109. WIOERR WIOAPI wioFileOpen
  110. (
  111.     LPWAVEIOCB      pwio,
  112.     LPCTSTR         pszFilePath,
  113.     DWORD           fdwOpen
  114. )
  115. {
  116.     UINT        u;
  117.     TCHAR       ach[255];
  118.     WIOERR      werr;
  119.     HMMIO       hmmio;
  120.     MMCKINFO    ckRIFF;
  121.     MMCKINFO    ck;
  122.     DWORD       dw;
  123.  
  124.     //
  125.     //  validate a couple of things...
  126.     //
  127.     if (NULL == pwio)
  128.         return (WIOERR_BADPARAM);
  129.  
  130.     //
  131.     //  default our error return (assume the worst)
  132.     //
  133.     _fmemset(pwio, 0, sizeof(*pwio));
  134.     werr = WIOERR_FILEERROR;
  135.  
  136.     pwio->dwFlags   = fdwOpen;
  137.  
  138.     //
  139.     //  first try to open the file, etc.. open the given file for reading
  140.     //  using buffered I/O
  141.     //
  142.     hmmio = mmioOpen((LPTSTR)pszFilePath, NULL, MMIO_READ | MMIO_ALLOCBUF);
  143.     if (NULL == hmmio)
  144.         goto wio_Open_Error;
  145.  
  146.     pwio->hmmio     = hmmio;
  147.  
  148.  
  149.     //
  150.     //  locate a 'WAVE' form type...
  151.     //
  152.     ckRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  153.     if (mmioDescend(hmmio, &ckRIFF, NULL, MMIO_FINDRIFF))
  154.         goto wio_Open_Error;
  155.  
  156.     //
  157.     //  we found a WAVE chunk--now go through and get all subchunks that
  158.     //  we know how to deal with...
  159.     //
  160.     pwio->dwDataSamples = (DWORD)-1L;
  161.  
  162. #if 0
  163.     if (lrt=riffInitINFO(&wio.pInfo))
  164.     {
  165.         lr=lrt;
  166.         goto wio_Open_Error;
  167.     }
  168. #endif
  169.  
  170.     //
  171.     //
  172.     //
  173.     while (MMSYSERR_NOERROR == mmioDescend(hmmio, &ck, &ckRIFF, 0))
  174.     {
  175.         //
  176.         //  quickly check for corrupt RIFF file--don't ascend past end!
  177.         //
  178.         if ((ck.dwDataOffset + ck.cksize) > (ckRIFF.dwDataOffset + ckRIFF.cksize))
  179.         {
  180.             DPF(1, "wioFileOpen() FILE MIGHT BE CORRUPT!");
  181.             DPF(1, "    ckRIFF.dwDataOffset: %lu", ckRIFF.dwDataOffset);
  182.             DPF(1, "          ckRIFF.cksize: %lu", ckRIFF.cksize);
  183.             DPF(1, "        ck.dwDataOffset: %lu", ck.dwDataOffset);
  184.             DPF(1, "              ck.cksize: %lu", ck.cksize);
  185.  
  186.             wsprintf(ach, TEXT("This wave file might be corrupt. The RIFF chunk.ckid '%.08lX' (data offset at %lu) specifies a cksize of %lu that extends beyond what the RIFF header cksize of %lu allows. Attempt to load?"),
  187.                      ck.ckid, ck.dwDataOffset, ck.cksize, ckRIFF.cksize);
  188.             u = MessageBox(NULL, ach, TEXT("wioFileOpen"),
  189.                            MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL);
  190.             if (IDNO == u)
  191.             {
  192.                 werr = WIOERR_BADFILE;
  193.                 goto wio_Open_Error;
  194.             }
  195.         }
  196.  
  197.         switch (ck.ckid)
  198.         {
  199.             case mmioFOURCC('L', 'I', 'S', 'T'):
  200.                 if (ck.fccType == mmioFOURCC('I', 'N', 'F', 'O'))
  201.                 {
  202. #if 0
  203.                     if(lrt=riffReadINFO(hmmio, &ck, wio.pInfo))
  204.                     {
  205.                         lr=lrt;
  206.                         goto wio_Open_Error;
  207.                     }
  208. #endif
  209.                 }
  210.                 break;
  211.                 
  212.             case mmioFOURCC('D', 'I', 'S', 'P'):
  213. #if 0
  214.                 riffReadDISP(hmmio, &ck, &(wio.pDisp));
  215. #endif
  216.                 break;
  217.                 
  218.             case mmioFOURCC('f', 'm', 't', ' '):
  219.                 //
  220.                 //  !?! another format chunk !?!
  221.                 //
  222.                 if (NULL != pwio->pwfx)
  223.                     break;
  224.  
  225.                 //
  226.                 //  get size of the format chunk, allocate and lock memory
  227.                 //  for it. we always alloc a complete extended format header
  228.                 //  (even for PCM headers that do not have the cbSize field
  229.                 //  defined--we just set it to zero).
  230.                 //
  231.                 dw = ck.cksize;
  232.                 if (dw < sizeof(WAVEFORMATEX))
  233.                     dw = sizeof(WAVEFORMATEX);
  234.  
  235.                 pwio->pwfx = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, dw);
  236.                 if (NULL == pwio->pwfx)
  237.                 {
  238.                     werr = WIOERR_NOMEM;
  239.                     goto wio_Open_Error;
  240.                 }
  241.  
  242.                 //
  243.                 //  read the format chunk
  244.                 //
  245.                 werr = WIOERR_FILEERROR;
  246.                 dw = ck.cksize;
  247.                 if (mmioRead(hmmio, (HPSTR)pwio->pwfx, dw) != (LONG)dw)
  248.                     goto wio_Open_Error;
  249.                 break;
  250.  
  251.  
  252.             case mmioFOURCC('d', 'a', 't', 'a'):
  253.                 //
  254.                 //  !?! multiple data chunks !?!
  255.                 //
  256.                 if (0L != pwio->dwDataBytes)
  257.                     break;
  258.  
  259.                 //
  260.                 //  just hang on to the total length in bytes of this data
  261.                 //  chunk.. and the offset to the start of the data
  262.                 //
  263.                 pwio->dwDataBytes  = ck.cksize;
  264.                 pwio->dwDataOffset = ck.dwDataOffset;
  265.                 break;
  266.  
  267.  
  268.             case mmioFOURCC('f', 'a', 'c', 't'):
  269.                 //
  270.                 //  !?! multiple fact chunks !?!
  271.                 //
  272.                 if (-1L != pwio->dwDataSamples)
  273.                     break;
  274.  
  275.                 //
  276.                 //  read the first dword in the fact chunk--it's the only
  277.                 //  info we need (and is currently the only info defined for
  278.                 //  the fact chunk...)
  279.                 //
  280.                 //  if this fails, dwDataSamples will remain -1 so we will
  281.                 //  deal with it later...
  282.                 //
  283.                 mmioRead(hmmio, (HPSTR)&pwio->dwDataSamples, sizeof(DWORD));
  284.                 break;
  285.         }
  286.  
  287.         //
  288.         //  step up to prepare for next chunk..
  289.         //
  290.         mmioAscend(hmmio, &ck, 0);
  291.     }
  292.  
  293.     //
  294.     //  if no fmt chunk was found, then die!
  295.     //
  296.     if (NULL == pwio->pwfx)
  297.     {
  298.         werr = WIOERR_ERROR;
  299.         goto wio_Open_Error;
  300.     }
  301.  
  302.     //
  303.     //  all wave files other than PCM are _REQUIRED_ to have a fact chunk
  304.     //  telling the number of samples that are contained in the file. it
  305.     //  is optional for PCM (and if not present, we compute it here).
  306.     //
  307.     //  if the file is not PCM and the fact chunk is not found, then fail!
  308.     //
  309.     if (-1L == pwio->dwDataSamples)
  310.     {
  311.         if (WAVE_FORMAT_PCM == pwio->pwfx->wFormatTag)
  312.         {
  313.             pwio->dwDataSamples = pwio->dwDataBytes / pwio->pwfx->nBlockAlign;
  314.         }
  315.         else
  316.         {
  317.             //
  318.             //  !!! HACK HACK HACK !!!
  319.             //
  320.             //  although this should be considered an invalid wave file, we
  321.             //  will bring up a message box describing the error--hopefully
  322.             //  people will start realizing that something is missing???
  323.             //
  324.             u = MessageBox(NULL, TEXT("This wave file does not have a 'fact' chunk and requires one! This is completely invalid and MUST be fixed! Attempt to load it anyway?"),
  325.                             TEXT("wioFileOpen"), MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL);
  326.             if (IDNO == u)
  327.             {
  328.                 werr = WIOERR_BADFILE;
  329.                 goto wio_Open_Error;
  330.             }
  331.  
  332.             //
  333.             //  !!! need to hack stuff in here !!!
  334.             //
  335.             pwio->dwDataSamples = 0L;
  336.         }
  337.     }
  338.  
  339.     //
  340.     //  cool! no problems.. 
  341.     //
  342.     return (WIOERR_NOERROR);
  343.  
  344.  
  345.     //
  346.     //  return error (after minor cleanup)
  347.     //
  348. wio_Open_Error:
  349.  
  350.     wioFileClose(pwio, 0L);
  351.     return (werr);
  352. } // wioFileOpen()
  353.