diff options
Diffstat (limited to 'indra')
| -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;  						} | 
