WAVEIO.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:

Windows编程

开发平台:

Visual C++

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