wave_out.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:7k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* Copyright (c) 2002, John Edwards
  2.    Redistribution and use in source and binary forms, with or without
  3.    modification, are permitted provided that the following conditions
  4.    are met:
  5.    - Redistributions of source code must retain the above copyright
  6.    notice, this list of conditions and the following disclaimer.
  7.    - Redistributions in binary form must reproduce the above copyright
  8.    notice, this list of conditions and the following disclaimer in the
  9.    documentation and/or other materials provided with the distribution.
  10.    - Neither the name of the Xiph.org Foundation nor the names of its
  11.    contributors may be used to endorse or promote products derived from
  12.    this software without specific prior written permission.
  13.    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  14.    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  15.    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  16.    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
  17.    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18.    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19.    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20.    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  21.    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  22.    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23.    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifdef HAVE_CONFIG_H
  26. # include "config.h"
  27. #endif
  28. /* Set TABS = 4 */
  29. /********************************************************************
  30.  function: To provide playback of 16 bit PCM wave data in Win32
  31.            environments from decoded compressed files.
  32.  ********************************************************************/
  33. #if defined WIN32 || defined _WIN32
  34. #include <string.h>
  35. #include <errno.h>
  36. #include "wave_out.h"
  37. #define MAXWAVESIZE     4294967040LU
  38. #define MAX_WAVEBLOCKS    32
  39. // This is modified for USE_WIN_AUDIO - ONLY 2002-02-27
  40. static CRITICAL_SECTION  cs;
  41. static HWAVEOUT          dev                    = NULL;
  42. static int               ScheduledBlocks        = 0;
  43. static int               PlayedWaveHeadersCount = 0;          // free index
  44. static WAVEHDR*          PlayedWaveHeaders [MAX_WAVEBLOCKS];
  45. static int
  46. Box ( const char* msg )
  47. {
  48. MessageBox ( NULL, msg, " "VERSION_STRING": Error Message . . .", MB_OK | MB_ICONEXCLAMATION );
  49. return -1;
  50. }
  51. /*
  52.  *  This function registers already played WAVE chunks. Freeing is done by free_memory(),
  53.  */
  54. static void CALLBACK
  55. wave_callback ( HWAVE hWave, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
  56. {
  57. if ( uMsg == WOM_DONE ) {
  58. EnterCriticalSection ( &cs );
  59. PlayedWaveHeaders [PlayedWaveHeadersCount++] = (WAVEHDR*) dwParam1;
  60. LeaveCriticalSection ( &cs );
  61. }
  62. }
  63. static void
  64. free_memory ( void )
  65. {
  66. WAVEHDR*  wh;
  67. HGLOBAL   hg;
  68. EnterCriticalSection ( &cs );
  69. wh = PlayedWaveHeaders [--PlayedWaveHeadersCount];
  70. ScheduledBlocks--;                               // decrease the number of USED blocks
  71. LeaveCriticalSection ( &cs );
  72. waveOutUnprepareHeader ( dev, wh, sizeof (WAVEHDR) );
  73. hg = GlobalHandle ( wh -> lpData );       // Deallocate the buffer memory
  74. GlobalUnlock (hg);
  75. GlobalFree   (hg);
  76. hg = GlobalHandle ( wh );                 // Deallocate the header memory
  77. GlobalUnlock (hg);
  78. GlobalFree   (hg);
  79. }
  80. Int
  81. Set_WIN_Params ( FILE_T   dummyFile ,
  82.                  Ldouble  SampleFreq,
  83.                  Uint     BitsPerSample,
  84.                  Uint     Channels )
  85. {
  86. WAVEFORMATEX  outFormat;
  87. UINT          deviceID = WAVE_MAPPER;
  88. (void) dummyFile;
  89. if ( waveOutGetNumDevs () == 0 )
  90. return Box ( "No audio device present." );
  91. outFormat.wFormatTag      = WAVE_FORMAT_PCM;
  92. outFormat.wBitsPerSample  = BitsPerSample;
  93. outFormat.nChannels       = Channels;
  94. outFormat.nSamplesPerSec  = (unsigned long)(SampleFreq + 0.5);
  95. outFormat.nBlockAlign     = (outFormat.wBitsPerSample + 7) / 8 * outFormat.nChannels;
  96. outFormat.nAvgBytesPerSec = outFormat.nSamplesPerSec * outFormat.nBlockAlign;
  97. switch ( waveOutOpen ( &dev, deviceID, &outFormat, (DWORD)wave_callback, 0, CALLBACK_FUNCTION ) )
  98. {
  99. case MMSYSERR_ALLOCATED:   return Box ( "Device is already open." );
  100. case MMSYSERR_BADDEVICEID: return Box ( "The specified device is out of range." );
  101. case MMSYSERR_NODRIVER:    return Box ( "There is no audio driver in this system." );
  102. case MMSYSERR_NOMEM:       return Box ( "Unable to allocate sound memory." );
  103. case WAVERR_BADFORMAT:     return Box ( "This audio format is not supported." );
  104. case WAVERR_SYNC:          return Box ( "The device is synchronous." );
  105. default:                   return Box ( "Unknown media error." );
  106. case MMSYSERR_NOERROR:     break;
  107. }
  108. waveOutReset ( dev );
  109. InitializeCriticalSection ( &cs );
  110. SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS );
  111. return 0;
  112. }
  113. int
  114. WIN_Play_Samples ( const void* data, size_t len )
  115. {
  116. HGLOBAL    hg;
  117. HGLOBAL    hg2;
  118. LPWAVEHDR  wh;
  119. void*      allocptr;
  120. do {
  121. while ( PlayedWaveHeadersCount > 0 )                // free used blocks ...
  122. free_memory ();
  123. if ( ScheduledBlocks < sizeof(PlayedWaveHeaders)/sizeof(*PlayedWaveHeaders) ) // wait for a free block ...
  124. break;
  125. Sleep (26);
  126. } while (1);
  127. if ( (hg2 = GlobalAlloc ( GMEM_MOVEABLE, len )) == NULL )   // allocate some memory for a copy of the buffer
  128. return Box ( "GlobalAlloc failed." );
  129. allocptr = GlobalLock (hg2);
  130. CopyMemory ( allocptr, data, len );                         // Here we can call any modification output functions we want....
  131. if ( (hg = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (WAVEHDR))) == NULL ) // now make a header and WRITE IT!
  132. return -1;
  133. wh                   = GlobalLock (hg);
  134. wh -> dwBufferLength = len;
  135. wh -> lpData         = allocptr;
  136. if ( waveOutPrepareHeader ( dev, wh, sizeof (WAVEHDR)) != MMSYSERR_NOERROR ) {
  137. GlobalUnlock (hg);
  138. GlobalFree   (hg);
  139. return -1;
  140. }
  141. if ( waveOutWrite ( dev, wh, sizeof (WAVEHDR)) != MMSYSERR_NOERROR ) {
  142. GlobalUnlock (hg);
  143. GlobalFree   (hg);
  144. return -1;
  145. }
  146. EnterCriticalSection ( &cs );
  147. ScheduledBlocks++;
  148. LeaveCriticalSection ( &cs );
  149. return len;
  150. }
  151. int
  152. WIN_Audio_close ( void )
  153. {
  154. if ( dev != NULL ) {
  155. while ( ScheduledBlocks > 0 ) {
  156. Sleep (ScheduledBlocks);
  157. while ( PlayedWaveHeadersCount > 0 )         // free used blocks ...
  158. free_memory ();
  159. }
  160. waveOutReset (dev);      // reset the device
  161. waveOutClose (dev);      // close the device
  162. dev = NULL;
  163. }
  164. DeleteCriticalSection ( &cs );
  165. ScheduledBlocks = 0;
  166. return 0;
  167. }
  168. #endif
  169. /* end of wave_out.c */