Platform_Win32_Sound_SoundStream_WMM.cpp
Go to the documentation of this file.00001 //*** Platform_Win32_Sound_SoundStream_WMM.cpp *** 00002 00003 #include "Platform_OS.h" 00004 00005 #pragma warning( disable: 4201) 00006 #define WIN32_LEAN_AND_MEAN 00007 #define VC_EXTRALEAN 00008 #include <windows.h> 00009 #include <mmsystem.h> 00010 #include <malloc.h> 00011 #pragma comment (lib, "winmm.lib") 00012 00013 #include "Platform_Win32_Sound_SoundStream_WMM.h" 00014 #include "Platform_Win32_Sound_WMM.h" 00015 #include "Platform_Win32_Sound.h" 00016 00017 00018 00019 //*** waveCriticalSection *** 00020 00021 CRITICAL_SECTION Platform_Win32_Sound_SoundStream_WMM::waveCriticalSection_; 00022 00023 00024 //*** waveOutProc *** 00025 00026 void CALLBACK Platform_Win32_Sound_SoundStream_WMM::waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) 00027 { 00028 // Get the pointer to free block counter 00029 int& firstUsedWaveBlock_=*(reinterpret_cast<int*>(dwInstance)); 00030 00031 // ignore calls that occur due to openining and closing the device. 00032 if (uMsg!=WOM_DONE) 00033 { 00034 return; 00035 } 00036 00037 EnterCriticalSection(&waveCriticalSection_); 00038 firstUsedWaveBlock_++; 00039 firstUsedWaveBlock_%=WaveBlockCount; 00040 LeaveCriticalSection(&waveCriticalSection_); 00041 } 00042 00043 00044 //*** Constructor *** 00045 00046 Platform_Win32_Sound_SoundStream_WMM::Platform_Win32_Sound_SoundStream_WMM(Platform_Win32_Sound_WMM* manager, int channels, int frequency, int bitsPerSample, int size): 00047 manager_(manager), 00048 channels_(channels), 00049 frequency_(frequency), 00050 bitsPerSample_(bitsPerSample), 00051 size_(size), 00052 firstUsedWaveBlock_(0), 00053 lastUsedWaveBlock_(0), 00054 waveBlocksBuffer_(0), 00055 soundBuffer_(0), 00056 soundPosition_(0), 00057 waveBlocks_(0), 00058 playing_(false) 00059 { 00060 InitializeCriticalSection(&waveCriticalSection_); 00061 00062 soundBuffer_=malloc(size); 00063 00064 // Allocate blocks 00065 waveBlocks_=new WAVEHDR[WaveBlockCount]; 00066 waveBlocksBuffer_=malloc(WaveBlockSize*WaveBlockCount); 00067 for (int i=0; i<WaveBlockCount; i++) 00068 { 00069 memset(&waveBlocks_[i],0,sizeof(waveBlocks_[i])); 00070 waveBlocks_[i].dwBufferLength=WaveBlockSize; 00071 waveBlocks_[i].lpData=static_cast<char*>(waveBlocksBuffer_)+WaveBlockSize*i; 00072 } 00073 00074 00075 // Set up wave format structure. 00076 WAVEFORMATEX format; 00077 memset(&format, 0, sizeof(WAVEFORMATEX)); 00078 format.wFormatTag=WAVE_FORMAT_PCM; 00079 format.nChannels=(WORD)channels; 00080 format.nSamplesPerSec=(DWORD)frequency; 00081 format.nBlockAlign=(WORD)((channels*bitsPerSample)/8); 00082 format.nAvgBytesPerSec=(DWORD)(frequency * format.nBlockAlign); 00083 format.wBitsPerSample=(WORD)bitsPerSample; 00084 format.cbSize=0; 00085 00086 // try to open the default wave device. WAVE_MAPPER is 00087 // a constant defined in mmsystem.h, it always points to the 00088 // default wave device on the system (some people have 2 or 00089 // more sound cards). 00090 MMRESULT result=waveOutOpen(&hWaveOut_, WAVE_MAPPER, &format, (DWORD_PTR)waveOutProc, (DWORD_PTR)&firstUsedWaveBlock_, CALLBACK_FUNCTION); 00091 if(result!=MMSYSERR_NOERROR) 00092 { 00093 Platform::GetPlatform_OS()->OutputDebugText("Couldn't open wave device\n"); 00094 } 00095 } 00096 00097 00098 //*** Destructor *** 00099 00100 Platform_Win32_Sound_SoundStream_WMM::~Platform_Win32_Sound_SoundStream_WMM() 00101 { 00102 Stop(); 00103 DeleteCriticalSection(&waveCriticalSection_); 00104 00105 waveOutClose(hWaveOut_); 00106 free(waveBlocksBuffer_); 00107 delete[] waveBlocks_; 00108 free(soundBuffer_); 00109 manager_->SoundStreamDestroyed(this); 00110 } 00111 00112 00113 void Platform_Win32_Sound_SoundStream_WMM::Play() 00114 { 00115 if (playing_) 00116 { 00117 return; 00118 } 00119 for (int i=0; i<WaveBlockCount; i++) 00120 { 00121 if(waveBlocks_[i].dwFlags & WHDR_PREPARED) 00122 { 00123 waveOutUnprepareHeader(hWaveOut_, &waveBlocks_[i], sizeof(WAVEHDR)); 00124 } 00125 int bytesToWrite=WaveBlockSize-(int)(waveBlocks_[i].dwUser); 00126 int remainder=0; 00127 if (soundPosition_+bytesToWrite>size_) 00128 { 00129 int roomLeft=size_-soundPosition_; 00130 remainder=bytesToWrite-roomLeft; 00131 bytesToWrite=roomLeft; 00132 } 00133 memcpy(waveBlocks_[i].lpData+waveBlocks_[i].dwUser, static_cast<char*>(soundBuffer_)+soundPosition_,bytesToWrite); 00134 soundPosition_+=bytesToWrite; 00135 soundPosition_%=size_; 00136 if (remainder>0) 00137 { 00138 memcpy(waveBlocks_[i].lpData+waveBlocks_[i].dwUser+bytesToWrite, static_cast<char*>(soundBuffer_)+soundPosition_,remainder); 00139 soundPosition_+=remainder; 00140 soundPosition_%=size_; 00141 } 00142 waveBlocks_[i].dwBufferLength = WaveBlockSize; 00143 waveOutPrepareHeader(hWaveOut_, &waveBlocks_[i], sizeof(WAVEHDR)); 00144 waveOutWrite(hWaveOut_, &waveBlocks_[i], sizeof(WAVEHDR)); 00145 00146 EnterCriticalSection(&waveCriticalSection_); 00147 firstUsedWaveBlock_=0; 00148 LeaveCriticalSection(&waveCriticalSection_); 00149 lastUsedWaveBlock_=WaveBlockCount-1; 00150 } 00151 playing_=true; 00152 } 00153 00154 00155 //*** Stop *** 00156 00157 void Platform_Win32_Sound_SoundStream_WMM::Stop() 00158 { 00159 if (!playing_) 00160 { 00161 return; 00162 } 00163 00164 00165 // Wait for all blocks to finish 00166 bool done=false; 00167 while (!done) 00168 { 00169 done=true; 00170 for (int i=0; i<WaveBlockCount; i++) 00171 { 00172 if(waveBlocks_[i].dwFlags!=0 /* or it doesn't work with no sound card */ && !(waveBlocks_[i].dwFlags & WHDR_DONE)) 00173 { 00174 done=false; 00175 break; 00176 } 00177 } 00178 if (!done) 00179 { 00180 Sleep(0); 00181 } 00182 } 00183 00184 for (int i=0; i<WaveBlockCount; i++) 00185 { 00186 if(waveBlocks_[i].dwFlags & WHDR_PREPARED) 00187 { 00188 waveOutUnprepareHeader(hWaveOut_, &waveBlocks_[i], sizeof(WAVEHDR)); 00189 } 00190 } 00191 playing_=false; 00192 } 00193 00194 00195 //*** GetPosition *** 00196 00197 int Platform_Win32_Sound_SoundStream_WMM::GetPosition() 00198 { 00199 return soundPosition_; 00200 } 00201 00202 00203 //*** SetPosition *** 00204 00205 void Platform_Win32_Sound_SoundStream_WMM::SetPosition(int position) 00206 { 00207 soundPosition_=position; 00208 } 00209 00210 00211 //*** CopySoundToBuffer *** 00212 00213 void Platform_Win32_Sound_SoundStream_WMM::CopySoundToBuffer(int bufferOffset, const void* soundData, int bytesToCopy) 00214 { 00215 memcpy(static_cast<unsigned char*>(soundBuffer_)+bufferOffset,soundData,bytesToCopy); 00216 } 00217 00218 00219 //*** Update *** 00220 00221 void Platform_Win32_Sound_SoundStream_WMM::Update() 00222 { 00223 if (!playing_) 00224 { 00225 return; 00226 } 00227 00228 // If all block are done, it means we've lost the buffers and need to refill from start 00229 bool allDone=true; 00230 for (int i=0; i<WaveBlockCount; i++) 00231 { 00232 if(!(waveBlocks_[i].dwFlags & WHDR_DONE)) 00233 { 00234 allDone=false; 00235 break; 00236 } 00237 } 00238 if (allDone) 00239 { 00240 Stop(); 00241 Play(); 00242 return; 00243 } 00244 00245 // If we haven't yet played half of the queued blocks, we don't do anything yet 00246 int lastBlockCorrected=lastUsedWaveBlock_%WaveBlockCount; 00247 if (lastBlockCorrected<firstUsedWaveBlock_) 00248 { 00249 lastBlockCorrected=(WaveBlockCount+lastBlockCorrected); 00250 } 00251 00252 if ((lastBlockCorrected-firstUsedWaveBlock_+1)<WaveBlockCount) 00253 { 00254 lastUsedWaveBlock_=(lastUsedWaveBlock_+1)%WaveBlockCount; 00255 if(waveBlocks_[lastUsedWaveBlock_].dwFlags & WHDR_PREPARED) 00256 { 00257 waveOutUnprepareHeader(hWaveOut_, &waveBlocks_[lastUsedWaveBlock_], sizeof(WAVEHDR)); 00258 } 00259 00260 int bytesToWrite=WaveBlockSize-((int)waveBlocks_[lastUsedWaveBlock_].dwUser); 00261 int remainder=0; 00262 if (soundPosition_+bytesToWrite>size_) 00263 { 00264 int roomLeft=size_-soundPosition_; 00265 remainder=bytesToWrite-roomLeft; 00266 bytesToWrite=roomLeft; 00267 } 00268 memcpy(waveBlocks_[lastUsedWaveBlock_].lpData+waveBlocks_[lastUsedWaveBlock_].dwUser, static_cast<char*>(soundBuffer_)+soundPosition_,bytesToWrite); 00269 soundPosition_+=bytesToWrite; 00270 soundPosition_%=size_; 00271 if (remainder>0) 00272 { 00273 memcpy(waveBlocks_[lastUsedWaveBlock_].lpData+waveBlocks_[lastUsedWaveBlock_].dwUser+bytesToWrite, static_cast<char*>(soundBuffer_)+soundPosition_,remainder); 00274 soundPosition_+=remainder; 00275 soundPosition_%=size_; 00276 } 00277 waveBlocks_[lastUsedWaveBlock_].dwBufferLength = WaveBlockSize; 00278 waveOutPrepareHeader(hWaveOut_, &waveBlocks_[lastUsedWaveBlock_], sizeof(WAVEHDR)); 00279 waveOutWrite(hWaveOut_, &waveBlocks_[lastUsedWaveBlock_], sizeof(WAVEHDR)); 00280 } 00281 00282 } 00283 00284 00285 //*** ClearBuffer *** 00286 00287 void Platform_Win32_Sound_SoundStream_WMM::ClearBuffer(int bufferOffset, int bytesToClear) 00288 { 00289 memset(soundBuffer_,0,size_); 00290 } 00291 00292 00293 //*** GetChannels *** 00294 00295 int Platform_Win32_Sound_SoundStream_WMM::GetChannels() 00296 { 00297 return channels_; 00298 } 00299 00300 00301 //*** GetFrequency *** 00302 00303 int Platform_Win32_Sound_SoundStream_WMM::GetFrequency() 00304 { 00305 return frequency_; 00306 } 00307 00308 00309 //*** GetBitsPerSample *** 00310 00311 int Platform_Win32_Sound_SoundStream_WMM::GetBitsPerSample() 00312 { 00313 return bitsPerSample_; 00314 } 00315 00316 00317 //*** GetSize *** 00318 00319 int Platform_Win32_Sound_SoundStream_WMM::GetSize() 00320 { 00321 return size_; 00322 } 00323 00324 00325 //*** SetVolume *** 00326 00327 void Platform_Win32_Sound_SoundStream_WMM::SetVolume(float level) 00328 { 00329 00330 } 00331 00332 00333 //*** GetVolume *** 00334 00335 float Platform_Win32_Sound_SoundStream_WMM::GetVolume() 00336 { 00337 return 1.0f; 00338 }
Reproduction/republishing of any material on this site without permission is strictly prohibited.
