diff options
author | Richard Linden <none@none> | 2010-04-27 15:50:51 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2010-04-27 15:50:51 -0700 |
commit | 48b3ac20d99e842b6d7adba63e9fa75a7d5cd82c (patch) | |
tree | 2fffd34981dad24e4387f4b0032998bfdf30d193 | |
parent | 5d690aadfcfd7e3981a57614d8720a8d35bed150 (diff) |
added some documentation to winmm_shim
-rw-r--r-- | indra/media_plugins/winmmshim/forwarding_api.cpp | 6 | ||||
-rw-r--r-- | indra/media_plugins/winmmshim/winmm_shim.cpp | 38 |
2 files changed, 29 insertions, 15 deletions
diff --git a/indra/media_plugins/winmmshim/forwarding_api.cpp b/indra/media_plugins/winmmshim/forwarding_api.cpp index 17bffdd850..c2f553dfef 100644 --- a/indra/media_plugins/winmmshim/forwarding_api.cpp +++ b/indra/media_plugins/winmmshim/forwarding_api.cpp @@ -210,9 +210,9 @@ mciGetYieldProc_type mciGetYieldProc_orig; mciLoadCommandResource_type mciLoadCommandResource_orig; mciExecute_type mciExecute_orig; - +// grab pointers to function calls in the real DLL void init_function_pointers(HMODULE winmm_handle) -{ +{ CloseDriver_orig = (CloseDriver_type)::GetProcAddress(winmm_handle, "CloseDriver"); OpenDriver_orig = (OpenDriver_type)::GetProcAddress(winmm_handle, "OpenDriver"); SendDriverMessage_orig = (SendDriverMessage_type)::GetProcAddress(winmm_handle, "SendDriverMessage"); @@ -536,7 +536,7 @@ extern "C" { //MMRESULT WINAPI waveOutWrite( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) //{ // //OutputDebugString(L"waveOutUnprepareHeader\n"); - // return waveOutUnprepareHeader_orig( hwo, pwh, cbwh); + // return waveOutWrite_orig( hwo, pwh, cbwh); //} MMRESULT WINAPI waveOutPause( HWAVEOUT hwo) diff --git a/indra/media_plugins/winmmshim/winmm_shim.cpp b/indra/media_plugins/winmmshim/winmm_shim.cpp index 974744333a..f7df3b19a0 100644 --- a/indra/media_plugins/winmmshim/winmm_shim.cpp +++ b/indra/media_plugins/winmmshim/winmm_shim.cpp @@ -45,21 +45,25 @@ BOOL APIENTRY DllMain( HMODULE hModule, ) { static bool initialized = false; + // do this only once if (!initialized) - { + { // bind to original winmm.dll TCHAR system_path[MAX_PATH]; TCHAR dll_path[MAX_PATH]; ::GetSystemDirectory(system_path, MAX_PATH); + // grab winmm.dll from system path, where it should live wsprintf(dll_path, "%s\\winmm.dll", system_path); HMODULE winmm_handle = ::LoadLibrary(dll_path); if (winmm_handle != NULL) - { + { // we have a dll, let's get out pointers! initialized = true; init_function_pointers(winmm_handle); return true; } + + // failed to initialize real winmm.dll return false; } return true; @@ -68,6 +72,7 @@ BOOL APIENTRY DllMain( HMODULE hModule, extern "C" { + // tracks the requested format for a given waveout buffer struct WaveOutFormat { WaveOutFormat(int bits_per_sample) @@ -80,15 +85,16 @@ extern "C" MMRESULT WINAPI waveOutOpen( LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) { - //OutputDebugString(L"waveOutOpen\n"); - if (pwfx->wFormatTag != WAVE_FORMAT_PCM) - { + if (pwfx->wFormatTag != WAVE_FORMAT_PCM + || (pwfx->wBitsPerSample != 8 && pwfx->wBitsPerSample != 16)) + { // uncompressed 8 and 16 bit sound are the only types we support return WAVERR_BADFORMAT; } + MMRESULT result = waveOutOpen_orig(phwo, uDeviceID, pwfx, dwCallback, dwInstance, fdwOpen); if (result == MMSYSERR_NOERROR && ((fdwOpen & WAVE_FORMAT_QUERY) == 0)) // not just querying for format support - { + { // remember the requested bits per sample, and associate with the given handle WaveOutFormat* wave_outp = new WaveOutFormat(pwfx->wBitsPerSample); sWaveOuts.insert(std::make_pair(*phwo, wave_outp)); } @@ -97,10 +103,9 @@ extern "C" MMRESULT WINAPI waveOutClose( HWAVEOUT hwo) { - //OutputDebugString(L"waveOutClose\n"); wave_out_map_t::iterator found_it = sWaveOuts.find(hwo); if (found_it != sWaveOuts.end()) - { + { // forget what we know about this handle delete found_it->second; sWaveOuts.erase(found_it); } @@ -109,11 +114,10 @@ extern "C" MMRESULT WINAPI waveOutWrite( HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) { - //OutputDebugString(L"waveOutWrite\n"); MMRESULT result = MMSYSERR_NOERROR; if (sMute) - { + { // zero out the audio buffer when muted memset(pwh->lpData, 0, pwh->dwBufferLength); } else @@ -128,6 +132,8 @@ extern "C" char volume = (char)(sVolumeLevel * 127.f); for (unsigned int i = 0; i < pwh->dwBufferLength; i++) { + // unsigned multiply doesn't use most significant bit, so shift by 7 bits + // to get resulting value back into 8 bits pwh->lpData[i] = (pwh->lpData[i] * volume) >> 7; } break; @@ -136,22 +142,30 @@ extern "C" { short volume_16 = (short)(sVolumeLevel * 32767.f); + // copy volume level 4 times into 64 bit MMX register __m64 volume_64 = _mm_set_pi16(volume_16, volume_16, volume_16, volume_16); __m64 *sample_64; + // for everything that can be addressed in 64 bit multiples... for (sample_64 = (__m64*)pwh->lpData; sample_64 < (__m64*)(pwh->lpData + pwh->dwBufferLength); ++sample_64) { + //...multiply the samples by the volume... __m64 scaled_sample = _mm_mulhi_pi16(*sample_64, volume_64); - *sample_64 = _mm_slli_pi16(scaled_sample, 1); //lose 1 bit of precision here + // ...and shift left 1 bit since an unsigned multiple loses the most significant bit + // 0x7FFF * 0x7FFF = 0x3fff0001 + // 0x3fff0001 << 1 = 0x7ffe0002 + // notice that the LSB is always 0...should consider dithering + *sample_64 = _mm_slli_pi16(scaled_sample, 1); } + // the captain has turned off the MMX sign, you are now free to use floating point registers _mm_empty(); for (short* sample_16 = (short*)sample_64; sample_16 < (short*)(pwh->lpData + pwh->dwBufferLength); ++sample_16) - { + { // finish remaining samples that didn't fit into 64 bit register *sample_16 = (*sample_16 * volume_16) >> 15; } |